github.com/trim21/go-phpserialize@v0.0.22-0.20240301204449-2fca0319b3f0/internal/decoder/bytes.go (about) 1 package decoder 2 3 import ( 4 "unsafe" 5 6 "github.com/trim21/go-phpserialize/internal/errors" 7 "github.com/trim21/go-phpserialize/internal/runtime" 8 ) 9 10 type bytesDecoder struct { 11 typ *runtime.Type 12 sliceDecoder Decoder 13 stringDecoder *stringDecoder 14 structName string 15 fieldName string 16 } 17 18 func byteUnmarshalerSliceDecoder(typ *runtime.Type, structName string, fieldName string) Decoder { 19 var unmarshalDecoder Decoder 20 switch { 21 case runtime.PtrTo(typ).Implements(unmarshalPHPType): 22 unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName) 23 default: 24 unmarshalDecoder, _ = compileUint8(typ, structName, fieldName) 25 } 26 return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName) 27 } 28 29 func newBytesDecoder(typ *runtime.Type, structName string, fieldName string) *bytesDecoder { 30 return &bytesDecoder{ 31 typ: typ, 32 sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName), 33 stringDecoder: newStringDecoder(structName, fieldName), 34 structName: structName, 35 fieldName: fieldName, 36 } 37 } 38 39 func (d *bytesDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 40 bytes, c, err := d.decodeBinary(ctx, cursor, depth, p) 41 if err != nil { 42 return 0, err 43 } 44 if bytes == nil { 45 return c, nil 46 } 47 cursor = c 48 *(*[]byte)(p) = bytes 49 return cursor, nil 50 } 51 52 func (d *bytesDecoder) decodeBinary(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) { 53 buf := ctx.Buf 54 if buf[cursor] == 'a' { 55 if d.sliceDecoder == nil { 56 return nil, 0, &errors.UnmarshalTypeError{ 57 Type: runtime.RType2Type(d.typ), 58 Offset: cursor, 59 } 60 } 61 c, err := d.sliceDecoder.Decode(ctx, cursor, depth, p) 62 if err != nil { 63 return nil, 0, err 64 } 65 return nil, c, nil 66 } 67 return d.stringDecoder.decodeByte(buf, cursor) 68 }