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

     1  package decoder
     2  
     3  import (
     4  	"reflect"
     5  	"strconv"
     6  	"unsafe"
     7  
     8  	"github.com/trim21/go-phpserialize/internal/errors"
     9  	"github.com/trim21/go-phpserialize/internal/runtime"
    10  )
    11  
    12  type stringWrappedDecoder interface {
    13  	DecodeString(ctx *RuntimeContext, bytes []byte, topCursor int64, p unsafe.Pointer) error
    14  }
    15  
    16  type wrappedStringDecoder struct {
    17  	typ           *runtime.Type
    18  	dec           stringWrappedDecoder
    19  	stringDecoder *stringDecoder
    20  	structName    string
    21  	fieldName     string
    22  	isPtrType     bool
    23  }
    24  
    25  func newWrappedStringDecoder(typ *runtime.Type, dec Decoder, structName, fieldName string) (Decoder, error) {
    26  	var innerDec stringWrappedDecoder
    27  	switch v := dec.(type) {
    28  	case *boolDecoder:
    29  		innerDec = newStringBoolDecoder(structName, fieldName)
    30  	case *floatDecoder:
    31  		innerDec = newStringFloatDecoder(structName, fieldName, v)
    32  	case *uintDecoder:
    33  		innerDec = newStringUintDecoder(structName, fieldName, v)
    34  	case *intDecoder:
    35  		innerDec = newStringIntDecoder(structName, fieldName, v)
    36  	case *ptrDecoder:
    37  		err := v.wrapString()
    38  		return dec, err
    39  	default:
    40  		return nil, &errors.UnsupportedTypeError{Type: runtime.RType2Type(typ)}
    41  	}
    42  
    43  	return &wrappedStringDecoder{
    44  		typ:           typ,
    45  		dec:           innerDec,
    46  		stringDecoder: newStringDecoder(structName, fieldName),
    47  		structName:    structName,
    48  		fieldName:     fieldName,
    49  		isPtrType:     typ.Kind() == reflect.Ptr,
    50  	}, nil
    51  }
    52  
    53  func (d *wrappedStringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
    54  	bytes, c, err := d.stringDecoder.decodeByte(ctx.Buf, cursor)
    55  	if err != nil {
    56  		return 0, err
    57  	}
    58  	if bytes == nil {
    59  		if d.isPtrType {
    60  			*(*unsafe.Pointer)(p) = nil
    61  		}
    62  		return c, nil
    63  	}
    64  
    65  	if err := d.dec.DecodeString(ctx, bytes, cursor, p); err != nil {
    66  		return 0, err
    67  	}
    68  	return c, nil
    69  }
    70  
    71  func newStringBoolDecoder(structName, fieldName string) *stringBoolDecoder {
    72  	return &stringBoolDecoder{}
    73  }
    74  
    75  var _ stringWrappedDecoder = (*stringBoolDecoder)(nil)
    76  
    77  type stringBoolDecoder struct {
    78  }
    79  
    80  func (s stringBoolDecoder) DecodeString(ctx *RuntimeContext, bytes []byte, topCursor int64, p unsafe.Pointer) error {
    81  	str := *(*string)(unsafe.Pointer(&bytes))
    82  
    83  	value, err := strconv.ParseBool(str)
    84  	if err != nil {
    85  		return errors.ErrSyntax(err.Error(), topCursor)
    86  	}
    87  
    88  	if value {
    89  		**(**bool)(unsafe.Pointer(&p)) = true
    90  	} else {
    91  		**(**bool)(unsafe.Pointer(&p)) = false
    92  	}
    93  
    94  	return nil
    95  }
    96  
    97  var _ stringWrappedDecoder = (*stringFloatDecoder)(nil)
    98  
    99  func newStringFloatDecoder(structName, fieldName string, dec *floatDecoder) *stringFloatDecoder {
   100  	return &stringFloatDecoder{floatDecoder: dec}
   101  }
   102  
   103  type stringFloatDecoder struct {
   104  	floatDecoder *floatDecoder
   105  }
   106  
   107  func (d stringFloatDecoder) DecodeString(ctx *RuntimeContext, bytes []byte, topCursor int64, p unsafe.Pointer) error {
   108  	_, err := d.floatDecoder.processBytes(bytes, topCursor, p)
   109  	return err
   110  }
   111  
   112  var _ stringWrappedDecoder = (*stringUintDecoder)(nil)
   113  
   114  func newStringUintDecoder(structName, fieldName string, dec *uintDecoder) *stringUintDecoder {
   115  	return &stringUintDecoder{uintDecoder: dec}
   116  }
   117  
   118  type stringUintDecoder struct {
   119  	uintDecoder *uintDecoder
   120  }
   121  
   122  func (d stringUintDecoder) DecodeString(ctx *RuntimeContext, bytes []byte, topCursor int64, p unsafe.Pointer) error {
   123  	_, err := d.uintDecoder.processBytes(bytes, topCursor, p)
   124  	return err
   125  }
   126  
   127  var _ stringWrappedDecoder = (*stringIntDecoder)(nil)
   128  
   129  func newStringIntDecoder(structName string, fieldName string, decoder *intDecoder) *stringIntDecoder {
   130  	return &stringIntDecoder{intDecoder: decoder}
   131  }
   132  
   133  type stringIntDecoder struct {
   134  	intDecoder *intDecoder
   135  }
   136  
   137  func (d *stringIntDecoder) DecodeString(ctx *RuntimeContext, bytes []byte, topCursor int64, p unsafe.Pointer) error {
   138  	_, err := d.intDecoder.processBytes(bytes, topCursor, p)
   139  	return err
   140  }
   141  
   142  func (d *ptrDecoder) wrapString() error {
   143  	var err error
   144  	d.dec, err = newWrappedStringDecoder(d.typ, d.dec, d.structName, d.fieldName)
   145  	return err
   146  }