Merge pull request #23 from goccy/feature/fix-disallow-unknown-fields

Fix implementation of DisallowUnknownFields for improvement performance
This commit is contained in:
Masaaki Goshima 2020-08-14 18:16:08 +09:00 committed by GitHub
commit 901128a986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 18 additions and 74 deletions

View File

@ -18,7 +18,6 @@ func (d Delim) String() string {
type decoder interface {
decode([]byte, int64, uintptr) (int64, error)
decodeStream(*stream, uintptr) error
setDisallowUnknownFields(bool)
}
type Decoder struct {
@ -99,7 +98,6 @@ func (d *Decoder) decode(src []byte, header *interfaceHeader) error {
cachedDecoder.set(typeptr, compiledDec)
dec = compiledDec
}
dec.setDisallowUnknownFields(d.disallowUnknownFields)
if _, err := dec.decode(src, 0, ptr); err != nil {
return err
}
@ -164,7 +162,6 @@ func (d *Decoder) Decode(v interface{}) error {
cachedDecoder.set(typeptr, compiledDec)
dec = compiledDec
}
dec.setDisallowUnknownFields(d.disallowUnknownFields)
if err := d.prepareForDecode(); err != nil {
return err
}
@ -252,7 +249,7 @@ func (d *Decoder) Token() (Token, error) {
// is a struct and the input contains object keys which do not match any
// non-ignored, exported fields in the destination.
func (d *Decoder) DisallowUnknownFields() {
d.disallowUnknownFields = true
d.s.disallowUnknownFields = true
}
func (d *Decoder) InputOffset() int64 {

View File

@ -16,10 +16,6 @@ func newArrayDecoder(dec decoder, elemType *rtype, alen int) *arrayDecoder {
}
}
func (d *arrayDecoder) setDisallowUnknownFields(disallowUnknownFields bool) {
d.valueDecoder.setDisallowUnknownFields(disallowUnknownFields)
}
func (d *arrayDecoder) decodeStream(s *stream, p uintptr) error {
for {
switch s.char() {

View File

@ -58,8 +58,6 @@ func falseBytes(s *stream) error {
return nil
}
func (d *boolDecoder) setDisallowUnknownFields(_ bool) {}
func (d *boolDecoder) decodeStream(s *stream, p uintptr) error {
s.skipWhiteSpace()
for {

View File

@ -47,8 +47,6 @@ func floatBytes(s *stream) []byte {
return s.buf[start:s.cursor]
}
func (d *floatDecoder) setDisallowUnknownFields(_ bool) {}
func (d *floatDecoder) decodeStreamByte(s *stream) ([]byte, error) {
for {
switch s.char() {

View File

@ -49,8 +49,6 @@ var (
}
)
func (d *intDecoder) setDisallowUnknownFields(_ bool) {}
func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
for {
switch s.char() {

View File

@ -6,9 +6,8 @@ import (
)
type interfaceDecoder struct {
typ *rtype
dummy unsafe.Pointer // for escape value
disallowUnknownFields bool
typ *rtype
dummy unsafe.Pointer // for escape value
}
func newInterfaceDecoder(typ *rtype) *interfaceDecoder {
@ -17,10 +16,6 @@ func newInterfaceDecoder(typ *rtype) *interfaceDecoder {
}
}
func (d *interfaceDecoder) setDisallowUnknownFields(disallowUnknownFields bool) {
d.disallowUnknownFields = disallowUnknownFields
}
func (d *interfaceDecoder) numDecoder(s *stream) decoder {
if s.useNumber {
return newNumberDecoder(func(p uintptr, v Number) {
@ -46,13 +41,11 @@ func (d *interfaceDecoder) decodeStream(s *stream, p uintptr) error {
var v map[interface{}]interface{}
ptr := unsafe.Pointer(&v)
d.dummy = ptr
dec := newMapDecoder(
if err := newMapDecoder(
interfaceMapType,
newInterfaceDecoder(d.typ),
newInterfaceDecoder(d.typ),
)
dec.setDisallowUnknownFields(d.disallowUnknownFields)
if err := dec.decodeStream(s, uintptr(ptr)); err != nil {
).decodeStream(s, uintptr(ptr)); err != nil {
return err
}
*(*interface{})(unsafe.Pointer(p)) = v
@ -61,13 +54,11 @@ func (d *interfaceDecoder) decodeStream(s *stream, p uintptr) error {
var v []interface{}
ptr := unsafe.Pointer(&v)
d.dummy = ptr // escape ptr
dec := newSliceDecoder(
if err := newSliceDecoder(
newInterfaceDecoder(d.typ),
d.typ,
d.typ.Size(),
)
dec.setDisallowUnknownFields(d.disallowUnknownFields)
if err := dec.decodeStream(s, uintptr(ptr)); err != nil {
).decodeStream(s, uintptr(ptr)); err != nil {
return err
}
*(*interface{})(unsafe.Pointer(p)) = v
@ -135,7 +126,6 @@ func (d *interfaceDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, e
newInterfaceDecoder(d.typ),
newInterfaceDecoder(d.typ),
)
dec.setDisallowUnknownFields(d.disallowUnknownFields)
cursor, err := dec.decode(buf, cursor, uintptr(ptr))
if err != nil {
return 0, err
@ -151,7 +141,6 @@ func (d *interfaceDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, e
d.typ,
d.typ.Size(),
)
dec.setDisallowUnknownFields(d.disallowUnknownFields)
cursor, err := dec.decode(buf, cursor, uintptr(ptr))
if err != nil {
return 0, err

View File

@ -26,11 +26,6 @@ func makemap(*rtype, int) unsafe.Pointer
//go:noescape
func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
func (d *mapDecoder) setDisallowUnknownFields(disallowUnknownFields bool) {
d.keyDecoder.setDisallowUnknownFields(disallowUnknownFields)
d.valueDecoder.setDisallowUnknownFields(disallowUnknownFields)
}
func (d *mapDecoder) setKey(buf []byte, cursor int64, key interface{}) (int64, error) {
header := (*interfaceHeader)(unsafe.Pointer(&key))
return d.keyDecoder.decode(buf, cursor, uintptr(header.ptr))

View File

@ -16,8 +16,6 @@ func newNumberDecoder(op func(uintptr, Number)) *numberDecoder {
}
}
func (d *numberDecoder) setDisallowUnknownFields(_ bool) {}
func (d *numberDecoder) decodeStream(s *stream, p uintptr) error {
bytes, err := d.floatDecoder.decodeStreamByte(s)
if err != nil {

View File

@ -16,10 +16,6 @@ func newPtrDecoder(dec decoder, typ *rtype) *ptrDecoder {
//go:linkname unsafe_New reflect.unsafe_New
func unsafe_New(*rtype) uintptr
func (d *ptrDecoder) setDisallowUnknownFields(disallowUnknownFields bool) {
d.dec.setDisallowUnknownFields(disallowUnknownFields)
}
func (d *ptrDecoder) decodeStream(s *stream, p uintptr) error {
newptr := unsafe_New(d.typ)
if err := d.dec.decodeStream(s, newptr); err != nil {

View File

@ -56,10 +56,6 @@ func copySlice(elemType *rtype, dst, src reflect.SliceHeader) int
//go:linkname newArray reflect.unsafe_NewArray
func newArray(*rtype, int) unsafe.Pointer
func (d *sliceDecoder) setDisallowUnknownFields(disallowUnknownFields bool) {
d.valueDecoder.setDisallowUnknownFields(disallowUnknownFields)
}
func (d *sliceDecoder) decodeStream(s *stream, p uintptr) error {
for {
switch s.char() {

View File

@ -10,13 +10,14 @@ const (
)
type stream struct {
buf []byte
length int64
r io.Reader
offset int64
cursor int64
allRead bool
useNumber bool
buf []byte
length int64
r io.Reader
offset int64
cursor int64
allRead bool
useNumber bool
disallowUnknownFields bool
}
func (s *stream) buffered() io.Reader {

View File

@ -11,8 +11,6 @@ func newStringDecoder() *stringDecoder {
return &stringDecoder{}
}
func (d *stringDecoder) setDisallowUnknownFields(_ bool) {}
func (d *stringDecoder) decodeStream(s *stream, p uintptr) error {
bytes, err := d.decodeStreamByte(s)
if err != nil {

View File

@ -11,9 +11,8 @@ type structFieldSet struct {
}
type structDecoder struct {
fieldMap map[string]*structFieldSet
keyDecoder *stringDecoder
disallowUnknownFields bool
fieldMap map[string]*structFieldSet
keyDecoder *stringDecoder
}
func newStructDecoder(fieldMap map[string]*structFieldSet) *structDecoder {
@ -23,13 +22,6 @@ func newStructDecoder(fieldMap map[string]*structFieldSet) *structDecoder {
}
}
func (d *structDecoder) setDisallowUnknownFields(disallowUnknownFields bool) {
d.disallowUnknownFields = disallowUnknownFields
for _, field := range d.fieldMap {
field.dec.setDisallowUnknownFields(disallowUnknownFields)
}
}
func (d *structDecoder) decodeStream(s *stream, p uintptr) error {
s.skipWhiteSpace()
if s.char() == nul {
@ -65,7 +57,7 @@ func (d *structDecoder) decodeStream(s *stream, p uintptr) error {
if err := field.dec.decodeStream(s, p+field.offset); err != nil {
return err
}
} else if d.disallowUnknownFields {
} else if s.disallowUnknownFields {
return fmt.Errorf("json: unknown field %q", k)
} else {
if err := s.skipValue(); err != nil {
@ -121,8 +113,6 @@ func (d *structDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, erro
return 0, err
}
cursor = c
} else if d.disallowUnknownFields {
return 0, fmt.Errorf("json: unknown field %q", k)
} else {
c, err := skipValue(buf, cursor)
if err != nil {

View File

@ -24,8 +24,6 @@ func (d *uintDecoder) parseUint(b []byte) uint64 {
return sum
}
func (d *uintDecoder) setDisallowUnknownFields(_ bool) {}
func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
for {
switch s.char() {

View File

@ -12,8 +12,6 @@ func newUnmarshalJSONDecoder(typ *rtype) *unmarshalJSONDecoder {
return &unmarshalJSONDecoder{typ: typ}
}
func (d *unmarshalJSONDecoder) setDisallowUnknownFields(_ bool) {}
func (d *unmarshalJSONDecoder) decodeStream(s *stream, p uintptr) error {
s.skipWhiteSpace()
start := s.cursor

View File

@ -13,8 +13,6 @@ func newUnmarshalTextDecoder(typ *rtype) *unmarshalTextDecoder {
return &unmarshalTextDecoder{typ: typ}
}
func (d *unmarshalTextDecoder) setDisallowUnknownFields(_ bool) {}
func (d *unmarshalTextDecoder) decodeStream(s *stream, p uintptr) error {
s.skipWhiteSpace()
start := s.cursor