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  }