You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
4.8 KiB
Go
203 lines
4.8 KiB
Go
package stt
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"github.com/modern-go/reflect2"
|
|
"io"
|
|
"strings"
|
|
"unsafe"
|
|
)
|
|
|
|
func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder {
|
|
bindings := map[string]*Binding{}
|
|
structDescriptor := describeStruct(ctx, typ)
|
|
for _, binding := range structDescriptor.Fields {
|
|
for _, fromName := range binding.FromNames {
|
|
old := bindings[fromName]
|
|
if old == nil {
|
|
bindings[fromName] = binding
|
|
continue
|
|
}
|
|
ignoreOld, ignoreNew := resolveConflictBinding(ctx.frozenConfig, old, binding)
|
|
if ignoreOld {
|
|
delete(bindings, fromName)
|
|
}
|
|
if !ignoreNew {
|
|
bindings[fromName] = binding
|
|
}
|
|
}
|
|
}
|
|
fields := map[string]*structFieldDecoder{}
|
|
for k, binding := range bindings {
|
|
fields[k] = binding.Decoder.(*structFieldDecoder)
|
|
}
|
|
return createStructDecoder(ctx, typ, fields)
|
|
}
|
|
|
|
func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structFieldDecoder) ValDecoder {
|
|
switch len(fields) {
|
|
case 0:
|
|
return &skipObjectDecoder{typ}
|
|
}
|
|
return &generalStructDecoder{typ, fields}
|
|
}
|
|
|
|
type generalStructDecoder struct {
|
|
typ reflect2.Type
|
|
fields map[string]*structFieldDecoder
|
|
}
|
|
|
|
func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|
if !iter.incrementDepth() {
|
|
return
|
|
}
|
|
var splitBytes = encryptBytes([]byte{'/'}, iter.depth)
|
|
cc := splitBytes
|
|
var c byte = '/'
|
|
for {
|
|
if iter.head >= iter.tail {
|
|
break
|
|
}
|
|
if iter.depth > 1 {
|
|
if bytes.Equal(cc, splitBytes) {
|
|
nc := iter.nextToken()
|
|
iter.unreadByte()
|
|
if nc != '/' && nc != '@' {
|
|
decoder.decodeOneField(ptr, iter)
|
|
cc = cc[:0]
|
|
for i, sbLen := 0, len(splitBytes); i < sbLen; i++ {
|
|
cc = append(cc, iter.nextToken())
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
} else {
|
|
cc = cc[:1]
|
|
for i, sbLen := 0, len(splitBytes); i < sbLen; i++ {
|
|
cc = append(cc, iter.nextToken())
|
|
}
|
|
continue
|
|
}
|
|
} else {
|
|
if c == '/' {
|
|
nc := iter.nextToken()
|
|
iter.unreadByte()
|
|
if nc != '/' {
|
|
decoder.decodeOneField(ptr, iter)
|
|
c = iter.nextToken()
|
|
} else {
|
|
break
|
|
}
|
|
} else {
|
|
c = iter.nextToken()
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
if iter.Error != nil && iter.Error != io.EOF && len(decoder.typ.Type1().Name()) != 0 {
|
|
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
|
|
}
|
|
if c != '/' {
|
|
iter.ReportError("struct Decode", `expect /, but found `+string([]byte{c}))
|
|
}
|
|
iter.decrementDepth()
|
|
}
|
|
|
|
func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *Iterator) {
|
|
var field string
|
|
var fieldDecoder *structFieldDecoder
|
|
|
|
field = iter.ReadFieldName()
|
|
fieldDecoder = decoder.fields[field]
|
|
if fieldDecoder == nil && !iter.cfg.caseSensitive {
|
|
fieldDecoder = decoder.fields[strings.ToLower(field)]
|
|
}
|
|
|
|
if fieldDecoder == nil {
|
|
c := iter.nextToken()
|
|
if c != '@' {
|
|
iter.ReportError("ReadObject", "expect @ after object field, but found "+string([]byte{c}))
|
|
}
|
|
iter.skipBytes('=')
|
|
iter.Skip()
|
|
return
|
|
}
|
|
c := iter.nextToken()
|
|
if c != '@' {
|
|
iter.ReportError("ReadObject", "expect @ after object field, but found "+string([]byte{c}))
|
|
}
|
|
iter.unreadByte()
|
|
if iter.depth > 1 {
|
|
iter.skipBytes(encryptBytes([]byte("@="), iter.depth)...)
|
|
} else {
|
|
iter.skipBytes('@', '=')
|
|
}
|
|
fieldDecoder.Decode(ptr, iter)
|
|
}
|
|
|
|
type skipObjectDecoder struct {
|
|
typ reflect2.Type
|
|
}
|
|
|
|
func (decoder *skipObjectDecoder) Decode(_ unsafe.Pointer, iter *Iterator) {
|
|
valueType := iter.WhatIsNext()
|
|
if valueType != NilValue {
|
|
iter.ReportError("skipObjectDecoder", "expect object or null")
|
|
return
|
|
}
|
|
iter.Skip()
|
|
}
|
|
|
|
type structFieldDecoder struct {
|
|
field reflect2.StructField
|
|
fieldDecoder ValDecoder
|
|
}
|
|
|
|
func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|
fieldPtr := decoder.field.UnsafeGet(ptr)
|
|
decoder.fieldDecoder.Decode(fieldPtr, iter)
|
|
if iter.Error != nil && iter.Error != io.EOF {
|
|
iter.Error = fmt.Errorf("%s: %s", decoder.field.Name(), iter.Error.Error())
|
|
}
|
|
}
|
|
|
|
type stringModeStringDecoder struct {
|
|
elemDecoder ValDecoder
|
|
cfg *frozenConfig
|
|
}
|
|
|
|
func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|
decoder.elemDecoder.Decode(ptr, iter)
|
|
str := *((*string)(ptr))
|
|
tempIter := decoder.cfg.BorrowIterator([]byte(str))
|
|
defer decoder.cfg.ReturnIterator(tempIter)
|
|
*((*string)(ptr)) = tempIter.ReadString()
|
|
}
|
|
|
|
type stringModeNumberDecoder struct {
|
|
elemDecoder ValDecoder
|
|
}
|
|
|
|
func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|
if iter.WhatIsNext() == NilValue {
|
|
decoder.elemDecoder.Decode(ptr, iter)
|
|
return
|
|
}
|
|
|
|
c := iter.nextToken()
|
|
if c != '"' {
|
|
iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
decoder.elemDecoder.Decode(ptr, iter)
|
|
if iter.Error != nil {
|
|
return
|
|
}
|
|
c = iter.readByte()
|
|
if c != '"' {
|
|
iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
}
|