mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[chore]: Bump github.com/gin-contrib/gzip from 1.0.1 to 1.1.0 (#3639)
Bumps [github.com/gin-contrib/gzip](https://github.com/gin-contrib/gzip) from 1.0.1 to 1.1.0. - [Release notes](https://github.com/gin-contrib/gzip/releases) - [Changelog](https://github.com/gin-contrib/gzip/blob/master/.goreleaser.yaml) - [Commits](https://github.com/gin-contrib/gzip/compare/v1.0.1...v1.1.0) --- updated-dependencies: - dependency-name: github.com/gin-contrib/gzip dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
174
vendor/github.com/bytedance/sonic/internal/decoder/optdec/compile_struct.go
generated
vendored
Normal file
174
vendor/github.com/bytedance/sonic/internal/decoder/optdec/compile_struct.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
caching "github.com/bytedance/sonic/internal/optcaching"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/internal/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
_MAX_FIELDS = 50 // cutoff at 50 fields struct
|
||||
)
|
||||
|
||||
func (c *compiler) compileIntStringOption(vt reflect.Type) decFunc {
|
||||
switch vt.Size() {
|
||||
case 4:
|
||||
switch vt.Kind() {
|
||||
case reflect.Uint:
|
||||
fallthrough
|
||||
case reflect.Uintptr:
|
||||
return &u32StringDecoder{}
|
||||
case reflect.Int:
|
||||
return &i32StringDecoder{}
|
||||
}
|
||||
case 8:
|
||||
switch vt.Kind() {
|
||||
case reflect.Uint:
|
||||
fallthrough
|
||||
case reflect.Uintptr:
|
||||
return &u64StringDecoder{}
|
||||
case reflect.Int:
|
||||
return &i64StringDecoder{}
|
||||
}
|
||||
default:
|
||||
panic("not supported pointer size: " + fmt.Sprint(vt.Size()))
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func isInteger(vt reflect.Type) bool {
|
||||
switch vt.Kind() {
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr, reflect.Int: return true
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) assertStringOptTypes(vt reflect.Type) {
|
||||
if c.depth > _CompileMaxDepth {
|
||||
panic(*stackOverflow)
|
||||
}
|
||||
|
||||
c.depth += 1
|
||||
defer func () {
|
||||
c.depth -= 1
|
||||
}()
|
||||
|
||||
if isInteger(vt) {
|
||||
return
|
||||
}
|
||||
|
||||
switch vt.Kind() {
|
||||
case reflect.String, reflect.Bool, reflect.Float32, reflect.Float64:
|
||||
return
|
||||
case reflect.Ptr: c.assertStringOptTypes(vt.Elem())
|
||||
default:
|
||||
panicForInvalidStrType(vt)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compileFieldStringOption(vt reflect.Type) decFunc {
|
||||
c.assertStringOptTypes(vt)
|
||||
unmDec := c.tryCompilePtrUnmarshaler(vt, true)
|
||||
if unmDec != nil {
|
||||
return unmDec
|
||||
}
|
||||
|
||||
switch vt.Kind() {
|
||||
case reflect.String:
|
||||
if vt == jsonNumberType {
|
||||
return &numberStringDecoder{}
|
||||
}
|
||||
return &strStringDecoder{}
|
||||
case reflect.Bool:
|
||||
return &boolStringDecoder{}
|
||||
case reflect.Int8:
|
||||
return &i8StringDecoder{}
|
||||
case reflect.Int16:
|
||||
return &i16StringDecoder{}
|
||||
case reflect.Int32:
|
||||
return &i32StringDecoder{}
|
||||
case reflect.Int64:
|
||||
return &i64StringDecoder{}
|
||||
case reflect.Uint8:
|
||||
return &u8StringDecoder{}
|
||||
case reflect.Uint16:
|
||||
return &u16StringDecoder{}
|
||||
case reflect.Uint32:
|
||||
return &u32StringDecoder{}
|
||||
case reflect.Uint64:
|
||||
return &u64StringDecoder{}
|
||||
case reflect.Float32:
|
||||
return &f32StringDecoder{}
|
||||
case reflect.Float64:
|
||||
return &f64StringDecoder{}
|
||||
case reflect.Uint:
|
||||
fallthrough
|
||||
case reflect.Uintptr:
|
||||
fallthrough
|
||||
case reflect.Int:
|
||||
return c.compileIntStringOption(vt)
|
||||
case reflect.Ptr:
|
||||
return &ptrStrDecoder{
|
||||
typ: rt.UnpackType(vt.Elem()),
|
||||
deref: c.compileFieldStringOption(vt.Elem()),
|
||||
}
|
||||
default:
|
||||
panicForInvalidStrType(vt)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compileStruct(vt reflect.Type) decFunc {
|
||||
c.enter(vt)
|
||||
defer c.exit(vt)
|
||||
if c.namedPtr {
|
||||
c.namedPtr = false
|
||||
return c.compileStructBody(vt)
|
||||
}
|
||||
|
||||
if c.depth >= c.opts.MaxInlineDepth + 1 || (c.counts > 0 && vt.NumField() >= _MAX_FIELDS) {
|
||||
return &recuriveDecoder{
|
||||
typ: rt.UnpackType(vt),
|
||||
}
|
||||
} else {
|
||||
return c.compileStructBody(vt)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compileStructBody(vt reflect.Type) decFunc {
|
||||
fv := resolver.ResolveStruct(vt)
|
||||
entries := make([]fieldEntry, 0, len(fv))
|
||||
|
||||
for _, f := range fv {
|
||||
var dec decFunc
|
||||
/* dealt with field tag options */
|
||||
if f.Opts&resolver.F_stringize != 0 {
|
||||
dec = c.compileFieldStringOption(f.Type)
|
||||
} else {
|
||||
dec = c.compile(f.Type)
|
||||
}
|
||||
|
||||
/* deal with embedded pointer fields */
|
||||
if f.Path[0].Kind == resolver.F_deref {
|
||||
dec = &embeddedFieldPtrDecoder{
|
||||
field: f,
|
||||
fieldDec: dec,
|
||||
fieldName: f.Name,
|
||||
}
|
||||
}
|
||||
|
||||
entries = append(entries, fieldEntry{
|
||||
FieldMeta: f,
|
||||
fieldDec: dec,
|
||||
})
|
||||
}
|
||||
return &structDecoder{
|
||||
fieldMap: caching.NewFieldLookup(fv),
|
||||
fields: entries,
|
||||
structName: vt.Name(),
|
||||
typ: vt,
|
||||
}
|
||||
}
|
449
vendor/github.com/bytedance/sonic/internal/decoder/optdec/compiler.go
generated
vendored
Normal file
449
vendor/github.com/bytedance/sonic/internal/decoder/optdec/compiler.go
generated
vendored
Normal file
@ -0,0 +1,449 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/bytedance/sonic/option"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/internal/caching"
|
||||
)
|
||||
|
||||
var (
|
||||
programCache = caching.CreateProgramCache()
|
||||
)
|
||||
|
||||
func findOrCompile(vt *rt.GoType) (decFunc, error) {
|
||||
makeDecoder := func(vt *rt.GoType, _ ...interface{}) (interface{}, error) {
|
||||
ret, err := newCompiler().compileType(vt.Pack())
|
||||
return ret, err
|
||||
}
|
||||
if val := programCache.Get(vt); val != nil {
|
||||
return val.(decFunc), nil
|
||||
} else if ret, err := programCache.Compute(vt, makeDecoder); err == nil {
|
||||
return ret.(decFunc), nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
type compiler struct {
|
||||
visited map[reflect.Type]bool
|
||||
depth int
|
||||
counts int
|
||||
opts option.CompileOptions
|
||||
namedPtr bool
|
||||
}
|
||||
|
||||
func newCompiler() *compiler {
|
||||
return &compiler{
|
||||
visited: make(map[reflect.Type]bool),
|
||||
opts: option.DefaultCompileOptions(),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *compiler) apply(opts option.CompileOptions) *compiler {
|
||||
self.opts = opts
|
||||
return self
|
||||
}
|
||||
|
||||
const _CompileMaxDepth = 4096
|
||||
|
||||
func (c *compiler) enter(vt reflect.Type) {
|
||||
c.visited[vt] = true
|
||||
c.depth += 1
|
||||
|
||||
if c.depth > _CompileMaxDepth {
|
||||
panic(*stackOverflow)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) exit(vt reflect.Type) {
|
||||
c.visited[vt] = false
|
||||
c.depth -= 1
|
||||
}
|
||||
|
||||
func (c *compiler) compileInt(vt reflect.Type) decFunc {
|
||||
switch vt.Size() {
|
||||
case 4:
|
||||
switch vt.Kind() {
|
||||
case reflect.Uint:
|
||||
fallthrough
|
||||
case reflect.Uintptr:
|
||||
return &u32Decoder{}
|
||||
case reflect.Int:
|
||||
return &i32Decoder{}
|
||||
}
|
||||
case 8:
|
||||
switch vt.Kind() {
|
||||
case reflect.Uint:
|
||||
fallthrough
|
||||
case reflect.Uintptr:
|
||||
return &u64Decoder{}
|
||||
case reflect.Int:
|
||||
return &i64Decoder{}
|
||||
}
|
||||
default:
|
||||
panic("not supported pointer size: " + fmt.Sprint(vt.Size()))
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (c *compiler) rescue(ep *error) {
|
||||
if val := recover(); val != nil {
|
||||
if err, ok := val.(error); ok {
|
||||
*ep = err
|
||||
} else {
|
||||
panic(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compileType(vt reflect.Type) (rt decFunc, err error) {
|
||||
defer c.rescue(&err)
|
||||
rt = c.compile(vt)
|
||||
return rt, err
|
||||
}
|
||||
|
||||
func (c *compiler) compile(vt reflect.Type) decFunc {
|
||||
if c.visited[vt] {
|
||||
return &recuriveDecoder{
|
||||
typ: rt.UnpackType(vt),
|
||||
}
|
||||
}
|
||||
|
||||
dec := c.tryCompilePtrUnmarshaler(vt, false)
|
||||
if dec != nil {
|
||||
return dec
|
||||
}
|
||||
|
||||
return c.compileBasic(vt)
|
||||
}
|
||||
|
||||
func (c *compiler) compileBasic(vt reflect.Type) decFunc {
|
||||
defer func() {
|
||||
c.counts += 1
|
||||
}()
|
||||
switch vt.Kind() {
|
||||
case reflect.Bool:
|
||||
return &boolDecoder{}
|
||||
case reflect.Int8:
|
||||
return &i8Decoder{}
|
||||
case reflect.Int16:
|
||||
return &i16Decoder{}
|
||||
case reflect.Int32:
|
||||
return &i32Decoder{}
|
||||
case reflect.Int64:
|
||||
return &i64Decoder{}
|
||||
case reflect.Uint8:
|
||||
return &u8Decoder{}
|
||||
case reflect.Uint16:
|
||||
return &u16Decoder{}
|
||||
case reflect.Uint32:
|
||||
return &u32Decoder{}
|
||||
case reflect.Uint64:
|
||||
return &u64Decoder{}
|
||||
case reflect.Float32:
|
||||
return &f32Decoder{}
|
||||
case reflect.Float64:
|
||||
return &f64Decoder{}
|
||||
case reflect.Uint:
|
||||
fallthrough
|
||||
case reflect.Uintptr:
|
||||
fallthrough
|
||||
case reflect.Int:
|
||||
return c.compileInt(vt)
|
||||
case reflect.String:
|
||||
return c.compileString(vt)
|
||||
case reflect.Array:
|
||||
return c.compileArray(vt)
|
||||
case reflect.Interface:
|
||||
return c.compileInterface(vt)
|
||||
case reflect.Map:
|
||||
return c.compileMap(vt)
|
||||
case reflect.Ptr:
|
||||
return c.compilePtr(vt)
|
||||
case reflect.Slice:
|
||||
return c.compileSlice(vt)
|
||||
case reflect.Struct:
|
||||
return c.compileStruct(vt)
|
||||
default:
|
||||
panic(&json.UnmarshalTypeError{Type: vt})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compilePtr(vt reflect.Type) decFunc {
|
||||
c.enter(vt)
|
||||
defer c.exit(vt)
|
||||
|
||||
// specail logic for Named Ptr, issue 379
|
||||
if reflect.PtrTo(vt.Elem()) != vt {
|
||||
c.namedPtr = true
|
||||
return &ptrDecoder{
|
||||
typ: rt.UnpackType(vt.Elem()),
|
||||
deref: c.compileBasic(vt.Elem()),
|
||||
}
|
||||
}
|
||||
|
||||
return &ptrDecoder{
|
||||
typ: rt.UnpackType(vt.Elem()),
|
||||
deref: c.compile(vt.Elem()),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compileArray(vt reflect.Type) decFunc {
|
||||
c.enter(vt)
|
||||
defer c.exit(vt)
|
||||
return &arrayDecoder{
|
||||
len: vt.Len(),
|
||||
elemType: rt.UnpackType(vt.Elem()),
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
typ: vt,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compileString(vt reflect.Type) decFunc {
|
||||
if vt == jsonNumberType {
|
||||
return &numberDecoder{}
|
||||
}
|
||||
return &stringDecoder{}
|
||||
|
||||
}
|
||||
|
||||
func (c *compiler) tryCompileSliceUnmarshaler(vt reflect.Type) decFunc {
|
||||
pt := reflect.PtrTo(vt.Elem())
|
||||
if pt.Implements(jsonUnmarshalerType) {
|
||||
return &sliceDecoder{
|
||||
elemType: rt.UnpackType(vt.Elem()),
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
typ: vt,
|
||||
}
|
||||
}
|
||||
|
||||
if pt.Implements(encodingTextUnmarshalerType) {
|
||||
return &sliceDecoder{
|
||||
elemType: rt.UnpackType(vt.Elem()),
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
typ: vt,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *compiler) compileSlice(vt reflect.Type) decFunc {
|
||||
c.enter(vt)
|
||||
defer c.exit(vt)
|
||||
|
||||
// Some common slice, use a decoder, to avoid function calls
|
||||
et := rt.UnpackType(vt.Elem())
|
||||
|
||||
/* first checking `[]byte` */
|
||||
if et.Kind() == reflect.Uint8 /* []byte */ {
|
||||
return c.compileSliceBytes(vt)
|
||||
}
|
||||
|
||||
dec := c.tryCompileSliceUnmarshaler(vt)
|
||||
if dec != nil {
|
||||
return dec
|
||||
}
|
||||
|
||||
if vt == reflect.TypeOf([]interface{}{}) {
|
||||
return &sliceEfaceDecoder{}
|
||||
}
|
||||
if et.IsInt32() {
|
||||
return &sliceI32Decoder{}
|
||||
}
|
||||
if et.IsInt64() {
|
||||
return &sliceI64Decoder{}
|
||||
}
|
||||
if et.IsUint32() {
|
||||
return &sliceU32Decoder{}
|
||||
}
|
||||
if et.IsUint64() {
|
||||
return &sliceU64Decoder{}
|
||||
}
|
||||
if et.Kind() == reflect.String {
|
||||
return &sliceStringDecoder{}
|
||||
}
|
||||
|
||||
return &sliceDecoder{
|
||||
elemType: rt.UnpackType(vt.Elem()),
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
typ: vt,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compileSliceBytes(vt reflect.Type) decFunc {
|
||||
ep := reflect.PtrTo(vt.Elem())
|
||||
|
||||
if ep.Implements(jsonUnmarshalerType) {
|
||||
return &sliceBytesUnmarshalerDecoder{
|
||||
elemType: rt.UnpackType(vt.Elem()),
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
typ: vt,
|
||||
}
|
||||
}
|
||||
|
||||
if ep.Implements(encodingTextUnmarshalerType) {
|
||||
return &sliceBytesUnmarshalerDecoder{
|
||||
elemType: rt.UnpackType(vt.Elem()),
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
typ: vt,
|
||||
}
|
||||
}
|
||||
|
||||
return &sliceBytesDecoder{}
|
||||
}
|
||||
|
||||
func (c *compiler) compileInterface(vt reflect.Type) decFunc {
|
||||
c.enter(vt)
|
||||
defer c.exit(vt)
|
||||
if vt.NumMethod() == 0 {
|
||||
return &efaceDecoder{}
|
||||
}
|
||||
|
||||
if vt.Implements(jsonUnmarshalerType) {
|
||||
return &unmarshalJSONDecoder{
|
||||
typ: rt.UnpackType(vt),
|
||||
}
|
||||
}
|
||||
|
||||
if vt.Implements(encodingTextUnmarshalerType) {
|
||||
return &unmarshalTextDecoder{
|
||||
typ: rt.UnpackType(vt),
|
||||
}
|
||||
}
|
||||
|
||||
return &ifaceDecoder{
|
||||
typ: rt.UnpackType(vt),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compileMap(vt reflect.Type) decFunc {
|
||||
c.enter(vt)
|
||||
defer c.exit(vt)
|
||||
// check the key unmarshaler at first
|
||||
decKey := tryCompileKeyUnmarshaler(vt)
|
||||
if decKey != nil {
|
||||
return &mapDecoder{
|
||||
mapType: rt.MapType(rt.UnpackType(vt)),
|
||||
keyDec: decKey,
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
}
|
||||
}
|
||||
|
||||
// Most common map, use a decoder, to avoid function calls
|
||||
if vt == reflect.TypeOf(map[string]interface{}{}) {
|
||||
return &mapEfaceDecoder{}
|
||||
} else if vt == reflect.TypeOf(map[string]string{}) {
|
||||
return &mapStringDecoder{}
|
||||
}
|
||||
|
||||
// Some common integer map later
|
||||
mt := rt.MapType(rt.UnpackType(vt))
|
||||
|
||||
if mt.Key.Kind() == reflect.String {
|
||||
return &mapStrKeyDecoder{
|
||||
mapType: mt,
|
||||
assign: rt.GetMapStrAssign(vt),
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
}
|
||||
}
|
||||
|
||||
if mt.Key.IsInt64() {
|
||||
return &mapI64KeyDecoder{
|
||||
mapType: mt,
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
assign: rt.GetMap64Assign(vt),
|
||||
}
|
||||
}
|
||||
|
||||
if mt.Key.IsInt32() {
|
||||
return &mapI32KeyDecoder{
|
||||
mapType: mt,
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
assign: rt.GetMap32Assign(vt),
|
||||
}
|
||||
}
|
||||
|
||||
if mt.Key.IsUint64() {
|
||||
return &mapU64KeyDecoder{
|
||||
mapType: mt,
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
assign: rt.GetMap64Assign(vt),
|
||||
}
|
||||
}
|
||||
|
||||
if mt.Key.IsUint32() {
|
||||
return &mapU32KeyDecoder{
|
||||
mapType: mt,
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
assign: rt.GetMap32Assign(vt),
|
||||
}
|
||||
}
|
||||
|
||||
// Generic map
|
||||
return &mapDecoder{
|
||||
mapType: mt,
|
||||
keyDec: c.compileMapKey(vt),
|
||||
elemDec: c.compile(vt.Elem()),
|
||||
}
|
||||
}
|
||||
|
||||
func tryCompileKeyUnmarshaler(vt reflect.Type) decKey {
|
||||
pt := reflect.PtrTo(vt.Key())
|
||||
|
||||
/* check for `encoding.TextUnmarshaler` with pointer receiver */
|
||||
if pt.Implements(encodingTextUnmarshalerType) {
|
||||
return decodeKeyTextUnmarshaler
|
||||
}
|
||||
|
||||
/* not support map key with `json.Unmarshaler` */
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *compiler) compileMapKey(vt reflect.Type) decKey {
|
||||
switch vt.Key().Kind() {
|
||||
case reflect.Int8:
|
||||
return decodeKeyI8
|
||||
case reflect.Int16:
|
||||
return decodeKeyI16
|
||||
case reflect.Uint8:
|
||||
return decodeKeyU8
|
||||
case reflect.Uint16:
|
||||
return decodeKeyU16
|
||||
default:
|
||||
panic(&json.UnmarshalTypeError{Type: vt})
|
||||
}
|
||||
}
|
||||
|
||||
// maybe vt is a named type, and not a pointer receiver, see issue 379
|
||||
func (c *compiler) tryCompilePtrUnmarshaler(vt reflect.Type, strOpt bool) decFunc {
|
||||
pt := reflect.PtrTo(vt)
|
||||
|
||||
/* check for `json.Unmarshaler` with pointer receiver */
|
||||
if pt.Implements(jsonUnmarshalerType) {
|
||||
return &unmarshalJSONDecoder{
|
||||
typ: rt.UnpackType(pt),
|
||||
strOpt: strOpt,
|
||||
}
|
||||
}
|
||||
|
||||
/* check for `encoding.TextMarshaler` with pointer receiver */
|
||||
if pt.Implements(encodingTextUnmarshalerType) {
|
||||
/* TextUnmarshal not support ,strig tag */
|
||||
if strOpt {
|
||||
panicForInvalidStrType(vt)
|
||||
}
|
||||
return &unmarshalTextDecoder{
|
||||
typ: rt.UnpackType(pt),
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func panicForInvalidStrType(vt reflect.Type) {
|
||||
panic(error_type(rt.UnpackType(vt)))
|
||||
}
|
60
vendor/github.com/bytedance/sonic/internal/decoder/optdec/const.go
generated
vendored
Normal file
60
vendor/github.com/bytedance/sonic/internal/decoder/optdec/const.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
package optdec
|
||||
|
||||
import "math"
|
||||
|
||||
/*
|
||||
Copied from sonic-rs
|
||||
// JSON Value Type
|
||||
const NULL: u64 = 0;
|
||||
const BOOL: u64 = 2;
|
||||
const FALSE: u64 = BOOL;
|
||||
const TRUE: u64 = (1 << 3) | BOOL;
|
||||
const NUMBER: u64 = 3;
|
||||
const UINT: u64 = NUMBER;
|
||||
const SINT: u64 = (1 << 3) | NUMBER;
|
||||
const REAL: u64 = (2 << 3) | NUMBER;
|
||||
const RAWNUMBER: u64 = (3 << 3) | NUMBER;
|
||||
const STRING: u64 = 4;
|
||||
const STRING_COMMON: u64 = STRING;
|
||||
const STRING_HASESCAPED: u64 = (1 << 3) | STRING;
|
||||
const OBJECT: u64 = 6;
|
||||
const ARRAY: u64 = 7;
|
||||
|
||||
/// JSON Type Mask
|
||||
const POS_MASK: u64 = (!0) << 32;
|
||||
const POS_BITS: u64 = 32;
|
||||
const TYPE_MASK: u64 = 0xFF;
|
||||
const TYPE_BITS: u64 = 8;
|
||||
|
||||
*/
|
||||
|
||||
const (
|
||||
// BasicType: 3 bits
|
||||
KNull = 0 // xxxxx000
|
||||
KBool = 2 // xxxxx010
|
||||
KNumber = 3 // xxxxx011
|
||||
KString = 4 // xxxxx100
|
||||
KRaw = 5 // xxxxx101
|
||||
KObject = 6 // xxxxx110
|
||||
KArray = 7 // xxxxx111
|
||||
|
||||
// SubType: 2 bits
|
||||
KFalse = (0 << 3) | KBool // xxx00_010, 2
|
||||
KTrue = (1 << 3) | KBool // xxx01_010, 10
|
||||
KUint = (0 << 3) | KNumber // xxx00_011, 3
|
||||
KSint = (1 << 3) | KNumber // xxx01_011, 11
|
||||
KReal = (2 << 3) | KNumber // xxx10_011, 19
|
||||
KRawNumber = (3 << 3) | KNumber // xxx11_011, 27
|
||||
KStringCommon = KString // xxx00_100, 4
|
||||
KStringEscaped = (1 << 3) | KString // xxx01_100, 12
|
||||
)
|
||||
|
||||
const (
|
||||
PosMask = math.MaxUint64 << 32
|
||||
PosBits = 32
|
||||
TypeMask = 0xFF
|
||||
TypeBits = 8
|
||||
|
||||
ConLenMask = uint64(math.MaxUint32)
|
||||
ConLenBits = 32
|
||||
)
|
3
vendor/github.com/bytedance/sonic/internal/decoder/optdec/context.go
generated
vendored
Normal file
3
vendor/github.com/bytedance/sonic/internal/decoder/optdec/context.go
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package optdec
|
||||
|
||||
type context = Context
|
160
vendor/github.com/bytedance/sonic/internal/decoder/optdec/decoder.go
generated
vendored
Normal file
160
vendor/github.com/bytedance/sonic/internal/decoder/optdec/decoder.go
generated
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"encoding/json"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/option"
|
||||
"github.com/bytedance/sonic/internal/decoder/errors"
|
||||
"github.com/bytedance/sonic/internal/decoder/consts"
|
||||
)
|
||||
|
||||
|
||||
type (
|
||||
MismatchTypeError = errors.MismatchTypeError
|
||||
SyntaxError = errors.SyntaxError
|
||||
)
|
||||
|
||||
const (
|
||||
_F_allow_control = consts.F_allow_control
|
||||
_F_copy_string = consts.F_copy_string
|
||||
_F_disable_unknown = consts.F_disable_unknown
|
||||
_F_disable_urc = consts.F_disable_urc
|
||||
_F_use_int64 = consts.F_use_int64
|
||||
_F_use_number = consts.F_use_number
|
||||
_F_validate_string = consts.F_validate_string
|
||||
)
|
||||
|
||||
type Options = consts.Options
|
||||
|
||||
const (
|
||||
OptionUseInt64 = consts.OptionUseInt64
|
||||
OptionUseNumber = consts.OptionUseNumber
|
||||
OptionUseUnicodeErrors = consts.OptionUseUnicodeErrors
|
||||
OptionDisableUnknown = consts.OptionDisableUnknown
|
||||
OptionCopyString = consts.OptionCopyString
|
||||
OptionValidateString = consts.OptionValidateString
|
||||
)
|
||||
|
||||
|
||||
func Decode(s *string, i *int, f uint64, val interface{}) error {
|
||||
vv := rt.UnpackEface(val)
|
||||
vp := vv.Value
|
||||
|
||||
/* check for nil type */
|
||||
if vv.Type == nil {
|
||||
return &json.InvalidUnmarshalError{}
|
||||
}
|
||||
|
||||
/* must be a non-nil pointer */
|
||||
if vp == nil || vv.Type.Kind() != reflect.Ptr {
|
||||
return &json.InvalidUnmarshalError{Type: vv.Type.Pack()}
|
||||
}
|
||||
|
||||
etp := rt.PtrElem(vv.Type)
|
||||
|
||||
/* check the defined pointer type for issue 379 */
|
||||
if vv.Type.IsNamed() {
|
||||
newp := vp
|
||||
etp = vv.Type
|
||||
vp = unsafe.Pointer(&newp)
|
||||
}
|
||||
|
||||
dec, err := findOrCompile(etp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/* parse into document */
|
||||
ctx, err := NewContext(*s, *i, uint64(f), etp)
|
||||
defer ctx.Delete()
|
||||
if ctx.Parser.Utf8Inv {
|
||||
*s = ctx.Parser.Json
|
||||
}
|
||||
if err != nil {
|
||||
goto fix_error;
|
||||
}
|
||||
err = dec.FromDom(vp, ctx.Root(), &ctx)
|
||||
|
||||
fix_error:
|
||||
err = fix_error(*s, *i, err)
|
||||
|
||||
// update position at last
|
||||
*i += ctx.Parser.Pos()
|
||||
return err
|
||||
}
|
||||
|
||||
func fix_error(json string, pos int, err error) error {
|
||||
if e, ok := err.(SyntaxError); ok {
|
||||
return SyntaxError{
|
||||
Pos: int(e.Pos) + pos,
|
||||
Src: json,
|
||||
Msg: e.Msg,
|
||||
}
|
||||
}
|
||||
|
||||
if e, ok := err.(MismatchTypeError); ok {
|
||||
return &MismatchTypeError {
|
||||
Pos: int(e.Pos) + pos,
|
||||
Src: json,
|
||||
Type: e.Type,
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in
|
||||
// order to reduce the first-hit latency.
|
||||
//
|
||||
// Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is
|
||||
// a compile option to set the depth of recursive compile for the nested struct type.
|
||||
func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
|
||||
cfg := option.DefaultCompileOptions()
|
||||
for _, opt := range opts {
|
||||
opt(&cfg)
|
||||
}
|
||||
return pretouchRec(map[reflect.Type]bool{vt:true}, cfg)
|
||||
}
|
||||
|
||||
func pretouchType(_vt reflect.Type, opts option.CompileOptions) (map[reflect.Type]bool, error) {
|
||||
/* compile function */
|
||||
compiler := newCompiler().apply(opts)
|
||||
decoder := func(vt *rt.GoType, _ ...interface{}) (interface{}, error) {
|
||||
if f, err := compiler.compileType(_vt); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return f, nil
|
||||
}
|
||||
}
|
||||
|
||||
/* find or compile */
|
||||
vt := rt.UnpackType(_vt)
|
||||
if val := programCache.Get(vt); val != nil {
|
||||
return nil, nil
|
||||
} else if _, err := programCache.Compute(vt, decoder); err == nil {
|
||||
return compiler.visited, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func pretouchRec(vtm map[reflect.Type]bool, opts option.CompileOptions) error {
|
||||
if opts.RecursiveDepth < 0 || len(vtm) == 0 {
|
||||
return nil
|
||||
}
|
||||
next := make(map[reflect.Type]bool)
|
||||
for vt := range(vtm) {
|
||||
sub, err := pretouchType(vt, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for svt := range(sub) {
|
||||
next[svt] = true
|
||||
}
|
||||
}
|
||||
opts.RecursiveDepth -= 1
|
||||
return pretouchRec(next, opts)
|
||||
}
|
73
vendor/github.com/bytedance/sonic/internal/decoder/optdec/errors.go
generated
vendored
Normal file
73
vendor/github.com/bytedance/sonic/internal/decoder/optdec/errors.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2021 ByteDance Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
/** JIT Error Helpers **/
|
||||
|
||||
var stackOverflow = &json.UnsupportedValueError{
|
||||
Str: "Value nesting too deep",
|
||||
Value: reflect.ValueOf("..."),
|
||||
}
|
||||
|
||||
func error_type(vt *rt.GoType) error {
|
||||
return &json.UnmarshalTypeError{Type: vt.Pack()}
|
||||
}
|
||||
|
||||
func error_mismatch(node Node, ctx *context, typ reflect.Type) error {
|
||||
return MismatchTypeError{
|
||||
Pos: node.Position(),
|
||||
Src: ctx.Parser.Json,
|
||||
Type: typ,
|
||||
}
|
||||
}
|
||||
|
||||
func newUnmatched(pos int, vt *rt.GoType) error {
|
||||
return MismatchTypeError{
|
||||
Pos: pos,
|
||||
Src: "",
|
||||
Type: vt.Pack(),
|
||||
}
|
||||
}
|
||||
|
||||
func error_field(name string) error {
|
||||
return errors.New("json: unknown field " + strconv.Quote(name))
|
||||
}
|
||||
|
||||
func error_value(value string, vtype reflect.Type) error {
|
||||
return &json.UnmarshalTypeError{
|
||||
Type: vtype,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
func error_syntax(pos int, src string, msg string) error {
|
||||
return SyntaxError{
|
||||
Pos: pos,
|
||||
Src: src,
|
||||
Msg: msg,
|
||||
}
|
||||
}
|
||||
|
281
vendor/github.com/bytedance/sonic/internal/decoder/optdec/functor.go
generated
vendored
Normal file
281
vendor/github.com/bytedance/sonic/internal/decoder/optdec/functor.go
generated
vendored
Normal file
@ -0,0 +1,281 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/internal/resolver"
|
||||
)
|
||||
|
||||
type decFunc interface {
|
||||
FromDom(vp unsafe.Pointer, node Node, ctx *context) error
|
||||
}
|
||||
|
||||
type ptrDecoder struct {
|
||||
typ *rt.GoType
|
||||
deref decFunc
|
||||
}
|
||||
|
||||
// Pointer Value is allocated in the Caller
|
||||
func (d *ptrDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if *(*unsafe.Pointer)(vp) == nil {
|
||||
*(*unsafe.Pointer)(vp) = rt.Mallocgc(d.typ.Size, d.typ, true)
|
||||
}
|
||||
|
||||
return d.deref.FromDom(*(*unsafe.Pointer)(vp), node, ctx)
|
||||
}
|
||||
|
||||
type embeddedFieldPtrDecoder struct {
|
||||
field resolver.FieldMeta
|
||||
fieldDec decFunc
|
||||
fieldName string
|
||||
}
|
||||
|
||||
// Pointer Value is allocated in the Caller
|
||||
func (d *embeddedFieldPtrDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// seek into the pointer
|
||||
vp = unsafe.Pointer(uintptr(vp) - uintptr(d.field.Path[0].Size))
|
||||
for _, f := range d.field.Path {
|
||||
deref := rt.UnpackType(f.Type)
|
||||
vp = unsafe.Pointer(uintptr(vp) + f.Size)
|
||||
if f.Kind == resolver.F_deref {
|
||||
if *(*unsafe.Pointer)(vp) == nil {
|
||||
*(*unsafe.Pointer)(vp) = rt.Mallocgc(deref.Size, deref, true)
|
||||
}
|
||||
vp = *(*unsafe.Pointer)(vp)
|
||||
}
|
||||
}
|
||||
return d.fieldDec.FromDom(vp, node, ctx)
|
||||
}
|
||||
|
||||
type i8Decoder struct{}
|
||||
|
||||
func (d *i8Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsI64(ctx)
|
||||
if !ok || ret > math.MaxInt8 || ret < math.MinInt8 {
|
||||
return error_mismatch(node, ctx, int8Type)
|
||||
}
|
||||
|
||||
*(*int8)(vp) = int8(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type i16Decoder struct{}
|
||||
|
||||
func (d *i16Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsI64(ctx)
|
||||
if !ok || ret > math.MaxInt16 || ret < math.MinInt16 {
|
||||
return error_mismatch(node, ctx, int16Type)
|
||||
}
|
||||
|
||||
*(*int16)(vp) = int16(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type i32Decoder struct{}
|
||||
|
||||
func (d *i32Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsI64(ctx)
|
||||
if !ok || ret > math.MaxInt32 || ret < math.MinInt32 {
|
||||
return error_mismatch(node, ctx, int32Type)
|
||||
}
|
||||
|
||||
*(*int32)(vp) = int32(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type i64Decoder struct{}
|
||||
|
||||
func (d *i64Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsI64(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, int64Type)
|
||||
}
|
||||
|
||||
*(*int64)(vp) = int64(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type u8Decoder struct{}
|
||||
|
||||
func (d *u8Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsU64(ctx)
|
||||
if !ok || ret > math.MaxUint8 {
|
||||
err := error_mismatch(node, ctx, uint8Type)
|
||||
return err
|
||||
}
|
||||
|
||||
*(*uint8)(vp) = uint8(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type u16Decoder struct{}
|
||||
|
||||
func (d *u16Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsU64(ctx)
|
||||
if !ok || ret > math.MaxUint16 {
|
||||
return error_mismatch(node, ctx, uint16Type)
|
||||
}
|
||||
*(*uint16)(vp) = uint16(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type u32Decoder struct{}
|
||||
|
||||
func (d *u32Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsU64(ctx)
|
||||
if !ok || ret > math.MaxUint32 {
|
||||
return error_mismatch(node, ctx, uint32Type)
|
||||
}
|
||||
|
||||
*(*uint32)(vp) = uint32(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type u64Decoder struct{}
|
||||
|
||||
func (d *u64Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsU64(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, uint64Type)
|
||||
}
|
||||
|
||||
*(*uint64)(vp) = uint64(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type f32Decoder struct{}
|
||||
|
||||
func (d *f32Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsF64(ctx)
|
||||
if !ok || ret > math.MaxFloat32 || ret < -math.MaxFloat32 {
|
||||
return error_mismatch(node, ctx, float32Type)
|
||||
}
|
||||
|
||||
*(*float32)(vp) = float32(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type f64Decoder struct{}
|
||||
|
||||
func (d *f64Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsF64(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, float64Type)
|
||||
}
|
||||
|
||||
*(*float64)(vp) = float64(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type boolDecoder struct {
|
||||
}
|
||||
|
||||
func (d *boolDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsBool()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, boolType)
|
||||
}
|
||||
|
||||
*(*bool)(vp) = bool(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type stringDecoder struct {
|
||||
}
|
||||
|
||||
func (d *stringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, ok := node.AsStr(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, stringType)
|
||||
}
|
||||
*(*string)(vp) = ret
|
||||
return nil
|
||||
}
|
||||
|
||||
type numberDecoder struct {
|
||||
}
|
||||
|
||||
func (d *numberDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
num, ok := node.AsNumber(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, jsonNumberType)
|
||||
}
|
||||
*(*json.Number)(vp) = num
|
||||
return nil
|
||||
}
|
||||
|
||||
type recuriveDecoder struct {
|
||||
typ *rt.GoType
|
||||
}
|
||||
|
||||
func (d *recuriveDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
dec, err := findOrCompile(d.typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dec.FromDom(vp, node, ctx)
|
||||
}
|
110
vendor/github.com/bytedance/sonic/internal/decoder/optdec/helper.go
generated
vendored
Normal file
110
vendor/github.com/bytedance/sonic/internal/decoder/optdec/helper.go
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"github.com/bytedance/sonic/internal/native"
|
||||
"github.com/bytedance/sonic/internal/utils"
|
||||
"github.com/bytedance/sonic/internal/native/types"
|
||||
)
|
||||
|
||||
|
||||
func SkipNumberFast(json string, start int) (int, bool) {
|
||||
// find the number ending, we pasred in native, it alway valid
|
||||
pos := start
|
||||
for pos < len(json) && json[pos] != ']' && json[pos] != '}' && json[pos] != ',' {
|
||||
if json[pos] >= '0' && json[pos] <= '9' || json[pos] == '.' || json[pos] == '-' || json[pos] == '+' || json[pos] == 'e' || json[pos] == 'E' {
|
||||
pos += 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// if not found number, return false
|
||||
if pos == start {
|
||||
return pos, false
|
||||
}
|
||||
return pos, true
|
||||
}
|
||||
|
||||
|
||||
func isSpace(c byte) bool {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r'
|
||||
}
|
||||
|
||||
// pos is the start index of the raw
|
||||
func ValidNumberFast(raw string) bool {
|
||||
ret := utils.SkipNumber(raw, 0)
|
||||
if ret < 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// check trainling chars
|
||||
for ret < len(raw) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func SkipOneFast2(json string, pos *int) (int, error) {
|
||||
// find the number ending, we pasred in sonic-cpp, it alway valid
|
||||
start := native.SkipOneFast(&json, pos)
|
||||
if start < 0 {
|
||||
return -1, error_syntax(*pos, json, types.ParsingError(-start).Error())
|
||||
}
|
||||
return start, nil
|
||||
}
|
||||
|
||||
func SkipOneFast(json string, pos int) (string, error) {
|
||||
// find the number ending, we pasred in sonic-cpp, it alway valid
|
||||
start := native.SkipOneFast(&json, &pos)
|
||||
if start < 0 {
|
||||
// TODO: details error code
|
||||
return "", error_syntax(pos, json, types.ParsingError(-start).Error())
|
||||
}
|
||||
return json[start:pos], nil
|
||||
}
|
||||
|
||||
func ParseI64(raw string) (int64, error) {
|
||||
i64, err := strconv.ParseInt(raw, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return i64, nil
|
||||
}
|
||||
|
||||
func ParseBool(raw string) (bool, error) {
|
||||
var b bool
|
||||
err := json.Unmarshal([]byte(raw), &b)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func ParseU64(raw string) (uint64, error) {
|
||||
u64, err := strconv.ParseUint(raw, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return u64, nil
|
||||
}
|
||||
|
||||
func ParseF64(raw string) (float64, error) {
|
||||
f64, err := strconv.ParseFloat(raw, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return f64, nil
|
||||
}
|
||||
|
||||
func Unquote(raw string) (string, error) {
|
||||
var u string
|
||||
err := json.Unmarshal([]byte(raw), &u)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return u, nil
|
||||
}
|
169
vendor/github.com/bytedance/sonic/internal/decoder/optdec/interface.go
generated
vendored
Normal file
169
vendor/github.com/bytedance/sonic/internal/decoder/optdec/interface.go
generated
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"unsafe"
|
||||
"reflect"
|
||||
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
type efaceDecoder struct {
|
||||
}
|
||||
|
||||
func (d *efaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*interface{})(vp) = interface{}(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
eface := *(*rt.GoEface)(vp)
|
||||
|
||||
// not pointer type, or nil pointer, or *interface{}
|
||||
if eface.Value == nil || eface.Type.Kind() != reflect.Ptr || rt.PtrElem(eface.Type) == anyType {
|
||||
ret, err := node.AsEface(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*(*interface{})(vp) = ret
|
||||
return nil
|
||||
}
|
||||
|
||||
etp := rt.PtrElem(eface.Type)
|
||||
vp = eface.Value
|
||||
|
||||
/* check the defined pointer type for issue 379 */
|
||||
if eface.Type.IsNamed() {
|
||||
newp := vp
|
||||
etp = eface.Type
|
||||
vp = unsafe.Pointer(&newp)
|
||||
}
|
||||
|
||||
dec, err := findOrCompile(etp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dec.FromDom(vp, node, ctx)
|
||||
}
|
||||
|
||||
type ifaceDecoder struct {
|
||||
typ *rt.GoType
|
||||
}
|
||||
|
||||
func (d *ifaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
iface := *(*rt.GoIface)(vp)
|
||||
if iface.Itab == nil {
|
||||
return error_type(d.typ)
|
||||
}
|
||||
|
||||
vt := iface.Itab.Vt
|
||||
|
||||
// not pointer type, or nil pointer, or *interface{}
|
||||
if vp == nil || vt.Kind() != reflect.Ptr || rt.PtrElem(vt) == anyType {
|
||||
ret, err := node.AsEface(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*(*interface{})(vp) = ret
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
etp := rt.PtrElem(vt)
|
||||
vp = iface.Value
|
||||
|
||||
/* check the defined pointer type for issue 379 */
|
||||
if vt.IsNamed() {
|
||||
newp := vp
|
||||
etp = vt
|
||||
vp = unsafe.Pointer(&newp)
|
||||
}
|
||||
|
||||
dec, err := findOrCompile(etp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dec.FromDom(vp, node, ctx)
|
||||
}
|
||||
|
||||
type unmarshalTextDecoder struct {
|
||||
typ *rt.GoType
|
||||
}
|
||||
|
||||
func (d *unmarshalTextDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
txt, ok := node.AsStringText(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.typ.Pack())
|
||||
}
|
||||
|
||||
v := *(*interface{})(unsafe.Pointer(&rt.GoEface{
|
||||
Type: d.typ,
|
||||
Value: vp,
|
||||
}))
|
||||
|
||||
// fast path
|
||||
if u, ok := v.(encoding.TextUnmarshaler); ok {
|
||||
return u.UnmarshalText(txt)
|
||||
}
|
||||
|
||||
// slow path
|
||||
rv := reflect.ValueOf(v)
|
||||
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
|
||||
return u.UnmarshalText(txt)
|
||||
}
|
||||
|
||||
return error_type(d.typ)
|
||||
}
|
||||
|
||||
type unmarshalJSONDecoder struct {
|
||||
typ *rt.GoType
|
||||
strOpt bool
|
||||
}
|
||||
|
||||
func (d *unmarshalJSONDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
v := *(*interface{})(unsafe.Pointer(&rt.GoEface{
|
||||
Type: d.typ,
|
||||
Value: vp,
|
||||
}))
|
||||
|
||||
var input []byte
|
||||
if d.strOpt && node.IsNull() {
|
||||
input = []byte("null")
|
||||
} else if d.strOpt {
|
||||
s, ok := node.AsStringText(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.typ.Pack())
|
||||
}
|
||||
input = s
|
||||
} else {
|
||||
input = []byte(node.AsRaw(ctx))
|
||||
}
|
||||
|
||||
// fast path
|
||||
if u, ok := v.(json.Unmarshaler); ok {
|
||||
return u.UnmarshalJSON((input))
|
||||
}
|
||||
|
||||
// slow path
|
||||
rv := reflect.ValueOf(v)
|
||||
if u, ok := rv.Interface().(json.Unmarshaler); ok {
|
||||
return u.UnmarshalJSON(input)
|
||||
}
|
||||
|
||||
return error_type(d.typ)
|
||||
}
|
430
vendor/github.com/bytedance/sonic/internal/decoder/optdec/map.go
generated
vendored
Normal file
430
vendor/github.com/bytedance/sonic/internal/decoder/optdec/map.go
generated
vendored
Normal file
@ -0,0 +1,430 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
/** Decoder for most common map types: map[string]interface{}, map[string]string **/
|
||||
|
||||
type mapEfaceDecoder struct {
|
||||
}
|
||||
|
||||
func (d *mapEfaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*map[string]interface{})(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
return node.AsMapEface(ctx, vp)
|
||||
}
|
||||
|
||||
type mapStringDecoder struct {
|
||||
}
|
||||
|
||||
func (d *mapStringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*map[string]string)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
return node.AsMapString(ctx, vp)
|
||||
}
|
||||
|
||||
/** Decoder for map with string key **/
|
||||
|
||||
type mapStrKeyDecoder struct {
|
||||
mapType *rt.GoMapType
|
||||
elemDec decFunc
|
||||
assign rt.MapStrAssign
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
func (d *mapStrKeyDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
obj, ok := node.AsObj()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.mapType.Pack())
|
||||
}
|
||||
|
||||
// allocate map
|
||||
m := *(*unsafe.Pointer)(vp)
|
||||
if m == nil {
|
||||
m = rt.Makemap(&d.mapType.GoType, obj.Len())
|
||||
}
|
||||
|
||||
var gerr error
|
||||
next := obj.Children()
|
||||
for i := 0; i < obj.Len(); i++ {
|
||||
keyn := NewNode(next)
|
||||
key, _ := keyn.AsStr(ctx)
|
||||
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
valp := d.assign(d.mapType, m, key)
|
||||
err := d.elemDec.FromDom(valp, valn, ctx)
|
||||
if gerr == nil && err != nil {
|
||||
gerr = err
|
||||
}
|
||||
next = valn.Next()
|
||||
}
|
||||
|
||||
*(*unsafe.Pointer)(vp) = m
|
||||
return gerr
|
||||
}
|
||||
|
||||
/** Decoder for map with int32 or int64 key **/
|
||||
|
||||
type mapI32KeyDecoder struct {
|
||||
mapType *rt.GoMapType
|
||||
elemDec decFunc
|
||||
assign rt.Map32Assign
|
||||
}
|
||||
|
||||
func (d *mapI32KeyDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
obj, ok := node.AsObj()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.mapType.Pack())
|
||||
}
|
||||
|
||||
// allocate map
|
||||
m := *(*unsafe.Pointer)(vp)
|
||||
if m == nil {
|
||||
m = rt.Makemap(&d.mapType.GoType, obj.Len())
|
||||
}
|
||||
|
||||
next := obj.Children()
|
||||
var gerr error
|
||||
for i := 0; i < obj.Len(); i++ {
|
||||
keyn := NewNode(next)
|
||||
k, ok := keyn.ParseI64(ctx)
|
||||
if !ok || k > math.MaxInt32 || k < math.MinInt32 {
|
||||
if gerr == nil {
|
||||
gerr = error_mismatch(keyn, ctx, d.mapType.Pack())
|
||||
}
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
next = valn.Next()
|
||||
continue
|
||||
}
|
||||
|
||||
key := int32(k)
|
||||
ku32 := *(*uint32)(unsafe.Pointer(&key))
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
valp := d.assign(d.mapType, m, ku32)
|
||||
err := d.elemDec.FromDom(valp, valn, ctx)
|
||||
if gerr == nil && err != nil {
|
||||
gerr = err
|
||||
}
|
||||
|
||||
next = valn.Next()
|
||||
}
|
||||
|
||||
*(*unsafe.Pointer)(vp) = m
|
||||
return gerr
|
||||
}
|
||||
|
||||
type mapI64KeyDecoder struct {
|
||||
mapType *rt.GoMapType
|
||||
elemDec decFunc
|
||||
assign rt.Map64Assign
|
||||
}
|
||||
|
||||
func (d *mapI64KeyDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
obj, ok := node.AsObj()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.mapType.Pack())
|
||||
}
|
||||
|
||||
// allocate map
|
||||
m := *(*unsafe.Pointer)(vp)
|
||||
if m == nil {
|
||||
m = rt.Makemap(&d.mapType.GoType, obj.Len())
|
||||
}
|
||||
|
||||
var gerr error
|
||||
next := obj.Children()
|
||||
for i := 0; i < obj.Len(); i++ {
|
||||
keyn := NewNode(next)
|
||||
key, ok := keyn.ParseI64(ctx)
|
||||
|
||||
if !ok {
|
||||
if gerr == nil {
|
||||
gerr = error_mismatch(keyn, ctx, d.mapType.Pack())
|
||||
}
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
next = valn.Next()
|
||||
continue
|
||||
}
|
||||
|
||||
ku64 := *(*uint64)(unsafe.Pointer(&key))
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
valp := d.assign(d.mapType, m, ku64)
|
||||
err := d.elemDec.FromDom(valp, valn, ctx)
|
||||
if gerr == nil && err != nil {
|
||||
gerr = err
|
||||
}
|
||||
next = valn.Next()
|
||||
}
|
||||
|
||||
*(*unsafe.Pointer)(vp) = m
|
||||
return gerr
|
||||
}
|
||||
|
||||
/** Decoder for map with unt32 or uint64 key **/
|
||||
|
||||
type mapU32KeyDecoder struct {
|
||||
mapType *rt.GoMapType
|
||||
elemDec decFunc
|
||||
assign rt.Map32Assign
|
||||
}
|
||||
|
||||
func (d *mapU32KeyDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
obj, ok := node.AsObj()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.mapType.Pack())
|
||||
}
|
||||
|
||||
// allocate map
|
||||
m := *(*unsafe.Pointer)(vp)
|
||||
if m == nil {
|
||||
m = rt.Makemap(&d.mapType.GoType, obj.Len())
|
||||
}
|
||||
|
||||
var gerr error
|
||||
next := obj.Children()
|
||||
for i := 0; i < obj.Len(); i++ {
|
||||
keyn := NewNode(next)
|
||||
k, ok := keyn.ParseU64(ctx)
|
||||
if !ok || k > math.MaxUint32 {
|
||||
if gerr == nil {
|
||||
gerr = error_mismatch(keyn, ctx, d.mapType.Pack())
|
||||
}
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
next = valn.Next()
|
||||
continue
|
||||
}
|
||||
|
||||
key := uint32(k)
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
valp := d.assign(d.mapType, m, key)
|
||||
err := d.elemDec.FromDom(valp, valn, ctx)
|
||||
if gerr == nil && err != nil {
|
||||
gerr = err
|
||||
}
|
||||
next = valn.Next()
|
||||
}
|
||||
|
||||
*(*unsafe.Pointer)(vp) = m
|
||||
return gerr
|
||||
}
|
||||
|
||||
type mapU64KeyDecoder struct {
|
||||
mapType *rt.GoMapType
|
||||
elemDec decFunc
|
||||
assign rt.Map64Assign
|
||||
}
|
||||
|
||||
func (d *mapU64KeyDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
obj, ok := node.AsObj()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.mapType.Pack())
|
||||
}
|
||||
// allocate map
|
||||
m := *(*unsafe.Pointer)(vp)
|
||||
if m == nil {
|
||||
m = rt.Makemap(&d.mapType.GoType, obj.Len())
|
||||
}
|
||||
|
||||
var gerr error
|
||||
next := obj.Children()
|
||||
for i := 0; i < obj.Len(); i++ {
|
||||
keyn := NewNode(next)
|
||||
key, ok := keyn.ParseU64(ctx)
|
||||
if !ok {
|
||||
if gerr == nil {
|
||||
gerr = error_mismatch(keyn, ctx, d.mapType.Pack())
|
||||
}
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
next = valn.Next()
|
||||
continue
|
||||
}
|
||||
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
valp := d.assign(d.mapType, m, key)
|
||||
err := d.elemDec.FromDom(valp, valn, ctx)
|
||||
if gerr == nil && err != nil {
|
||||
gerr = err
|
||||
}
|
||||
next = valn.Next()
|
||||
}
|
||||
|
||||
*(*unsafe.Pointer)(vp) = m
|
||||
return gerr
|
||||
}
|
||||
|
||||
/** Decoder for generic cases */
|
||||
|
||||
type decKey func(dec *mapDecoder, raw string, ctx *context) (interface{}, error)
|
||||
|
||||
func decodeKeyU8(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
|
||||
key, err := Unquote(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, err := ParseU64(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ret > math.MaxUint8 {
|
||||
return nil, error_value(key, dec.mapType.Key.Pack())
|
||||
}
|
||||
return uint8(ret), nil
|
||||
}
|
||||
|
||||
func decodeKeyU16(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
|
||||
key, err := Unquote(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, err := ParseU64(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ret > math.MaxUint16 {
|
||||
return nil, error_value(key, dec.mapType.Key.Pack())
|
||||
}
|
||||
return uint16(ret), nil
|
||||
}
|
||||
|
||||
func decodeKeyI8(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
|
||||
key, err := Unquote(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, err := ParseI64(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ret > math.MaxInt8 || ret < math.MinInt8 {
|
||||
return nil, error_value(key, dec.mapType.Key.Pack())
|
||||
}
|
||||
return int8(ret), nil
|
||||
}
|
||||
|
||||
func decodeKeyI16(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
|
||||
key, err := Unquote(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, err := ParseI64(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ret > math.MaxInt16 || ret < math.MinInt16 {
|
||||
return nil, error_value(key, dec.mapType.Key.Pack())
|
||||
}
|
||||
return int16(ret), nil
|
||||
}
|
||||
|
||||
func decodeKeyJSONUnmarshaler(dec *mapDecoder, raw string, _ *context) (interface{}, error) {
|
||||
ret := reflect.New(dec.mapType.Key.Pack()).Interface()
|
||||
err := ret.(json.Unmarshaler).UnmarshalJSON([]byte(raw))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func decodeKeyTextUnmarshaler(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
|
||||
key, err := Unquote(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := reflect.New(dec.mapType.Key.Pack()).Interface()
|
||||
err = ret.(encoding.TextUnmarshaler).UnmarshalText([]byte(key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
type mapDecoder struct {
|
||||
mapType *rt.GoMapType
|
||||
keyDec decKey
|
||||
elemDec decFunc
|
||||
}
|
||||
|
||||
func (d *mapDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
obj, ok := node.AsObj()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.mapType.Pack())
|
||||
}
|
||||
|
||||
// allocate map
|
||||
m := *(*unsafe.Pointer)(vp)
|
||||
if m == nil {
|
||||
m = rt.Makemap(&d.mapType.GoType, obj.Len())
|
||||
}
|
||||
|
||||
next := obj.Children()
|
||||
var gerr error
|
||||
for i := 0; i < obj.Len(); i++ {
|
||||
keyn := NewNode(next)
|
||||
raw := keyn.AsRaw(ctx)
|
||||
key, err := d.keyDec(d, raw, ctx)
|
||||
if err != nil {
|
||||
if gerr == nil {
|
||||
gerr = error_mismatch(keyn, ctx, d.mapType.Pack())
|
||||
}
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
next = valn.Next()
|
||||
continue
|
||||
}
|
||||
|
||||
valn := NewNode(PtrOffset(next, 1))
|
||||
keyp := rt.UnpackEface(key).Value
|
||||
valp := rt.Mapassign(d.mapType, m, keyp)
|
||||
err = d.elemDec.FromDom(valp, valn, ctx)
|
||||
if gerr == nil && err != nil {
|
||||
gerr = err
|
||||
}
|
||||
|
||||
next = valn.Next()
|
||||
}
|
||||
|
||||
*(*unsafe.Pointer)(vp) = m
|
||||
return gerr
|
||||
}
|
269
vendor/github.com/bytedance/sonic/internal/decoder/optdec/native.go
generated
vendored
Normal file
269
vendor/github.com/bytedance/sonic/internal/decoder/optdec/native.go
generated
vendored
Normal file
@ -0,0 +1,269 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"sync"
|
||||
|
||||
"github.com/bytedance/sonic/internal/native"
|
||||
"github.com/bytedance/sonic/internal/native/types"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/utf8"
|
||||
)
|
||||
|
||||
|
||||
type ErrorCode int
|
||||
|
||||
const (
|
||||
SONIC_OK = 0;
|
||||
SONIC_CONTROL_CHAR = 1;
|
||||
SONIC_INVALID_ESCAPED = 2;
|
||||
SONIC_INVALID_NUM = 3;
|
||||
SONIC_FLOAT_INF = 4;
|
||||
SONIC_EOF = 5;
|
||||
SONIC_INVALID_CHAR = 6;
|
||||
SONIC_EXPECT_KEY = 7;
|
||||
SONIC_EXPECT_COLON = 8;
|
||||
SONIC_EXPECT_OBJ_COMMA_OR_END = 9;
|
||||
SONIC_EXPECT_ARR_COMMA_OR_END = 10;
|
||||
SONIC_VISIT_FAILED = 11;
|
||||
SONIC_INVALID_ESCAPED_UTF = 12;
|
||||
SONIC_INVALID_LITERAL = 13;
|
||||
SONIC_STACK_OVERFLOW = 14;
|
||||
)
|
||||
|
||||
var ParsingErrors = []string{
|
||||
SONIC_OK : "ok",
|
||||
SONIC_CONTROL_CHAR : "control chars in string",
|
||||
SONIC_INVALID_ESCAPED : "invalid escaped chars in string",
|
||||
SONIC_INVALID_NUM : "invalid number",
|
||||
SONIC_FLOAT_INF : "float infinity",
|
||||
SONIC_EOF : "eof",
|
||||
SONIC_INVALID_CHAR : "invalid chars",
|
||||
SONIC_EXPECT_KEY : "expect a json key",
|
||||
SONIC_EXPECT_COLON : "expect a `:`",
|
||||
SONIC_EXPECT_OBJ_COMMA_OR_END : "expect a `,` or `}`",
|
||||
SONIC_EXPECT_ARR_COMMA_OR_END : "expect a `,` or `]`",
|
||||
SONIC_VISIT_FAILED : "failed in json visitor",
|
||||
SONIC_INVALID_ESCAPED_UTF : "invalid escaped unicodes",
|
||||
SONIC_INVALID_LITERAL : "invalid literal(true/false/null)",
|
||||
SONIC_STACK_OVERFLOW : "json is exceeded max depth 4096, cause stack overflow",
|
||||
}
|
||||
|
||||
func (code ErrorCode) Error() string {
|
||||
return ParsingErrors[code]
|
||||
}
|
||||
|
||||
type node struct {
|
||||
typ uint64
|
||||
val uint64
|
||||
}
|
||||
|
||||
// should consitent with native/parser.c
|
||||
type _nospaceBlock struct {
|
||||
_ [8]byte
|
||||
_ [8]byte
|
||||
}
|
||||
|
||||
// should consitent with native/parser.c
|
||||
type nodeBuf struct {
|
||||
ncur uintptr
|
||||
parent int64
|
||||
depth uint64
|
||||
nstart uintptr
|
||||
nend uintptr
|
||||
stat jsonStat
|
||||
}
|
||||
|
||||
func (self *nodeBuf) init(nodes []node) {
|
||||
self.ncur = uintptr(unsafe.Pointer(&nodes[0]))
|
||||
self.nstart = self.ncur
|
||||
self.nend = self.ncur + uintptr(cap(nodes)) * unsafe.Sizeof(node{})
|
||||
self.parent = -1
|
||||
}
|
||||
|
||||
// should consitent with native/parser.c
|
||||
type Parser struct {
|
||||
Json string
|
||||
padded []byte
|
||||
nodes []node
|
||||
dbuf []byte
|
||||
backup []node
|
||||
|
||||
options uint64
|
||||
// JSON cursor
|
||||
start uintptr
|
||||
cur uintptr
|
||||
end uintptr
|
||||
_nbk _nospaceBlock
|
||||
|
||||
// node buffer cursor
|
||||
nbuf nodeBuf
|
||||
Utf8Inv bool
|
||||
isEface bool
|
||||
}
|
||||
|
||||
// only when parse non-empty object/array are needed.
|
||||
type jsonStat struct {
|
||||
object uint32
|
||||
array uint32
|
||||
str uint32
|
||||
number uint32
|
||||
array_elems uint32
|
||||
object_keys uint32
|
||||
max_depth uint32
|
||||
}
|
||||
|
||||
|
||||
var (
|
||||
defaultJsonPaddedCap uintptr = 1 << 20 // 1 Mb
|
||||
defaultNodesCap uintptr = (1 << 20) / unsafe.Sizeof(node{}) // 1 Mb
|
||||
)
|
||||
|
||||
var parsePool sync.Pool = sync.Pool {
|
||||
New: func () interface{} {
|
||||
return &Parser{
|
||||
options: 0,
|
||||
padded: make([]byte, 0, defaultJsonPaddedCap),
|
||||
nodes: make([]node, defaultNodesCap, defaultNodesCap),
|
||||
dbuf: make([]byte, types.MaxDigitNums, types.MaxDigitNums),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var padding string = "x\"x\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
|
||||
func newParser(data string, pos int, opt uint64) *Parser {
|
||||
p := parsePool.Get().(*Parser)
|
||||
|
||||
/* validate json if needed */
|
||||
if (opt & (1 << _F_validate_string)) != 0 && !utf8.ValidateString(data){
|
||||
dbuf := utf8.CorrectWith(nil, rt.Str2Mem(data[pos:]), "\ufffd")
|
||||
dbuf = append(dbuf, padding...)
|
||||
p.Json = rt.Mem2Str(dbuf[:len(dbuf) - len(padding)])
|
||||
p.Utf8Inv = true
|
||||
p.start = uintptr((*rt.GoString)(unsafe.Pointer(&p.Json)).Ptr)
|
||||
} else {
|
||||
p.Json = data
|
||||
// TODO: prevent too large JSON
|
||||
p.padded = append(p.padded, data[pos:]...)
|
||||
p.padded = append(p.padded, padding...)
|
||||
p.start = uintptr((*rt.GoSlice)(unsafe.Pointer(&p.padded)).Ptr)
|
||||
}
|
||||
|
||||
p.cur = p.start
|
||||
p.end = p.cur + uintptr(len(p.Json))
|
||||
p.options = opt
|
||||
p.nbuf.init(p.nodes)
|
||||
return p
|
||||
}
|
||||
|
||||
|
||||
func (p *Parser) Pos() int {
|
||||
return int(p.cur - p.start)
|
||||
}
|
||||
|
||||
func (p *Parser) JsonBytes() []byte {
|
||||
if p.Utf8Inv {
|
||||
return (rt.Str2Mem(p.Json))
|
||||
} else {
|
||||
return p.padded
|
||||
}
|
||||
}
|
||||
|
||||
var nodeType = rt.UnpackType(reflect.TypeOf(node{}))
|
||||
|
||||
//go:inline
|
||||
func calMaxNodeCap(jsonSize int) int {
|
||||
return jsonSize / 2 + 2
|
||||
}
|
||||
|
||||
func (p *Parser) parse() ErrorCode {
|
||||
// when decode into struct, we should decode number as possible
|
||||
old := p.options
|
||||
if !p.isEface {
|
||||
p.options &^= 1 << _F_use_number
|
||||
}
|
||||
|
||||
// fast path with limited node buffer
|
||||
err := ErrorCode(native.ParseWithPadding(unsafe.Pointer(p)))
|
||||
if err != SONIC_VISIT_FAILED {
|
||||
p.options = old
|
||||
return err
|
||||
}
|
||||
|
||||
// check OoB here
|
||||
offset := p.nbuf.ncur - p.nbuf.nstart
|
||||
curLen := offset / unsafe.Sizeof(node{})
|
||||
if curLen != uintptr(len(p.nodes)) {
|
||||
panic(fmt.Sprintf("current len: %d, real len: %d cap: %d", curLen, len(p.nodes), cap(p.nodes)))
|
||||
}
|
||||
|
||||
// node buf is not enough, continue parse
|
||||
// the maxCap is always meet all valid JSON
|
||||
maxCap := calMaxNodeCap(len(p.Json))
|
||||
slice := rt.GoSlice{
|
||||
Ptr: rt.Mallocgc(uintptr(maxCap) * nodeType.Size, nodeType, false),
|
||||
Len: maxCap,
|
||||
Cap: maxCap,
|
||||
}
|
||||
rt.Memmove(unsafe.Pointer(slice.Ptr), unsafe.Pointer(&p.nodes[0]), offset)
|
||||
p.backup = p.nodes
|
||||
p.nodes = *(*[]node)(unsafe.Pointer(&slice))
|
||||
|
||||
// update node cursor
|
||||
p.nbuf.nstart = uintptr(unsafe.Pointer(&p.nodes[0]))
|
||||
p.nbuf.nend = p.nbuf.nstart + uintptr(cap(p.nodes)) * unsafe.Sizeof(node{})
|
||||
p.nbuf.ncur = p.nbuf.nstart + offset
|
||||
|
||||
// continue parse json
|
||||
err = ErrorCode(native.ParseWithPadding(unsafe.Pointer(p)))
|
||||
p.options = old
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *Parser) reset() {
|
||||
p.options = 0
|
||||
p.padded = p.padded[:0]
|
||||
// nodes is too large here, we will not reset it and use small backup nodes buffer
|
||||
if p.backup != nil {
|
||||
p.nodes = p.backup
|
||||
p.backup = nil
|
||||
}
|
||||
p.start = 0
|
||||
p.cur = 0
|
||||
p.end = 0
|
||||
p.Json = ""
|
||||
p.nbuf = nodeBuf{}
|
||||
p._nbk = _nospaceBlock{}
|
||||
p.Utf8Inv = false
|
||||
p.isEface = false
|
||||
}
|
||||
|
||||
func (p *Parser) free() {
|
||||
p.reset()
|
||||
parsePool.Put(p)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func (p *Parser) fixError(code ErrorCode) error {
|
||||
if code == SONIC_OK {
|
||||
return nil
|
||||
}
|
||||
|
||||
if p.Pos() == 0 {
|
||||
code = SONIC_EOF;
|
||||
}
|
||||
|
||||
pos := p.Pos() - 1
|
||||
return error_syntax(pos, p.Json, ParsingErrors[code])
|
||||
}
|
||||
|
||||
func Parse(data string, opt uint64) error {
|
||||
p := newParser(data, 0, opt)
|
||||
err := p.parse()
|
||||
p.free()
|
||||
return err
|
||||
}
|
1278
vendor/github.com/bytedance/sonic/internal/decoder/optdec/node.go
generated
vendored
Normal file
1278
vendor/github.com/bytedance/sonic/internal/decoder/optdec/node.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
224
vendor/github.com/bytedance/sonic/internal/decoder/optdec/slice.go
generated
vendored
Normal file
224
vendor/github.com/bytedance/sonic/internal/decoder/optdec/slice.go
generated
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
type sliceDecoder struct {
|
||||
elemType *rt.GoType
|
||||
elemDec decFunc
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
var (
|
||||
emptyPtr = &struct{}{}
|
||||
)
|
||||
|
||||
func (d *sliceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||||
return nil
|
||||
}
|
||||
|
||||
arr, ok := node.AsArr()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.typ)
|
||||
}
|
||||
|
||||
slice := rt.MakeSlice(vp, d.elemType, arr.Len())
|
||||
elems := slice.Ptr
|
||||
next := arr.Children()
|
||||
|
||||
var gerr error
|
||||
for i := 0; i < arr.Len(); i++ {
|
||||
val := NewNode(next)
|
||||
elem := unsafe.Pointer(uintptr(elems) + uintptr(i)*d.elemType.Size)
|
||||
err := d.elemDec.FromDom(elem, val, ctx)
|
||||
if gerr == nil && err != nil {
|
||||
gerr = err
|
||||
}
|
||||
next = val.Next()
|
||||
}
|
||||
|
||||
*(*rt.GoSlice)(vp) = *slice
|
||||
return gerr
|
||||
}
|
||||
|
||||
type arrayDecoder struct {
|
||||
len int
|
||||
elemType *rt.GoType
|
||||
elemDec decFunc
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
//go:nocheckptr
|
||||
func (d *arrayDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
arr, ok := node.AsArr()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.typ)
|
||||
}
|
||||
|
||||
next := arr.Children()
|
||||
i := 0
|
||||
|
||||
var gerr error
|
||||
for ; i < d.len && i < arr.Len(); i++ {
|
||||
elem := unsafe.Pointer(uintptr(vp) + uintptr(i)*d.elemType.Size)
|
||||
val := NewNode(next)
|
||||
err := d.elemDec.FromDom(elem, val, ctx)
|
||||
if gerr == nil && err != nil {
|
||||
gerr = err
|
||||
}
|
||||
next = val.Next()
|
||||
}
|
||||
|
||||
/* zero rest of array */
|
||||
ptr := unsafe.Pointer(uintptr(vp) + uintptr(i)*d.elemType.Size)
|
||||
n := uintptr(d.len-i) * d.elemType.Size
|
||||
rt.ClearMemory(d.elemType, ptr, n)
|
||||
return gerr
|
||||
}
|
||||
|
||||
type sliceEfaceDecoder struct {
|
||||
}
|
||||
|
||||
func (d *sliceEfaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||||
return nil
|
||||
}
|
||||
|
||||
return node.AsSliceEface(ctx, vp)
|
||||
}
|
||||
|
||||
type sliceI32Decoder struct {
|
||||
}
|
||||
|
||||
func (d *sliceI32Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||||
return nil
|
||||
}
|
||||
|
||||
return node.AsSliceI32(ctx, vp)
|
||||
}
|
||||
|
||||
type sliceI64Decoder struct {
|
||||
}
|
||||
|
||||
func (d *sliceI64Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||||
return nil
|
||||
}
|
||||
|
||||
return node.AsSliceI64(ctx, vp)
|
||||
}
|
||||
|
||||
type sliceU32Decoder struct {
|
||||
}
|
||||
|
||||
func (d *sliceU32Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||||
return nil
|
||||
}
|
||||
|
||||
return node.AsSliceU32(ctx, vp)
|
||||
}
|
||||
|
||||
type sliceU64Decoder struct {
|
||||
}
|
||||
|
||||
func (d *sliceU64Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||||
return nil
|
||||
}
|
||||
|
||||
return node.AsSliceU64(ctx, vp)
|
||||
}
|
||||
|
||||
type sliceStringDecoder struct {
|
||||
}
|
||||
|
||||
func (d *sliceStringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||||
return nil
|
||||
}
|
||||
|
||||
return node.AsSliceString(ctx, vp)
|
||||
}
|
||||
|
||||
type sliceBytesDecoder struct {
|
||||
}
|
||||
|
||||
func (d *sliceBytesDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||||
return nil
|
||||
}
|
||||
|
||||
s, err := node.AsSliceBytes(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*(*[]byte)(vp) = s
|
||||
return nil
|
||||
}
|
||||
|
||||
type sliceBytesUnmarshalerDecoder struct {
|
||||
elemType *rt.GoType
|
||||
elemDec decFunc
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
func (d *sliceBytesUnmarshalerDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* parse JSON string into `[]byte` */
|
||||
if node.IsStr() {
|
||||
slice, err := node.AsSliceBytes(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*(*[]byte)(vp) = slice
|
||||
return nil
|
||||
}
|
||||
|
||||
/* parse JSON array into `[]byte` */
|
||||
arr, ok := node.AsArr()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.typ)
|
||||
}
|
||||
|
||||
slice := rt.MakeSlice(vp, d.elemType, arr.Len())
|
||||
elems := slice.Ptr
|
||||
|
||||
var gerr error
|
||||
next := arr.Children()
|
||||
for i := 0; i < arr.Len(); i++ {
|
||||
child := NewNode(next)
|
||||
elem := unsafe.Pointer(uintptr(elems) + uintptr(i)*d.elemType.Size)
|
||||
err := d.elemDec.FromDom(elem, child, ctx)
|
||||
if gerr == nil && err != nil {
|
||||
gerr = err
|
||||
}
|
||||
next = child.Next()
|
||||
}
|
||||
|
||||
*(*rt.GoSlice)(vp) = *slice
|
||||
return gerr
|
||||
}
|
360
vendor/github.com/bytedance/sonic/internal/decoder/optdec/stringopts.go
generated
vendored
Normal file
360
vendor/github.com/bytedance/sonic/internal/decoder/optdec/stringopts.go
generated
vendored
Normal file
@ -0,0 +1,360 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
type ptrStrDecoder struct {
|
||||
typ *rt.GoType
|
||||
deref decFunc
|
||||
}
|
||||
|
||||
// Pointer Value is allocated in the Caller
|
||||
func (d *ptrStrDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
s, ok := node.AsStrRef(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, stringType)
|
||||
}
|
||||
|
||||
if s == "null" {
|
||||
*(*unsafe.Pointer)(vp) = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if *(*unsafe.Pointer)(vp) == nil {
|
||||
*(*unsafe.Pointer)(vp) = rt.Mallocgc(d.typ.Size, d.typ, true)
|
||||
}
|
||||
|
||||
return d.deref.FromDom(*(*unsafe.Pointer)(vp), node, ctx)
|
||||
}
|
||||
|
||||
type boolStringDecoder struct {
|
||||
}
|
||||
|
||||
func (d *boolStringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
s, ok := node.AsStrRef(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, stringType)
|
||||
}
|
||||
|
||||
if s == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
b, err := ParseBool(s)
|
||||
if err != nil {
|
||||
return error_mismatch(node, ctx, boolType)
|
||||
}
|
||||
|
||||
*(*bool)(vp) = b
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseI64(node Node, ctx *context) (int64, error, bool) {
|
||||
if node.IsNull() {
|
||||
return 0, nil, true
|
||||
}
|
||||
|
||||
s, ok := node.AsStrRef(ctx)
|
||||
if !ok {
|
||||
return 0, error_mismatch(node, ctx, stringType), false
|
||||
}
|
||||
|
||||
if s == "null" {
|
||||
return 0, nil, true
|
||||
}
|
||||
|
||||
ret, err := ParseI64(s)
|
||||
return ret, err, false
|
||||
}
|
||||
|
||||
type i8StringDecoder struct{}
|
||||
|
||||
func (d *i8StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
ret, err, null := parseI64(node, ctx)
|
||||
if null {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ret > math.MaxInt8 || ret < math.MinInt8 {
|
||||
return error_mismatch(node, ctx, int8Type)
|
||||
}
|
||||
|
||||
*(*int8)(vp) = int8(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type i16StringDecoder struct{}
|
||||
|
||||
func (d *i16StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
ret, err, null := parseI64(node, ctx)
|
||||
if null {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ret > math.MaxInt16 || ret < math.MinInt16 {
|
||||
return error_mismatch(node, ctx, int16Type)
|
||||
}
|
||||
|
||||
*(*int16)(vp) = int16(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type i32StringDecoder struct{}
|
||||
|
||||
func (d *i32StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
ret, err, null := parseI64(node, ctx)
|
||||
if null {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ret > math.MaxInt32 || ret < math.MinInt32 {
|
||||
return error_mismatch(node, ctx, int32Type)
|
||||
}
|
||||
|
||||
*(*int32)(vp) = int32(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type i64StringDecoder struct{}
|
||||
|
||||
func (d *i64StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
ret, err, null := parseI64(node, ctx)
|
||||
if null {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*(*int64)(vp) = int64(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseU64(node Node, ctx *context) (uint64, error, bool) {
|
||||
if node.IsNull() {
|
||||
return 0, nil, true
|
||||
}
|
||||
|
||||
s, ok := node.AsStrRef(ctx)
|
||||
if !ok {
|
||||
return 0, error_mismatch(node, ctx, stringType), false
|
||||
}
|
||||
|
||||
if s == "null" {
|
||||
return 0, nil, true
|
||||
}
|
||||
|
||||
ret, err := ParseU64(s)
|
||||
return ret, err, false
|
||||
}
|
||||
|
||||
type u8StringDecoder struct{}
|
||||
|
||||
func (d *u8StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
ret, err, null := parseU64(node, ctx)
|
||||
if null {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ret > math.MaxUint8 {
|
||||
return error_mismatch(node, ctx, uint8Type)
|
||||
}
|
||||
|
||||
*(*uint8)(vp) = uint8(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type u16StringDecoder struct{}
|
||||
|
||||
func (d *u16StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
ret, err, null := parseU64(node, ctx)
|
||||
if null {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ret > math.MaxUint16 {
|
||||
return error_mismatch(node, ctx, uint16Type)
|
||||
}
|
||||
|
||||
*(*uint16)(vp) = uint16(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type u32StringDecoder struct{}
|
||||
|
||||
func (d *u32StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
ret, err, null := parseU64(node, ctx)
|
||||
if null {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ret > math.MaxUint32 {
|
||||
return error_mismatch(node, ctx, uint32Type)
|
||||
}
|
||||
|
||||
*(*uint32)(vp) = uint32(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
type u64StringDecoder struct{}
|
||||
|
||||
func (d *u64StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
ret, err, null := parseU64(node, ctx)
|
||||
if null {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*(*uint64)(vp) = uint64(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type f32StringDecoder struct{}
|
||||
|
||||
func (d *f32StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
s, ok := node.AsStrRef(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, stringType)
|
||||
}
|
||||
|
||||
if s == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, err := ParseF64(s)
|
||||
if err != nil || ret > math.MaxFloat32 || ret < -math.MaxFloat32 {
|
||||
return error_mismatch(node, ctx, float32Type)
|
||||
}
|
||||
|
||||
*(*float32)(vp) = float32(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
type f64StringDecoder struct{}
|
||||
|
||||
func (d *f64StringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
s, ok := node.AsStrRef(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, stringType)
|
||||
}
|
||||
|
||||
if s == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, err := ParseF64(s)
|
||||
if err != nil {
|
||||
return error_mismatch(node, ctx, float64Type)
|
||||
}
|
||||
|
||||
*(*float64)(vp) = float64(ret)
|
||||
return nil
|
||||
}
|
||||
|
||||
/* parse string field with string options */
|
||||
type strStringDecoder struct{}
|
||||
|
||||
func (d *strStringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
s, ok := node.AsStrRef(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, stringType)
|
||||
}
|
||||
|
||||
if s == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
s, err := Unquote(s)
|
||||
if err != nil {
|
||||
return error_mismatch(node, ctx, stringType)
|
||||
}
|
||||
|
||||
*(*string)(vp) = s
|
||||
return nil
|
||||
}
|
||||
|
||||
type numberStringDecoder struct{}
|
||||
|
||||
func (d *numberStringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
s, ok := node.AsStrRef(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, stringType)
|
||||
}
|
||||
|
||||
if s == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
num, ok := node.ParseNumber(ctx)
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, jsonNumberType)
|
||||
}
|
||||
|
||||
end, ok := SkipNumberFast(s, 0)
|
||||
// has error or trailing chars
|
||||
if !ok || end != len(s) {
|
||||
return error_mismatch(node, ctx, jsonNumberType)
|
||||
}
|
||||
|
||||
*(*json.Number)(vp) = json.Number(num)
|
||||
return nil
|
||||
}
|
61
vendor/github.com/bytedance/sonic/internal/decoder/optdec/structs.go
generated
vendored
Normal file
61
vendor/github.com/bytedance/sonic/internal/decoder/optdec/structs.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
caching "github.com/bytedance/sonic/internal/optcaching"
|
||||
"github.com/bytedance/sonic/internal/resolver"
|
||||
)
|
||||
|
||||
type fieldEntry struct {
|
||||
resolver.FieldMeta
|
||||
fieldDec decFunc
|
||||
}
|
||||
|
||||
type structDecoder struct {
|
||||
fieldMap caching.FieldLookup
|
||||
fields []fieldEntry
|
||||
structName string
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
func (d *structDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||||
if node.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
var gerr error
|
||||
obj, ok := node.AsObj()
|
||||
if !ok {
|
||||
return error_mismatch(node, ctx, d.typ)
|
||||
}
|
||||
|
||||
next := obj.Children()
|
||||
for i := 0; i < obj.Len(); i++ {
|
||||
key, _ := NewNode(next).AsStrRef(ctx)
|
||||
val := NewNode(PtrOffset(next, 1))
|
||||
next = val.Next()
|
||||
|
||||
// find field idx
|
||||
idx := d.fieldMap.Get(key)
|
||||
if idx == -1 {
|
||||
if Options(ctx.Options())&OptionDisableUnknown != 0 {
|
||||
return error_field(key)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
offset := d.fields[idx].Path[0].Size
|
||||
elem := unsafe.Pointer(uintptr(vp) + offset)
|
||||
err := d.fields[idx].fieldDec.FromDom(elem, val, ctx)
|
||||
|
||||
// deal with mismatch type errors
|
||||
if gerr == nil && err != nil {
|
||||
// TODO: better error info
|
||||
gerr = err
|
||||
}
|
||||
}
|
||||
return gerr
|
||||
}
|
||||
|
60
vendor/github.com/bytedance/sonic/internal/decoder/optdec/types.go
generated
vendored
Normal file
60
vendor/github.com/bytedance/sonic/internal/decoder/optdec/types.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2021 ByteDance Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package optdec
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
var (
|
||||
boolType = reflect.TypeOf(bool(false))
|
||||
byteType = reflect.TypeOf(byte(0))
|
||||
intType = reflect.TypeOf(int(0))
|
||||
int8Type = reflect.TypeOf(int8(0))
|
||||
int16Type = reflect.TypeOf(int16(0))
|
||||
int32Type = reflect.TypeOf(int32(0))
|
||||
int64Type = reflect.TypeOf(int64(0))
|
||||
uintType = reflect.TypeOf(uint(0))
|
||||
uint8Type = reflect.TypeOf(uint8(0))
|
||||
uint16Type = reflect.TypeOf(uint16(0))
|
||||
uint32Type = reflect.TypeOf(uint32(0))
|
||||
uint64Type = reflect.TypeOf(uint64(0))
|
||||
float32Type = reflect.TypeOf(float32(0))
|
||||
float64Type = reflect.TypeOf(float64(0))
|
||||
stringType = reflect.TypeOf("")
|
||||
bytesType = reflect.TypeOf([]byte(nil))
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
base64CorruptInputError = reflect.TypeOf(base64.CorruptInputError(0))
|
||||
anyType = rt.UnpackType(reflect.TypeOf((*interface{})(nil)).Elem())
|
||||
)
|
||||
|
||||
var (
|
||||
errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
||||
encodingTextUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
func rtype(t reflect.Type) (*rt.GoItab, *rt.GoType) {
|
||||
p := (*rt.GoIface)(unsafe.Pointer(&t))
|
||||
return p.Itab, (*rt.GoType)(p.Value)
|
||||
}
|
Reference in New Issue
Block a user