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 }