Fix algorithm of struct field detection

This commit is contained in:
Masaaki Goshima 2021-02-06 20:07:01 +09:00
parent a75b5e9d93
commit 0c1e7c61e0
2 changed files with 49 additions and 17 deletions

View File

@ -260,6 +260,8 @@ func (d *Decoder) removeConflictFields(fieldMap map[string]*structFieldSet, conf
dec: v.dec,
offset: baseOffset + v.offset,
isTaggedKey: v.isTaggedKey,
key: k,
keyLen: int64(len(k)),
}
fieldMap[k] = fieldSet
lower := strings.ToLower(k)
@ -282,6 +284,8 @@ func (d *Decoder) removeConflictFields(fieldMap map[string]*structFieldSet, conf
dec: v.dec,
offset: baseOffset + v.offset,
isTaggedKey: v.isTaggedKey,
key: k,
keyLen: int64(len(k)),
}
fieldMap[k] = fieldSet
lower := strings.ToLower(k)
@ -345,6 +349,8 @@ func (d *Decoder) compileStruct(typ *rtype, structName, fieldName string) (decod
dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec),
offset: field.Offset,
isTaggedKey: v.isTaggedKey,
key: k,
keyLen: int64(len(k)),
}
fieldMap[k] = fieldSet
lower := strings.ToLower(k)
@ -367,6 +373,8 @@ func (d *Decoder) compileStruct(typ *rtype, structName, fieldName string) (decod
dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec),
offset: field.Offset,
isTaggedKey: v.isTaggedKey,
key: k,
keyLen: int64(len(k)),
}
fieldMap[k] = fieldSet
lower := strings.ToLower(k)
@ -388,22 +396,26 @@ func (d *Decoder) compileStruct(typ *rtype, structName, fieldName string) (decod
if tag.isString {
dec = newWrappedStringDecoder(dec, structName, field.Name)
}
fieldSet := &structFieldSet{dec: dec, offset: field.Offset, isTaggedKey: tag.isTaggedKey}
var key string
if tag.key != "" {
fieldMap[tag.key] = fieldSet
lower := strings.ToLower(tag.key)
if _, exists := fieldMap[lower]; !exists {
fieldMap[lower] = fieldSet
}
key = tag.key
} else {
fieldMap[field.Name] = fieldSet
lower := strings.ToLower(field.Name)
key = field.Name
}
fieldSet := &structFieldSet{
dec: dec,
offset: field.Offset,
isTaggedKey: tag.isTaggedKey,
key: key,
keyLen: int64(len(key)),
}
fieldMap[key] = fieldSet
lower := strings.ToLower(key)
if _, exists := fieldMap[lower]; !exists {
fieldMap[lower] = fieldSet
}
}
}
}
delete(d.structTypeToDecoder, typeptr)
structDec.tryOptimize()
return structDec, nil

View File

@ -12,6 +12,8 @@ type structFieldSet struct {
dec decoder
offset uintptr
isTaggedKey bool
key string
keyLen int64
}
type structDecoder struct {
@ -157,6 +159,7 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
keyIdx := 0
bitmap := d.keyBitmapInt8
keyBitmapLen := len(bitmap)
start := cursor
for {
c := char(b, cursor)
switch c {
@ -164,7 +167,12 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
x := uint64(curBit & -curBit)
fieldSetIndex := bitHashTable[(x*0x03F566ED27179461)>>58]
field = d.sortedFieldSets[fieldSetIndex]
keyLen := cursor - start
cursor++
if keyLen < field.keyLen {
// early match
return cursor, nil, nil
}
return cursor, field, nil
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
@ -237,6 +245,7 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
keyIdx := 0
bitmap := d.keyBitmapInt16
keyBitmapLen := len(bitmap)
start := cursor
for {
c := char(b, cursor)
switch c {
@ -244,7 +253,12 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
x := uint64(curBit & -curBit)
fieldSetIndex := bitHashTable[(x*0x03F566ED27179461)>>58]
field = d.sortedFieldSets[fieldSetIndex]
keyLen := cursor - start
cursor++
if keyLen < field.keyLen {
// early match
return cursor, nil, nil
}
return cursor, field, nil
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
@ -341,10 +355,13 @@ func decodeKeyByBitmapInt8Stream(d *structDecoder, s *stream) (*structFieldSet,
x := uint64(curBit & -curBit)
fieldSetIndex := bitHashTable[(x*0x03F566ED27179461)>>58]
field = d.sortedFieldSets[fieldSetIndex]
b := s.buf[start:s.cursor]
key := *(*string)(unsafe.Pointer(&b))
keyLen := s.cursor - start
s.cursor++
return field, key, nil
if keyLen < field.keyLen {
// early match
return nil, field.key, nil
}
return field, field.key, nil
case nul:
if s.read() {
continue
@ -441,10 +458,13 @@ func decodeKeyByBitmapInt16Stream(d *structDecoder, s *stream) (*structFieldSet,
x := uint64(curBit & -curBit)
fieldSetIndex := bitHashTable[(x*0x03F566ED27179461)>>58]
field = d.sortedFieldSets[fieldSetIndex]
b := s.buf[start:s.cursor]
key := *(*string)(unsafe.Pointer(&b))
keyLen := s.cursor - start
s.cursor++
return field, key, nil
if keyLen < field.keyLen {
// early match
return nil, field.key, nil
}
return field, field.key, nil
case nul:
if s.read() {
continue