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

     1  package decoder
     2  
     3  import (
     4  	"reflect"
     5  	"unsafe"
     6  
     7  	"github.com/trim21/go-phpserialize/internal/errors"
     8  )
     9  
    10  type stringDecoder struct {
    11  	structName string
    12  	fieldName  string
    13  }
    14  
    15  func newStringDecoder(structName, fieldName string) *stringDecoder {
    16  	return &stringDecoder{
    17  		structName: structName,
    18  		fieldName:  fieldName,
    19  	}
    20  }
    21  
    22  func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *errors.UnmarshalTypeError {
    23  	return &errors.UnmarshalTypeError{
    24  		Value:  typeName,
    25  		Type:   reflect.TypeOf(""),
    26  		Offset: offset,
    27  		Struct: d.structName,
    28  		Field:  d.fieldName,
    29  	}
    30  }
    31  
    32  func (d *stringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
    33  	bytes, c, err := d.decodeByte(ctx.Buf, cursor)
    34  	if err != nil {
    35  		return 0, err
    36  	}
    37  	if bytes == nil {
    38  		return c, nil
    39  	}
    40  	cursor = c
    41  	**(**string)(unsafe.Pointer(&p)) = *(*string)(unsafe.Pointer(&bytes))
    42  	return cursor, nil
    43  }
    44  
    45  var (
    46  	hexToInt = [256]int{
    47  		'0': 0,
    48  		'1': 1,
    49  		'2': 2,
    50  		'3': 3,
    51  		'4': 4,
    52  		'5': 5,
    53  		'6': 6,
    54  		'7': 7,
    55  		'8': 8,
    56  		'9': 9,
    57  		'A': 10,
    58  		'B': 11,
    59  		'C': 12,
    60  		'D': 13,
    61  		'E': 14,
    62  		'F': 15,
    63  		'a': 10,
    64  		'b': 11,
    65  		'c': 12,
    66  		'd': 13,
    67  		'e': 14,
    68  		'f': 15,
    69  	}
    70  )
    71  
    72  func unicodeToRune(code []byte) rune {
    73  	var r rune
    74  	for i := 0; i < len(code); i++ {
    75  		r = r*16 + rune(hexToInt[code[i]])
    76  	}
    77  	return r
    78  }
    79  
    80  func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
    81  	switch buf[cursor] {
    82  	case 'n':
    83  		if err := validateNull(buf, cursor); err != nil {
    84  			return nil, 0, err
    85  		}
    86  		cursor += 2
    87  		return nil, cursor, nil
    88  	case 'b':
    89  		return nil, 0, d.errUnmarshalType("bool", cursor)
    90  	case 'd':
    91  		return nil, 0, d.errUnmarshalType("float", cursor)
    92  	case 's':
    93  		cursor++
    94  		break
    95  	case 'i':
    96  		return nil, 0, d.errUnmarshalType("number", cursor)
    97  		// read int as string
    98  	default:
    99  		return nil, 0, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
   100  	}
   101  
   102  	s, end, err := readString(buf, cursor)
   103  	if err != nil {
   104  		return nil, 0, err
   105  	}
   106  
   107  	return s, end, nil
   108  }