package jsoniter
import (
"errors"
"fmt"
"github.com/modern-go/reflect2"
"io"
"reflect"
"strconv"
"unsafe"
)
type Any interface {
LastError () error
ValueType () ValueType
MustBeValid () Any
ToBool () bool
ToInt () int
ToInt32 () int32
ToInt64 () int64
ToUint () uint
ToUint32 () uint32
ToUint64 () uint64
ToFloat32 () float32
ToFloat64 () float64
ToString () string
ToVal (val interface {})
Get (path ...interface {}) Any
Size () int
Keys () []string
GetInterface () interface {}
WriteTo (stream *Stream )
}
type baseAny struct {}
func (any *baseAny ) Get (path ...interface {}) Any {
return &invalidAny {baseAny {}, fmt .Errorf ("GetIndex %v from simple value" , path )}
}
func (any *baseAny ) Size () int {
return 0
}
func (any *baseAny ) Keys () []string {
return []string {}
}
func (any *baseAny ) ToVal (obj interface {}) {
panic ("not implemented" )
}
func WrapInt32 (val int32 ) Any {
return &int32Any {baseAny {}, val }
}
func WrapInt64 (val int64 ) Any {
return &int64Any {baseAny {}, val }
}
func WrapUint32 (val uint32 ) Any {
return &uint32Any {baseAny {}, val }
}
func WrapUint64 (val uint64 ) Any {
return &uint64Any {baseAny {}, val }
}
func WrapFloat64 (val float64 ) Any {
return &floatAny {baseAny {}, val }
}
func WrapString (val string ) Any {
return &stringAny {baseAny {}, val }
}
func Wrap (val interface {}) Any {
if val == nil {
return &nilAny {}
}
asAny , isAny := val .(Any )
if isAny {
return asAny
}
typ := reflect2 .TypeOf (val )
switch typ .Kind () {
case reflect .Slice :
return wrapArray (val )
case reflect .Struct :
return wrapStruct (val )
case reflect .Map :
return wrapMap (val )
case reflect .String :
return WrapString (val .(string ))
case reflect .Int :
if strconv .IntSize == 32 {
return WrapInt32 (int32 (val .(int )))
}
return WrapInt64 (int64 (val .(int )))
case reflect .Int8 :
return WrapInt32 (int32 (val .(int8 )))
case reflect .Int16 :
return WrapInt32 (int32 (val .(int16 )))
case reflect .Int32 :
return WrapInt32 (val .(int32 ))
case reflect .Int64 :
return WrapInt64 (val .(int64 ))
case reflect .Uint :
if strconv .IntSize == 32 {
return WrapUint32 (uint32 (val .(uint )))
}
return WrapUint64 (uint64 (val .(uint )))
case reflect .Uintptr :
if ptrSize == 32 {
return WrapUint32 (uint32 (val .(uintptr )))
}
return WrapUint64 (uint64 (val .(uintptr )))
case reflect .Uint8 :
return WrapUint32 (uint32 (val .(uint8 )))
case reflect .Uint16 :
return WrapUint32 (uint32 (val .(uint16 )))
case reflect .Uint32 :
return WrapUint32 (uint32 (val .(uint32 )))
case reflect .Uint64 :
return WrapUint64 (val .(uint64 ))
case reflect .Float32 :
return WrapFloat64 (float64 (val .(float32 )))
case reflect .Float64 :
return WrapFloat64 (val .(float64 ))
case reflect .Bool :
if val .(bool ) == true {
return &trueAny {}
}
return &falseAny {}
}
return &invalidAny {baseAny {}, fmt .Errorf ("unsupported type: %v" , typ )}
}
func (iter *Iterator ) ReadAny () Any {
return iter .readAny ()
}
func (iter *Iterator ) readAny () Any {
c := iter .nextToken ()
switch c {
case '"' :
iter .unreadByte ()
return &stringAny {baseAny {}, iter .ReadString ()}
case 'n' :
iter .skipThreeBytes ('u' , 'l' , 'l' )
return &nilAny {}
case 't' :
iter .skipThreeBytes ('r' , 'u' , 'e' )
return &trueAny {}
case 'f' :
iter .skipFourBytes ('a' , 'l' , 's' , 'e' )
return &falseAny {}
case '{' :
return iter .readObjectAny ()
case '[' :
return iter .readArrayAny ()
case '-' :
return iter .readNumberAny (false )
case 0 :
return &invalidAny {baseAny {}, errors .New ("input is empty" )}
default :
return iter .readNumberAny (true )
}
}
func (iter *Iterator ) readNumberAny (positive bool ) Any {
iter .startCapture (iter .head - 1 )
iter .skipNumber ()
lazyBuf := iter .stopCapture ()
return &numberLazyAny {baseAny {}, iter .cfg , lazyBuf , nil }
}
func (iter *Iterator ) readObjectAny () Any {
iter .startCapture (iter .head - 1 )
iter .skipObject ()
lazyBuf := iter .stopCapture ()
return &objectLazyAny {baseAny {}, iter .cfg , lazyBuf , nil }
}
func (iter *Iterator ) readArrayAny () Any {
iter .startCapture (iter .head - 1 )
iter .skipArray ()
lazyBuf := iter .stopCapture ()
return &arrayLazyAny {baseAny {}, iter .cfg , lazyBuf , nil }
}
func locateObjectField(iter *Iterator , target string ) []byte {
var found []byte
iter .ReadObjectCB (func (iter *Iterator , field string ) bool {
if field == target {
found = iter .SkipAndReturnBytes ()
return false
}
iter .Skip ()
return true
})
return found
}
func locateArrayElement(iter *Iterator , target int ) []byte {
var found []byte
n := 0
iter .ReadArrayCB (func (iter *Iterator ) bool {
if n == target {
found = iter .SkipAndReturnBytes ()
return false
}
iter .Skip ()
n ++
return true
})
return found
}
func locatePath(iter *Iterator , path []interface {}) Any {
for i , pathKeyObj := range path {
switch pathKey := pathKeyObj .(type ) {
case string :
valueBytes := locateObjectField (iter , pathKey )
if valueBytes == nil {
return newInvalidAny (path [i :])
}
iter .ResetBytes (valueBytes )
case int :
valueBytes := locateArrayElement (iter , pathKey )
if valueBytes == nil {
return newInvalidAny (path [i :])
}
iter .ResetBytes (valueBytes )
case int32 :
if '*' == pathKey {
return iter .readAny ().Get (path [i :]...)
}
return newInvalidAny (path [i :])
default :
return newInvalidAny (path [i :])
}
}
if iter .Error != nil && iter .Error != io .EOF {
return &invalidAny {baseAny {}, iter .Error }
}
return iter .readAny ()
}
var anyType = reflect2 .TypeOfPtr ((*Any )(nil )).Elem ()
func createDecoderOfAny(ctx *ctx , typ reflect2 .Type ) ValDecoder {
if typ == anyType {
return &directAnyCodec {}
}
if typ .Implements (anyType ) {
return &anyCodec {
valType : typ ,
}
}
return nil
}
func createEncoderOfAny(ctx *ctx , typ reflect2 .Type ) ValEncoder {
if typ == anyType {
return &directAnyCodec {}
}
if typ .Implements (anyType ) {
return &anyCodec {
valType : typ ,
}
}
return nil
}
type anyCodec struct {
valType reflect2 .Type
}
func (codec *anyCodec ) Decode (ptr unsafe .Pointer , iter *Iterator ) {
panic ("not implemented" )
}
func (codec *anyCodec ) Encode (ptr unsafe .Pointer , stream *Stream ) {
obj := codec .valType .UnsafeIndirect (ptr )
any := obj .(Any )
any .WriteTo (stream )
}
func (codec *anyCodec ) IsEmpty (ptr unsafe .Pointer ) bool {
obj := codec .valType .UnsafeIndirect (ptr )
any := obj .(Any )
return any .Size () == 0
}
type directAnyCodec struct {
}
func (codec *directAnyCodec ) Decode (ptr unsafe .Pointer , iter *Iterator ) {
*(*Any )(ptr ) = iter .readAny ()
}
func (codec *directAnyCodec ) Encode (ptr unsafe .Pointer , stream *Stream ) {
any := *(*Any )(ptr )
if any == nil {
stream .WriteNil ()
return
}
any .WriteTo (stream )
}
func (codec *directAnyCodec ) IsEmpty (ptr unsafe .Pointer ) bool {
any := *(*Any )(ptr )
return any .Size () == 0
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .