github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/packages/rubygems/marshal.go (about)

     1  // Copyright 2023 The GitBundle Inc. All rights reserved.
     2  // Copyright 2017 The Gitea Authors. All rights reserved.
     3  // Use of this source code is governed by a MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package rubygems
     7  
     8  import (
     9  	"bufio"
    10  	"bytes"
    11  	"errors"
    12  	"io"
    13  	"reflect"
    14  )
    15  
    16  const (
    17  	majorVersion = 4
    18  	minorVersion = 8
    19  
    20  	typeNil         = '0'
    21  	typeTrue        = 'T'
    22  	typeFalse       = 'F'
    23  	typeFixnum      = 'i'
    24  	typeString      = '"'
    25  	typeSymbol      = ':'
    26  	typeSymbolLink  = ';'
    27  	typeArray       = '['
    28  	typeIVar        = 'I'
    29  	typeUserMarshal = 'U'
    30  	typeUserDef     = 'u'
    31  	typeObject      = 'o'
    32  )
    33  
    34  var (
    35  	// ErrUnsupportedType indicates an unsupported type
    36  	ErrUnsupportedType = errors.New("Type is unsupported")
    37  	// ErrInvalidIntRange indicates an invalid number range
    38  	ErrInvalidIntRange = errors.New("Number is not in valid range")
    39  )
    40  
    41  // RubyUserMarshal is a Ruby object that has a marshal_load function.
    42  type RubyUserMarshal struct {
    43  	Name  string
    44  	Value interface{}
    45  }
    46  
    47  // RubyUserDef is a Ruby object that has a _load function.
    48  type RubyUserDef struct {
    49  	Name  string
    50  	Value interface{}
    51  }
    52  
    53  // RubyObject is a default Ruby object.
    54  type RubyObject struct {
    55  	Name   string
    56  	Member map[string]interface{}
    57  }
    58  
    59  // MarshalEncoder mimics Rubys Marshal class.
    60  // Note: Only supports types used by the RubyGems package registry.
    61  type MarshalEncoder struct {
    62  	w       *bufio.Writer
    63  	symbols map[string]int
    64  }
    65  
    66  // NewMarshalEncoder creates a new MarshalEncoder
    67  func NewMarshalEncoder(w io.Writer) *MarshalEncoder {
    68  	return &MarshalEncoder{
    69  		w:       bufio.NewWriter(w),
    70  		symbols: map[string]int{},
    71  	}
    72  }
    73  
    74  // Encode encodes the given type
    75  func (e *MarshalEncoder) Encode(v interface{}) error {
    76  	if _, err := e.w.Write([]byte{majorVersion, minorVersion}); err != nil {
    77  		return err
    78  	}
    79  
    80  	if err := e.marshal(v); err != nil {
    81  		return err
    82  	}
    83  
    84  	return e.w.Flush()
    85  }
    86  
    87  func (e *MarshalEncoder) marshal(v interface{}) error {
    88  	if v == nil {
    89  		return e.marshalNil()
    90  	}
    91  
    92  	val := reflect.ValueOf(v)
    93  	typ := reflect.TypeOf(v)
    94  
    95  	if typ.Kind() == reflect.Ptr {
    96  		val = val.Elem()
    97  		typ = typ.Elem()
    98  	}
    99  
   100  	switch typ.Kind() {
   101  	case reflect.Bool:
   102  		return e.marshalBool(val.Bool())
   103  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
   104  		return e.marshalInt(val.Int())
   105  	case reflect.String:
   106  		return e.marshalString(val.String())
   107  	case reflect.Slice, reflect.Array:
   108  		return e.marshalArray(val)
   109  	}
   110  
   111  	switch typ.Name() {
   112  	case "RubyUserMarshal":
   113  		return e.marshalUserMarshal(val.Interface().(RubyUserMarshal))
   114  	case "RubyUserDef":
   115  		return e.marshalUserDef(val.Interface().(RubyUserDef))
   116  	case "RubyObject":
   117  		return e.marshalObject(val.Interface().(RubyObject))
   118  	}
   119  
   120  	return ErrUnsupportedType
   121  }
   122  
   123  func (e *MarshalEncoder) marshalNil() error {
   124  	return e.w.WriteByte(typeNil)
   125  }
   126  
   127  func (e *MarshalEncoder) marshalBool(b bool) error {
   128  	if b {
   129  		return e.w.WriteByte(typeTrue)
   130  	}
   131  	return e.w.WriteByte(typeFalse)
   132  }
   133  
   134  func (e *MarshalEncoder) marshalInt(i int64) error {
   135  	if err := e.w.WriteByte(typeFixnum); err != nil {
   136  		return err
   137  	}
   138  
   139  	return e.marshalIntInternal(i)
   140  }
   141  
   142  func (e *MarshalEncoder) marshalIntInternal(i int64) error {
   143  	if i == 0 {
   144  		return e.w.WriteByte(0)
   145  	} else if 0 < i && i < 123 {
   146  		return e.w.WriteByte(byte(i + 5))
   147  	} else if -124 < i && i <= -1 {
   148  		return e.w.WriteByte(byte(i - 5))
   149  	}
   150  
   151  	var len int
   152  	if 122 < i && i <= 0xff {
   153  		len = 1
   154  	} else if 0xff < i && i <= 0xffff {
   155  		len = 2
   156  	} else if 0xffff < i && i <= 0xffffff {
   157  		len = 3
   158  	} else if 0xffffff < i && i <= 0x3fffffff {
   159  		len = 4
   160  	} else if -0x100 <= i && i < -123 {
   161  		len = -1
   162  	} else if -0x10000 <= i && i < -0x100 {
   163  		len = -2
   164  	} else if -0x1000000 <= i && i < -0x100000 {
   165  		len = -3
   166  	} else if -0x40000000 <= i && i < -0x1000000 {
   167  		len = -4
   168  	} else {
   169  		return ErrInvalidIntRange
   170  	}
   171  
   172  	if err := e.w.WriteByte(byte(len)); err != nil {
   173  		return err
   174  	}
   175  	if len < 0 {
   176  		len = -len
   177  	}
   178  
   179  	for c := 0; c < len; c++ {
   180  		if err := e.w.WriteByte(byte(i >> uint(8*c) & 0xff)); err != nil {
   181  			return err
   182  		}
   183  	}
   184  
   185  	return nil
   186  }
   187  
   188  func (e *MarshalEncoder) marshalString(str string) error {
   189  	if err := e.w.WriteByte(typeIVar); err != nil {
   190  		return err
   191  	}
   192  
   193  	if err := e.marshalRawString(str); err != nil {
   194  		return err
   195  	}
   196  
   197  	if err := e.marshalIntInternal(1); err != nil {
   198  		return err
   199  	}
   200  
   201  	if err := e.marshalSymbol("E"); err != nil {
   202  		return err
   203  	}
   204  
   205  	return e.marshalBool(true)
   206  }
   207  
   208  func (e *MarshalEncoder) marshalRawString(str string) error {
   209  	if err := e.w.WriteByte(typeString); err != nil {
   210  		return err
   211  	}
   212  
   213  	if err := e.marshalIntInternal(int64(len(str))); err != nil {
   214  		return err
   215  	}
   216  
   217  	_, err := e.w.WriteString(str)
   218  	return err
   219  }
   220  
   221  func (e *MarshalEncoder) marshalSymbol(str string) error {
   222  	if index, ok := e.symbols[str]; ok {
   223  		if err := e.w.WriteByte(typeSymbolLink); err != nil {
   224  			return err
   225  		}
   226  		return e.marshalIntInternal(int64(index))
   227  	}
   228  
   229  	e.symbols[str] = len(e.symbols)
   230  
   231  	if err := e.w.WriteByte(typeSymbol); err != nil {
   232  		return err
   233  	}
   234  
   235  	if err := e.marshalIntInternal(int64(len(str))); err != nil {
   236  		return err
   237  	}
   238  
   239  	_, err := e.w.WriteString(str)
   240  	return err
   241  }
   242  
   243  func (e *MarshalEncoder) marshalArray(arr reflect.Value) error {
   244  	if err := e.w.WriteByte(typeArray); err != nil {
   245  		return err
   246  	}
   247  
   248  	len := arr.Len()
   249  
   250  	if err := e.marshalIntInternal(int64(len)); err != nil {
   251  		return err
   252  	}
   253  
   254  	for i := 0; i < len; i++ {
   255  		if err := e.marshal(arr.Index(i).Interface()); err != nil {
   256  			return err
   257  		}
   258  	}
   259  	return nil
   260  }
   261  
   262  func (e *MarshalEncoder) marshalUserMarshal(userMarshal RubyUserMarshal) error {
   263  	if err := e.w.WriteByte(typeUserMarshal); err != nil {
   264  		return err
   265  	}
   266  
   267  	if err := e.marshalSymbol(userMarshal.Name); err != nil {
   268  		return err
   269  	}
   270  
   271  	return e.marshal(userMarshal.Value)
   272  }
   273  
   274  func (e *MarshalEncoder) marshalUserDef(userDef RubyUserDef) error {
   275  	var buf bytes.Buffer
   276  	if err := NewMarshalEncoder(&buf).Encode(userDef.Value); err != nil {
   277  		return err
   278  	}
   279  
   280  	if err := e.w.WriteByte(typeUserDef); err != nil {
   281  		return err
   282  	}
   283  	if err := e.marshalSymbol(userDef.Name); err != nil {
   284  		return err
   285  	}
   286  	if err := e.marshalIntInternal(int64(buf.Len())); err != nil {
   287  		return err
   288  	}
   289  	_, err := e.w.Write(buf.Bytes())
   290  	return err
   291  }
   292  
   293  func (e *MarshalEncoder) marshalObject(obj RubyObject) error {
   294  	if err := e.w.WriteByte(typeObject); err != nil {
   295  		return err
   296  	}
   297  	if err := e.marshalSymbol(obj.Name); err != nil {
   298  		return err
   299  	}
   300  	if err := e.marshalIntInternal(int64(len(obj.Member))); err != nil {
   301  		return err
   302  	}
   303  	for k, v := range obj.Member {
   304  		if err := e.marshalSymbol(k); err != nil {
   305  			return err
   306  		}
   307  		if err := e.marshal(v); err != nil {
   308  			return err
   309  		}
   310  	}
   311  	return nil
   312  }