mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	Noteable additions: - `redefines-builtin-id` forbid variable names that shadow go builtins - `empty-lines` remove unnecessary empty lines that `gofumpt` does not remove for some reason - `superfluous-else` eliminate more superfluous `else` branches Rules are also sorted alphabetically and I cleaned up various parts of `.golangci.yml`.
		
			
				
	
	
		
			312 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			312 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2021 The Gitea Authors. All rights reserved.
 | 
						|
// SPDX-License-Identifier: MIT
 | 
						|
 | 
						|
package rubygems
 | 
						|
 | 
						|
import (
 | 
						|
	"bufio"
 | 
						|
	"bytes"
 | 
						|
	"io"
 | 
						|
	"reflect"
 | 
						|
 | 
						|
	"code.gitea.io/gitea/modules/util"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	majorVersion = 4
 | 
						|
	minorVersion = 8
 | 
						|
 | 
						|
	typeNil         = '0'
 | 
						|
	typeTrue        = 'T'
 | 
						|
	typeFalse       = 'F'
 | 
						|
	typeFixnum      = 'i'
 | 
						|
	typeString      = '"'
 | 
						|
	typeSymbol      = ':'
 | 
						|
	typeSymbolLink  = ';'
 | 
						|
	typeArray       = '['
 | 
						|
	typeIVar        = 'I'
 | 
						|
	typeUserMarshal = 'U'
 | 
						|
	typeUserDef     = 'u'
 | 
						|
	typeObject      = 'o'
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	// ErrUnsupportedType indicates an unsupported type
 | 
						|
	ErrUnsupportedType = util.NewInvalidArgumentErrorf("type is unsupported")
 | 
						|
	// ErrInvalidIntRange indicates an invalid number range
 | 
						|
	ErrInvalidIntRange = util.NewInvalidArgumentErrorf("number is not in valid range")
 | 
						|
)
 | 
						|
 | 
						|
// RubyUserMarshal is a Ruby object that has a marshal_load function.
 | 
						|
type RubyUserMarshal struct {
 | 
						|
	Name  string
 | 
						|
	Value any
 | 
						|
}
 | 
						|
 | 
						|
// RubyUserDef is a Ruby object that has a _load function.
 | 
						|
type RubyUserDef struct {
 | 
						|
	Name  string
 | 
						|
	Value any
 | 
						|
}
 | 
						|
 | 
						|
// RubyObject is a default Ruby object.
 | 
						|
type RubyObject struct {
 | 
						|
	Name   string
 | 
						|
	Member map[string]any
 | 
						|
}
 | 
						|
 | 
						|
// MarshalEncoder mimics Rubys Marshal class.
 | 
						|
// Note: Only supports types used by the RubyGems package registry.
 | 
						|
type MarshalEncoder struct {
 | 
						|
	w       *bufio.Writer
 | 
						|
	symbols map[string]int
 | 
						|
}
 | 
						|
 | 
						|
// NewMarshalEncoder creates a new MarshalEncoder
 | 
						|
