github.com/trim21/go-phpserialize@v0.0.22-0.20240301204449-2fca0319b3f0/internal/decoder/interface.go (about)

     1  package decoder
     2  
     3  import (
     4  	"bytes"
     5  	"reflect"
     6  	"unsafe"
     7  
     8  	"github.com/trim21/go-phpserialize/internal/errors"
     9  	"github.com/trim21/go-phpserialize/internal/runtime"
    10  )
    11  
    12  type interfaceDecoder struct {
    13  	typ              *runtime.Type
    14  	structName       string
    15  	fieldName        string
    16  	sliceDecoder     *sliceDecoder
    17  	mapArrayDecoder  *mapDecoder
    18  	mapClassDecoder  *mapDecoder
    19  	floatDecoder     *floatDecoder
    20  	stringDecoder    *stringDecoder
    21  	intDecode        *intDecoder
    22  	mapAnyKeyDecoder *mapKeyDecoder
    23  }
    24  
    25  func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
    26  	ifaceDecoder := &interfaceDecoder{
    27  		typ:           emptyInterfaceType,
    28  		structName:    structName,
    29  		fieldName:     fieldName,
    30  		floatDecoder:  newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { *(*any)(p) = v }),
    31  		intDecode:     newIntDecoder(interfaceIntType, structName, fieldName, func(p unsafe.Pointer, v int64) { *(*any)(p) = v }),
    32  		stringDecoder: newStringDecoder(structName, fieldName),
    33  	}
    34  
    35  	ifaceDecoder.mapAnyKeyDecoder = newInterfaceMapKeyDecoder(
    36  		newIntDecoder(interfaceIntType, structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int64)(p) = v }),
    37  		ifaceDecoder.stringDecoder)
    38  
    39  	ifaceDecoder.sliceDecoder = newSliceDecoder(
    40  		ifaceDecoder,
    41  		emptyInterfaceType,
    42  		emptyInterfaceType.Size(),
    43  		structName, fieldName,
    44  	)
    45  
    46  	ifaceDecoder.mapClassDecoder = newMapDecoder(
    47  		interfaceClassMapType,
    48  		stringType,
    49  		ifaceDecoder.stringDecoder,
    50  		interfaceClassMapType.Elem(),
    51  		ifaceDecoder,
    52  		structName,
    53  		fieldName,
    54  	)
    55  
    56  	ifaceDecoder.mapArrayDecoder = newMapDecoder(
    57  		interfaceMapType,
    58  		emptyInterfaceType,
    59  		ifaceDecoder.mapAnyKeyDecoder,
    60  		interfaceMapType.Elem(),
    61  		ifaceDecoder,
    62  		structName,
    63  		fieldName,
    64  	)
    65  	return ifaceDecoder
    66  }
    67  
    68  func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder {
    69  	emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
    70  	stringDecoder := newStringDecoder(structName, fieldName)
    71  	return &interfaceDecoder{
    72  		typ:        typ,
    73  		structName: structName,
    74  		fieldName:  fieldName,
    75  		sliceDecoder: newSliceDecoder(
    76  			emptyIfaceDecoder,
    77  			emptyInterfaceType,
    78  			emptyInterfaceType.Size(),
    79  			structName, fieldName,
    80  		),
    81  		mapArrayDecoder: newMapDecoder(
    82  			interfaceMapType,
    83  			emptyInterfaceType,
    84  			emptyIfaceDecoder.mapAnyKeyDecoder,
    85  			interfaceMapType.Elem(),
    86  			emptyIfaceDecoder,
    87  			structName,
    88  			fieldName,
    89  		),
    90  		floatDecoder:     emptyIfaceDecoder.floatDecoder,
    91  		stringDecoder:    stringDecoder,
    92  		intDecode:        emptyIfaceDecoder.intDecode,
    93  		mapClassDecoder:  emptyIfaceDecoder.mapClassDecoder,
    94  		mapAnyKeyDecoder: emptyIfaceDecoder.mapAnyKeyDecoder,
    95  	}
    96  }
    97  
    98  var (
    99  	stringType            = runtime.Type2RType(reflect.TypeOf((*string)(nil)).Elem())
   100  	emptyInterfaceType    = runtime.Type2RType(reflect.TypeOf((*any)(nil)).Elem())
   101  	interfaceMapType      = runtime.Type2RType(reflect.TypeOf((*map[any]any)(nil)).Elem())
   102  	interfaceClassMapType = runtime.Type2RType(reflect.TypeOf((*map[string]any)(nil)).Elem())
   103  	interfaceIntType      = runtime.Type2RType(reflect.TypeOf((*int64)(nil))).Elem()
   104  )
   105  
   106  func decodePHPUnmarshaler(buf []byte, cursor, depth int64, unmarshaler Unmarshaler, p unsafe.Pointer) (int64, error) {
   107  	start := cursor
   108  	end, err := skipValue(buf, cursor, depth)
   109  	if err != nil {
   110  		return 0, err
   111  	}
   112  	src := buf[start:end]
   113  	if bytes.Equal(src, nullbytes) {
   114  		*(*unsafe.Pointer)(p) = nil
   115  		return end, nil
   116  	}
   117  	if s, ok := unquoteBytes(src); ok {
   118  		src = s
   119  	}
   120  	if err := unmarshaler.UnmarshalPHP(src); err != nil {
   121  		return 0, err
   122  	}
   123  	return end, nil
   124  }
   125  
   126  type emptyInterface struct {
   127  	typ *runtime.Type
   128  	ptr unsafe.Pointer
   129  }
   130  
   131  func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError {
   132  	return &errors.UnmarshalTypeError{
   133  		Value:  typ.String(),
   134  		Type:   typ,
   135  		Offset: offset,
   136  		Struct: d.structName,
   137  		Field:  d.fieldName,
   138  	}
   139  }
   140  
   141  func (d *interfaceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
   142  	buf := ctx.Buf
   143  
   144  	runtimeInterfaceValue := *(*any)(unsafe.Pointer(&emptyInterface{typ: d.typ, ptr: p}))
   145  	rv := reflect.ValueOf(runtimeInterfaceValue)
   146  	if rv.NumMethod() > 0 && rv.CanInterface() {
   147  		if u, ok := rv.Interface().(Unmarshaler); ok {
   148  			return decodePHPUnmarshaler(buf, cursor, depth, u, p)
   149  		}
   150  		if buf[cursor] == 'N' {
   151  			if err := validateNull(buf, cursor); err != nil {
   152  				return 0, err
   153  			}
   154  			cursor += 2
   155  			**(**any)(unsafe.Pointer(&p)) = nil
   156  			return cursor, nil
   157  		}
   158  		return 0, d.errUnmarshalType(rv.Type(), cursor)
   159  	}
   160  
   161  	iface := rv.Interface()
   162  	ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface))
   163  	typ := ifaceHeader.typ
   164  	if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
   165  		// concrete type is empty interface
   166  		return d.decodeEmptyInterface(ctx, cursor, depth, p)
   167  	}
   168  	if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
   169  		return d.decodeEmptyInterface(ctx, cursor, depth, p)
   170  	}
   171  	if buf[cursor] == 'N' {
   172  		if err := validateNull(buf, cursor); err != nil {
   173  			return 0, err
   174  		}
   175  		cursor += 2
   176  		**(**any)(unsafe.Pointer(&p)) = nil
   177  		return cursor, nil
   178  	}
   179  	decoder, err := CompileToGetDecoder(typ)
   180  	if err != nil {
   181  		return 0, err
   182  	}
   183  	return decoder.Decode(ctx, cursor, depth, ifaceHeader.ptr)
   184  }
   185  
   186  func (d *interfaceDecoder) decodeEmptyInterface(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
   187  	buf := ctx.Buf
   188  	switch buf[cursor] {
   189  	case 'O':
   190  		var v map[string]any
   191  		ptr := unsafe.Pointer(&v)
   192  		cursor, err := d.mapClassDecoder.Decode(ctx, cursor, depth, ptr)
   193  		if err != nil {
   194  			return 0, err
   195  		}
   196  		**(**any)(unsafe.Pointer(&p)) = v
   197  		return cursor, nil
   198  	case 'a':
   199  		var v map[any]any
   200  		ptr := unsafe.Pointer(&v)
   201  		cursor, err := d.mapArrayDecoder.Decode(ctx, cursor, depth, ptr)
   202  		if err != nil {
   203  			return 0, err
   204  		}
   205  		**(**any)(unsafe.Pointer(&p)) = v
   206  		return cursor, nil
   207  	case 'd': // with op
   208  		return d.floatDecoder.Decode(ctx, cursor, depth, p)
   209  	case 's':
   210  		cursor++
   211  		b, end, err := readString(buf, cursor)
   212  		if err != nil {
   213  			return 0, err
   214  		}
   215  		*(*any)(p) = string(b)
   216  		return end, nil
   217  	case 'i': // with op
   218  		return d.intDecode.Decode(ctx, cursor, depth, p)
   219  	case 'b':
   220  		v, err := readBool(buf, cursor)
   221  		if err != nil {
   222  			return 0, err
   223  		}
   224  
   225  		if v {
   226  			**(**any)(unsafe.Pointer(&p)) = true
   227  		} else {
   228  			**(**any)(unsafe.Pointer(&p)) = false
   229  		}
   230  
   231  		return cursor + 3, nil
   232  	case 'N':
   233  		if err := validateNull(buf, cursor); err != nil {
   234  			return 0, err
   235  		}
   236  		cursor += 2
   237  		**(**any)(unsafe.Pointer(&p)) = nil
   238  		return cursor, nil
   239  	}
   240  	return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
   241  }
   242  
   243  type mapKeyDecoder struct {
   244  	strDecoder *stringDecoder
   245  	intDecoder *intDecoder
   246  }
   247  
   248  func (d *mapKeyDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
   249  	buf := ctx.Buf
   250  
   251  	switch buf[cursor] {
   252  	case 's':
   253  		var v string
   254  		ptr := unsafe.Pointer(&v)
   255  		cursor, err := d.strDecoder.Decode(ctx, cursor, depth, ptr)
   256  		if err != nil {
   257  			return 0, err
   258  		}
   259  		*(*any)(p) = v
   260  		return cursor, nil
   261  	// string key
   262  	case 'i':
   263  		var v int64
   264  		ptr := unsafe.Pointer(&v)
   265  		cursor, err := d.intDecoder.Decode(ctx, cursor, depth, ptr)
   266  		if err != nil {
   267  			return 0, err
   268  		}
   269  		*(*any)(p) = v
   270  		return cursor, nil
   271  	default:
   272  		return 0, errors.ErrExpected("array key", cursor)
   273  	}
   274  }
   275  
   276  func newInterfaceMapKeyDecoder(intDecoder *intDecoder, stringDecoder *stringDecoder) *mapKeyDecoder {
   277  	return &mapKeyDecoder{intDecoder: intDecoder, strDecoder: stringDecoder}
   278  }