mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-03-09 08:59:30 +00:00
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
326 lines
7.0 KiB
Go
326 lines
7.0 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
|
|
}
|