mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-04 01:12:24 -06:00 
			
		
		
		
	* start fixing up tests * fix up tests + automate with drone * fiddle with linting * messing about with drone.yml * some more fiddling * hmmm * add cache * add vendor directory * verbose * ci updates * update some little things * update sig
		
			
				
	
	
		
			325 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			325 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package jsoniter
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"github.com/modern-go/reflect2"
 | 
						|
	"io"
 | 
						|
	"reflect"
 | 
						|
	"strconv"
 | 
						|
	"unsafe"
 | 
						|
)
 | 
						|
 | 
						|
// Any generic object representation.
 | 
						|
// The lazy json implementation holds []byte and parse lazily.
 | 
						|
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")
 | 
						|
}
 | 
						|
 | 
						|
// WrapInt32 turn int32 into Any interface
 | 
						|
func WrapInt32(val int32) Any {
 | 
						|
	return &int32Any{baseAny{}, val}
 | 
						|
}
 | 
						|
 | 
						|
// WrapInt64 turn int64 into Any interface
 | 
						|
func WrapInt64(val int64) Any {
 | 
						|
	return &int64Any{baseAny{}, val}
 | 
						|
}
 | 
						|
 | 
						|
// WrapUint32 turn uint32 into Any interface
 | 
						|
func WrapUint32(val uint32) Any {
 | 
						|
	return &uint32Any{baseAny{}, val}
 | 
						|
}
 | 
						|
 | 
						|
// WrapUint64 turn uint64 into Any interface
 | 
						|
func WrapUint64(val uint64) Any {
 | 
						|
	return &uint64Any{baseAny{}, val}
 | 
						|
}
 | 
						|
 | 
						|
// WrapFloat64 turn float64 into Any interface
 | 
						|
func WrapFloat64(val float64) Any {
 | 
						|
	return &floatAny{baseAny{}, val}
 | 
						|
}
 | 
						|
 | 
						|
// WrapString turn string into Any interface
 | 
						|
func WrapString(val string) Any {
 | 
						|
	return &stringAny{baseAny{}, val}
 | 
						|
}
 | 
						|
 | 
						|
// Wrap turn a go object into Any interface
 | 
						|
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)}
 | 
						|
}
 | 
						|
 | 
						|
// ReadAny read next JSON element as an Any object. It is a better json.RawMessage.
 | 
						|
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') // null
 | 
						|
		return &nilAny{}
 | 
						|
	case 't':
 | 
						|
		iter.skipThreeBytes('r', 'u', 'e') // true
 | 
						|
		return &trueAny{}
 | 
						|
	case 'f':
 | 
						|
		iter.skipFourBytes('a', 'l', 's', 'e') // false
 | 
						|
		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
 | 
						|
}
 |