func NewMarshalEncoder(w io.Writer) *MarshalEncoder {
 | 
						|
	return &MarshalEncoder{
 | 
						|
		w:       bufio.NewWriter(w),
 | 
						|
		symbols: map[string]int{},
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Encode encodes the given type
 | 
						|
func (e *MarshalEncoder) Encode(v any) error {
 | 
						|
	if _, err := e.w.Write([]byte{majorVersion, minorVersion}); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := e.marshal(v); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	return e.w.Flush()
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshal(v any) error {
 | 
						|
	if v == nil {
 | 
						|
		return e.marshalNil()
 | 
						|
	}
 | 
						|
 | 
						|
	val := reflect.ValueOf(v)
 | 
						|
	typ := reflect.TypeOf(v)
 | 
						|
 | 
						|
	if typ.Kind() == reflect.Ptr {
 | 
						|
		val = val.Elem()
 | 
						|
		typ = typ.Elem()
 | 
						|
	}
 | 
						|
 | 
						|
	switch typ.Kind() {
 | 
						|
	case reflect.Bool:
 | 
						|
		return e.marshalBool(val.Bool())
 | 
						|
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
 | 
						|
		return e.marshalInt(val.Int())
 | 
						|
	case reflect.String:
 | 
						|
		return e.marshalString(val.String())
 | 
						|
	case reflect.Slice, reflect.Array:
 | 
						|
		return e.marshalArray(val)
 | 
						|
	}
 | 
						|
 | 
						|
	switch typ.Name() {
 | 
						|
	case "RubyUserMarshal":
 | 
						|
		return e.marshalUserMarshal(val.Interface().(RubyUserMarshal))
 | 
						|
	case "RubyUserDef":
 | 
						|
		return e.marshalUserDef(val.Interface().(RubyUserDef))
 | 
						|
	case "RubyObject":
 | 
						|
		return e.marshalObject(val.Interface().(RubyObject))
 | 
						|
	}
 | 
						|
 | 
						|
	return ErrUnsupportedType
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalNil() error {
 | 
						|
	return e.w.WriteByte(typeNil)
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalBool(b bool) error {
 | 
						|
	if b {
 | 
						|
		return e.w.WriteByte(typeTrue)
 | 
						|
	}
 | 
						|
	return e.w.WriteByte(typeFalse)
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalInt(i int64) error {
 | 
						|
	if err := e.w.WriteByte(typeFixnum); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	return e.marshalIntInternal(i)
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalIntInternal(i int64) error {
 | 
						|
	if i == 0 {
 | 
						|
		return e.w.WriteByte(0)
 | 
						|
	} else if 0 < i && i < 123 {
 | 
						|
		return e.w.WriteByte(byte(i + 5))
 | 
						|
	} else if -124 < i && i <= -1 {
 | 
						|
		return e.w.WriteByte(byte(i - 5))
 | 
						|
	}
 | 
						|
 | 
						|
	var length int
 | 
						|
	if 122 < i && i <= 0xff {
 | 
						|
		length = 1
 | 
						|
	} else if 0xff < i && i <= 0xffff {
 | 
						|
		length = 2
 | 
						|
	} else if 0xffff < i && i <= 0xffffff {
 | 
						|
		length = 3
 | 
						|
	} else if 0xffffff < i && i <= 0x3fffffff {
 | 
						|
		length = 4
 | 
						|
	} else if -0x100 <= i && i < -123 {
 | 
						|
		length = -1
 | 
						|
	} else if -0x10000 <= i && i < -0x100 {
 | 
						|
		length = -2
 | 
						|
	} else if -0x1000000 <= i && i < -0x100000 {
 | 
						|
		length = -3
 | 
						|
	} else if -0x40000000 <= i && i < -0x1000000 {
 | 
						|
		length = -4
 | 
						|
	} else {
 | 
						|
		return ErrInvalidIntRange
 | 
						|
	}
 | 
						|
 | 
						|
	if err := e.w.WriteByte(byte(length)); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if length < 0 {
 | 
						|
		length = -length
 | 
						|
	}
 | 
						|
 | 
						|
	for c := 0; c < length; c++ {
 | 
						|
		if err := e.w.WriteByte(byte(i >> uint(8*c) & 0xff)); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalString(str string) error {
 | 
						|
	if err := e.w.WriteByte(typeIVar); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := e.marshalRawString(str); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := e.marshalIntInternal(1); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := e.marshalSymbol("E"); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	return e.marshalBool(true)
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalRawString(str string) error {
 | 
						|
	if err := e.w.WriteByte(typeString); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := e.marshalIntInternal(int64(len(str))); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := e.w.WriteString(str)
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalSymbol(str string) error {
 | 
						|
	if index, ok := e.symbols[str]; ok {
 | 
						|
		if err := e.w.WriteByte(typeSymbolLink); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		return e.marshalIntInternal(int64(index))
 | 
						|
	}
 | 
						|
 | 
						|
	e.symbols[str] = len(e.symbols)
 | 
						|
 | 
						|
	if err := e.w.WriteByte(typeSymbol); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := e.marshalIntInternal(int64(len(str))); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := e.w.WriteString(str)
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalArray(arr reflect.Value) error {
 | 
						|
	if err := e.w.WriteByte(typeArray); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	length := arr.Len()
 | 
						|
 | 
						|
	if err := e.marshalIntInternal(int64(length)); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	for i := 0; i < length; i++ {
 | 
						|
		if err := e.marshal(arr.Index(i).Interface()); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalUserMarshal(userMarshal RubyUserMarshal) error {
 | 
						|
	if err := e.w.WriteByte(typeUserMarshal); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := e.marshalSymbol(userMarshal.Name); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	return e.marshal(userMarshal.Value)
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalUserDef(userDef RubyUserDef) error {
 | 
						|
	var buf bytes.Buffer
 | 
						|
	if err := NewMarshalEncoder(&buf).Encode(userDef.Value); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := e.w.WriteByte(typeUserDef); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if err := e.marshalSymbol(userDef.Name); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if err := e.marshalIntInternal(int64(buf.Len())); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	_, err := e.w.Write(buf.Bytes())
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
func (e *MarshalEncoder) marshalObject(obj RubyObject) error {
 | 
						|
	if err := e.w.WriteByte(typeObject); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if err := e.marshalSymbol(obj.Name); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if err := e.marshalIntInternal(int64(len(obj.Member))); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	for k, v := range obj.Member {
 | 
						|
		if err := e.marshalSymbol(k); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		if err := e.marshal(v); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 |