github.com/trim21/go-phpserialize@v0.0.22-0.20240301204449-2fca0319b3f0/internal/decoder/interface.go (about) 1 package decoder 2 3 import ( 4 "bytes" 5 "reflect" 6 "unsafe" 7 8 "github.com/trim21/go-phpserialize/internal/errors" 9 "github.com/trim21/go-phpserialize/internal/runtime" 10 ) 11 12 type interfaceDecoder struct { 13 typ *runtime.Type 14 structName string 15 fieldName string 16 sliceDecoder *sliceDecoder 17 mapArrayDecoder *mapDecoder 18 mapClassDecoder *mapDecoder 19 floatDecoder *floatDecoder 20 stringDecoder *stringDecoder 21 intDecode *intDecoder 22 mapAnyKeyDecoder *mapKeyDecoder 23 } 24 25 func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder { 26 ifaceDecoder := &interfaceDecoder{ 27 typ: emptyInterfaceType, 28 structName: structName, 29 fieldName: fieldName, 30 floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { *(*any)(p) = v }), 31 intDecode: newIntDecoder(interfaceIntType, structName, fieldName, func(p unsafe.Pointer, v int64) { *(*any)(p) = v }), 32 stringDecoder: newStringDecoder(structName, fieldName), 33 } 34 35 ifaceDecoder.mapAnyKeyDecoder = newInterfaceMapKeyDecoder( 36 newIntDecoder(interfaceIntType, structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int64)(p) = v }), 37 ifaceDecoder.stringDecoder) 38 39 ifaceDecoder.sliceDecoder = newSliceDecoder( 40 ifaceDecoder, 41 emptyInterfaceType, 42 emptyInterfaceType.Size(), 43 structName, fieldName, 44 ) 45 46 ifaceDecoder.mapClassDecoder = newMapDecoder( 47 interfaceClassMapType, 48 stringType, 49 ifaceDecoder.stringDecoder, 50 interfaceClassMapType.Elem(), 51 ifaceDecoder, 52 structName, 53 fieldName, 54 ) 55 56 ifaceDecoder.mapArrayDecoder = newMapDecoder( 57 interfaceMapType, 58 emptyInterfaceType, 59 ifaceDecoder.mapAnyKeyDecoder, 60 interfaceMapType.Elem(), 61 ifaceDecoder, 62 structName, 63 fieldName, 64 ) 65 return ifaceDecoder 66 } 67 68 func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder { 69 emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName) 70 stringDecoder := newStringDecoder(structName, fieldName) 71 return &interfaceDecoder{ 72 typ: typ, 73 structName: structName, 74 fieldName: fieldName, 75 sliceDecoder: newSliceDecoder( 76 emptyIfaceDecoder, 77 emptyInterfaceType, 78 emptyInterfaceType.Size(), 79 structName, fieldName, 80 ), 81 mapArrayDecoder: newMapDecoder( 82 interfaceMapType, 83 emptyInterfaceType, 84 emptyIfaceDecoder.mapAnyKeyDecoder, 85 interfaceMapType.Elem(), 86 emptyIfaceDecoder, 87 structName, 88 fieldName, 89 ), 90 floatDecoder: emptyIfaceDecoder.floatDecoder, 91 stringDecoder: stringDecoder, 92 intDecode: emptyIfaceDecoder.intDecode, 93 mapClassDecoder: emptyIfaceDecoder.mapClassDecoder, 94 mapAnyKeyDecoder: emptyIfaceDecoder.mapAnyKeyDecoder, 95 } 96 } 97 98 var ( 99 stringType = runtime.Type2RType(reflect.TypeOf((*string)(nil)).Elem()) 100 emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*any)(nil)).Elem()) 101 interfaceMapType = runtime.Type2RType(reflect.TypeOf((*map[any]any)(nil)).Elem()) 102 interfaceClassMapType = runtime.Type2RType(reflect.TypeOf((*map[string]any)(nil)).Elem()) 103 interfaceIntType = runtime.Type2RType(reflect.TypeOf((*int64)(nil))).Elem() 104 ) 105 106 func decodePHPUnmarshaler(buf []byte, cursor, depth int64, unmarshaler Unmarshaler, p unsafe.Pointer) (int64, error) { 107 start := cursor 108 end, err := skipValue(buf, cursor, depth) 109 if err != nil { 110 return 0, err 111 } 112 src := buf[start:end] 113 if bytes.Equal(src, nullbytes) { 114 *(*unsafe.Pointer)(p) = nil 115 return end, nil 116 } 117 if s, ok := unquoteBytes(src); ok { 118 src = s 119 } 120 if err := unmarshaler.UnmarshalPHP(src); err != nil { 121 return 0, err 122 } 123 return end, nil 124 } 125 126 type emptyInterface struct { 127 typ *runtime.Type 128 ptr unsafe.Pointer 129 } 130 131 func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError { 132 return &errors.UnmarshalTypeError{ 133 Value: typ.String(), 134 Type: typ, 135 Offset: offset, 136 Struct: d.structName, 137 Field: d.fieldName, 138 } 139 } 140 141 func (d *interfaceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 142 buf := ctx.Buf 143 144 runtimeInterfaceValue := *(*any)(unsafe.Pointer(&emptyInterface{typ: d.typ, ptr: p})) 145 rv := reflect.ValueOf(runtimeInterfaceValue) 146 if rv.NumMethod() > 0 && rv.CanInterface() { 147 if u, ok := rv.Interface().(Unmarshaler); ok { 148 return decodePHPUnmarshaler(buf, cursor, depth, u, p) 149 } 150 if buf[cursor] == 'N' { 151 if err := validateNull(buf, cursor); err != nil { 152 return 0, err 153 } 154 cursor += 2 155 **(**any)(unsafe.Pointer(&p)) = nil 156 return cursor, nil 157 } 158 return 0, d.errUnmarshalType(rv.Type(), cursor) 159 } 160 161 iface := rv.Interface() 162 ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface)) 163 typ := ifaceHeader.typ 164 if ifaceHeader.ptr == nil || d.typ == typ || typ == nil { 165 // concrete type is empty interface 166 return d.decodeEmptyInterface(ctx, cursor, depth, p) 167 } 168 if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr { 169 return d.decodeEmptyInterface(ctx, cursor, depth, p) 170 } 171 if buf[cursor] == 'N' { 172 if err := validateNull(buf, cursor); err != nil { 173 return 0, err 174 } 175 cursor += 2 176 **(**any)(unsafe.Pointer(&p)) = nil 177 return cursor, nil 178 } 179 decoder, err := CompileToGetDecoder(typ) 180 if err != nil { 181 return 0, err 182 } 183 return decoder.Decode(ctx, cursor, depth, ifaceHeader.ptr) 184 } 185 186 func (d *interfaceDecoder) decodeEmptyInterface(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 187 buf := ctx.Buf 188 switch buf[cursor] { 189 case 'O': 190 var v map[string]any 191 ptr := unsafe.Pointer(&v) 192 cursor, err := d.mapClassDecoder.Decode(ctx, cursor, depth, ptr) 193 if err != nil { 194 return 0, err 195 } 196 **(**any)(unsafe.Pointer(&p)) = v 197 return cursor, nil 198 case 'a': 199 var v map[any]any 200 ptr := unsafe.Pointer(&v) 201 cursor, err := d.mapArrayDecoder.Decode(ctx, cursor, depth, ptr) 202 if err != nil { 203 return 0, err 204 } 205 **(**any)(unsafe.Pointer(&p)) = v 206 return cursor, nil 207 case 'd': // with op 208 return d.floatDecoder.Decode(ctx, cursor, depth, p) 209 case 's': 210 cursor++ 211 b, end, err := readString(buf, cursor) 212 if err != nil { 213 return 0, err 214 } 215 *(*any)(p) = string(b) 216 return end, nil 217 case 'i': // with op 218 return d.intDecode.Decode(ctx, cursor, depth, p) 219 case 'b': 220 v, err := readBool(buf, cursor) 221 if err != nil { 222 return 0, err 223 } 224 225 if v { 226 **(**any)(unsafe.Pointer(&p)) = true 227 } else { 228 **(**any)(unsafe.Pointer(&p)) = false 229 } 230 231 return cursor + 3, nil 232 case 'N': 233 if err := validateNull(buf, cursor); err != nil { 234 return 0, err 235 } 236 cursor += 2 237 **(**any)(unsafe.Pointer(&p)) = nil 238 return cursor, nil 239 } 240 return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor) 241 } 242 243 type mapKeyDecoder struct { 244 strDecoder *stringDecoder 245 intDecoder *intDecoder 246 } 247 248 func (d *mapKeyDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 249 buf := ctx.Buf 250 251 switch buf[cursor] { 252 case 's': 253 var v string 254 ptr := unsafe.Pointer(&v) 255 cursor, err := d.strDecoder.Decode(ctx, cursor, depth, ptr) 256 if err != nil { 257 return 0, err 258 } 259 *(*any)(p) = v 260 return cursor, nil 261 // string key 262 case 'i': 263 var v int64 264 ptr := unsafe.Pointer(&v) 265 cursor, err := d.intDecoder.Decode(ctx, cursor, depth, ptr) 266 if err != nil { 267 return 0, err 268 } 269 *(*any)(p) = v 270 return cursor, nil 271 default: 272 return 0, errors.ErrExpected("array key", cursor) 273 } 274 } 275 276 func newInterfaceMapKeyDecoder(intDecoder *intDecoder, stringDecoder *stringDecoder) *mapKeyDecoder { 277 return &mapKeyDecoder{intDecoder: intDecoder, strDecoder: stringDecoder} 278 }