github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/jsoni/any.go (about) 1 package jsoni 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io" 8 "reflect" 9 "strconv" 10 "unsafe" 11 12 "github.com/modern-go/reflect2" 13 ) 14 15 // Any generic object representation. 16 // The lazy json implementation holds []byte and parse lazily. 17 type Any interface { 18 LastError() error 19 ValueType() ValueType 20 MustBeValid() Any 21 ToBool() bool 22 ToInt() int 23 ToInt32() int32 24 ToInt64() int64 25 ToUint() uint 26 ToUint32() uint32 27 ToUint64() uint64 28 ToFloat32() float32 29 ToFloat64() float64 30 ToString() string 31 ToVal(ctx context.Context, val interface{}) 32 Get(path ...interface{}) Any 33 Size() int 34 Keys() []string 35 GetInterface(ctx context.Context) interface{} 36 WriteTo(ctx context.Context, stream *Stream) 37 } 38 39 type baseAny struct{} 40 41 func (any *baseAny) Get(path ...interface{}) Any { 42 return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)} 43 } 44 45 func (any *baseAny) Size() int { return 0 } 46 func (any *baseAny) Keys() []string { return []string{} } 47 func (any *baseAny) ToVal(context.Context, interface{}) { panic("not implemented") } 48 49 // WrapInt32 turn int32 into Any interface 50 func WrapInt32(val int32) Any { return &int32Any{baseAny{}, val} } 51 52 // WrapInt64 turn int64 into Any interface 53 func WrapInt64(val int64) Any { return &int64Any{baseAny{}, val} } 54 55 // WrapUint32 turn uint32 into Any interface 56 func WrapUint32(val uint32) Any { return &uint32Any{baseAny{}, val} } 57 58 // WrapUint64 turn uint64 into Any interface 59 func WrapUint64(val uint64) Any { return &uint64Any{baseAny{}, val} } 60 61 // WrapFloat64 turn float64 into Any interface 62 func WrapFloat64(val float64) Any { return &floatAny{baseAny{}, val} } 63 64 // WrapString turn string into Any interface 65 func WrapString(val string) Any { return &stringAny{baseAny{}, val} } 66 67 // Wrap turn a go object into Any interface 68 func Wrap(val interface{}) Any { 69 if val == nil { 70 return &nilAny{} 71 } 72 asAny, isAny := val.(Any) 73 if isAny { 74 return asAny 75 } 76 typ := reflect2.TypeOf(val) 77 switch typ.Kind() { 78 case reflect.Slice: 79 return wrapArray(val) 80 case reflect.Struct: 81 return wrapStruct(val) 82 case reflect.Map: 83 return wrapMap(val) 84 case reflect.String: 85 return WrapString(val.(string)) 86 case reflect.Int: 87 if strconv.IntSize == 32 { 88 return WrapInt32(int32(val.(int))) 89 } 90 return WrapInt64(int64(val.(int))) 91 case reflect.Int8: 92 return WrapInt32(int32(val.(int8))) 93 case reflect.Int16: 94 return WrapInt32(int32(val.(int16))) 95 case reflect.Int32: 96 return WrapInt32(val.(int32)) 97 case reflect.Int64: 98 return WrapInt64(val.(int64)) 99 case reflect.Uint: 100 if strconv.IntSize == 32 { 101 return WrapUint32(uint32(val.(uint))) 102 } 103 return WrapUint64(uint64(val.(uint))) 104 case reflect.Uintptr: 105 if ptrSize == 32 { 106 return WrapUint32(uint32(val.(uintptr))) 107 } 108 return WrapUint64(uint64(val.(uintptr))) 109 case reflect.Uint8: 110 return WrapUint32(uint32(val.(uint8))) 111 case reflect.Uint16: 112 return WrapUint32(uint32(val.(uint16))) 113 case reflect.Uint32: 114 return WrapUint32(val.(uint32)) 115 case reflect.Uint64: 116 return WrapUint64(val.(uint64)) 117 case reflect.Float32: 118 return WrapFloat64(float64(val.(float32))) 119 case reflect.Float64: 120 return WrapFloat64(val.(float64)) 121 case reflect.Bool: 122 if val.(bool) == true { 123 return &trueAny{} 124 } 125 return &falseAny{} 126 } 127 return &invalidAny{baseAny{}, fmt.Errorf("unsupported type: %v", typ)} 128 } 129 130 // ReadAny read next JSON element as an Any object. It is a better json.RawMessage. 131 func (iter *Iterator) ReadAny() Any { 132 return iter.readAny() 133 } 134 135 func (iter *Iterator) readAny() Any { 136 c := iter.nextToken() 137 switch c { 138 case '"': 139 iter.unreadByte() 140 return &stringAny{baseAny{}, iter.ReadString()} 141 case 'n': 142 iter.skip3Bytes('u', 'l', 'l') // null 143 return &nilAny{} 144 case 't': 145 iter.skip3Bytes('r', 'u', 'e') // true 146 return &trueAny{} 147 case 'f': 148 iter.skip4Bytes('a', 'l', 's', 'e') // false 149 return &falseAny{} 150 case '{': 151 return iter.readObjectAny() 152 case '[': 153 return iter.readArrayAny() 154 case '-': 155 return iter.readNumberAny(false) 156 case 0: 157 return &invalidAny{baseAny{}, errors.New("input is empty")} 158 default: 159 return iter.readNumberAny(true) 160 } 161 } 162 163 func (iter *Iterator) readNumberAny(positive bool) Any { 164 iter.startCapture(iter.head - 1) 165 iter.skipNumber() 166 lazyBuf := iter.stopCapture() 167 return &numberLazyAny{baseAny{}, iter.cfg, lazyBuf, nil} 168 } 169 170 func (iter *Iterator) readObjectAny() Any { 171 iter.startCapture(iter.head - 1) 172 iter.skipObject() 173 lazyBuf := iter.stopCapture() 174 return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil} 175 } 176 177 func (iter *Iterator) readArrayAny() Any { 178 iter.startCapture(iter.head - 1) 179 iter.skipArray() 180 lazyBuf := iter.stopCapture() 181 return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil} 182 } 183 184 func locateObjectField(iter *Iterator, target string) []byte { 185 var found []byte 186 iter.ReadObjectCB(func(iter *Iterator, field string) bool { 187 if field == target { 188 found = iter.SkipAndReturnBytes() 189 return false 190 } 191 iter.Skip() 192 return true 193 }) 194 return found 195 } 196 197 func locateArrayElement(iter *Iterator, target int) []byte { 198 var found []byte 199 n := 0 200 iter.ReadArrayCB(func(iter *Iterator) bool { 201 if n == target { 202 found = iter.SkipAndReturnBytes() 203 return false 204 } 205 iter.Skip() 206 n++ 207 return true 208 }) 209 return found 210 } 211 212 func locatePath(iter *Iterator, path []interface{}) Any { 213 for i, pathKeyObj := range path { 214 switch pathKey := pathKeyObj.(type) { 215 case string: 216 valueBytes := locateObjectField(iter, pathKey) 217 if valueBytes == nil { 218 return newInvalidAny(path[i:]) 219 } 220 iter.ResetBytes(valueBytes) 221 case int: 222 valueBytes := locateArrayElement(iter, pathKey) 223 if valueBytes == nil { 224 return newInvalidAny(path[i:]) 225 } 226 iter.ResetBytes(valueBytes) 227 case int32: 228 if '*' == pathKey { 229 return iter.readAny().Get(path[i:]...) 230 } 231 return newInvalidAny(path[i:]) 232 default: 233 return newInvalidAny(path[i:]) 234 } 235 } 236 if iter.Error != nil && iter.Error != io.EOF { 237 return &invalidAny{baseAny{}, iter.Error} 238 } 239 return iter.readAny() 240 } 241 242 var anyType = PtrElem((*Any)(nil)) 243 244 func createDecoderOfAny(_ *ctx, typ reflect2.Type) ValDecoder { 245 if typ == anyType { 246 return &directAnyCodec{} 247 } 248 if typ.Implements(anyType) { 249 return &anyCodec{valType: typ} 250 } 251 return nil 252 } 253 254 func createEncoderOfAny(_ *ctx, typ reflect2.Type) ValEncoder { 255 if typ == anyType { 256 return &directAnyCodec{} 257 } 258 if typ.Implements(anyType) { 259 return &anyCodec{valType: typ} 260 } 261 return nil 262 } 263 264 type anyCodec struct { 265 valType reflect2.Type 266 } 267 268 func (c *anyCodec) Decode(context.Context, unsafe.Pointer, *Iterator) { panic("not implemented") } 269 270 func (c *anyCodec) Encode(ctx context.Context, ptr unsafe.Pointer, stream *Stream) { 271 obj := c.valType.UnsafeIndirect(ptr) 272 any := obj.(Any) 273 any.WriteTo(ctx, stream) 274 } 275 276 func (c *anyCodec) IsEmpty(_ context.Context, ptr unsafe.Pointer, _ bool) bool { 277 obj := c.valType.UnsafeIndirect(ptr) 278 any := obj.(Any) 279 return any.Size() == 0 280 } 281 282 type directAnyCodec struct{} 283 284 func (c *directAnyCodec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 285 *(*Any)(ptr) = iter.readAny() 286 } 287 288 func (c *directAnyCodec) Encode(ctx context.Context, ptr unsafe.Pointer, stream *Stream) { 289 any := *(*Any)(ptr) 290 if any == nil { 291 stream.WriteNil() 292 return 293 } 294 any.WriteTo(ctx, stream) 295 } 296 297 func (c *directAnyCodec) IsEmpty(_ context.Context, ptr unsafe.Pointer, _ bool) bool { 298 any := *(*Any)(ptr) 299 return any.Size() == 0 300 }