+45
-20
@@ -13,6 +13,8 @@ import (
|
||||
type structCache struct {
|
||||
indexes []int
|
||||
names []string
|
||||
omits []bool
|
||||
noOmit bool
|
||||
common.Common
|
||||
}
|
||||
|
||||
@@ -88,34 +90,49 @@ func (e *encoder) writeStructArray(rv reflect.Value) error {
|
||||
func (e *encoder) writeStructMap(rv reflect.Value) error {
|
||||
c := e.getStructCache(rv)
|
||||
|
||||
// format size
|
||||
num := len(c.indexes)
|
||||
if num <= 0x0f {
|
||||
if err := e.setByte1Int(def.FixMap + num); err != nil {
|
||||
l := 0
|
||||
if c.noOmit {
|
||||
l = num
|
||||
} else {
|
||||
for i := 0; i < num; i++ {
|
||||
irv := rv.Field(c.indexes[i])
|
||||
if !c.omits[i] || !irv.IsZero() {
|
||||
l++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// format size
|
||||
if l <= 0x0f {
|
||||
if err := e.setByte1Int(def.FixMap + l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if num <= math.MaxUint16 {
|
||||
} else if l <= math.MaxUint16 {
|
||||
if err := e.setByte1Int(def.Map16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Int(num); err != nil {
|
||||
if err := e.setByte2Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if uint(num) <= math.MaxUint32 {
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
if err := e.setByte1Int(def.Map32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Int(num); err != nil {
|
||||
if err := e.setByte4Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
if err := e.writeString(c.names[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.create(rv.Field(c.indexes[i])); err != nil {
|
||||
return err
|
||||
irv := rv.Field(c.indexes[i])
|
||||
if !c.omits[i] || !irv.IsZero() {
|
||||
if err := e.writeString(c.names[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.create(irv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -128,16 +145,24 @@ func (e *encoder) getStructCache(rv reflect.Value) *structCache {
|
||||
return cache.(*structCache)
|
||||
}
|
||||
|
||||
var c *structCache
|
||||
if !find {
|
||||
c = &structCache{}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if ok, name := e.CheckField(rv.Type().Field(i)); ok {
|
||||
c.indexes = append(c.indexes, i)
|
||||
c.names = append(c.names, name)
|
||||
num := rv.NumField()
|
||||
c := &structCache{
|
||||
indexes: make([]int, 0, num),
|
||||
names: make([]string, 0, num),
|
||||
omits: make([]bool, 0, num),
|
||||
}
|
||||
omitCount := 0
|
||||
for i := 0; i < num; i++ {
|
||||
if ok, omit, name := e.CheckField(rv.Type().Field(i)); ok {
|
||||
c.indexes = append(c.indexes, i)
|
||||
c.names = append(c.names, name)
|
||||
c.omits = append(c.omits, omit)
|
||||
if omit {
|
||||
omitCount++
|
||||
}
|
||||
}
|
||||
cachemap.Store(t, c)
|
||||
}
|
||||
c.noOmit = omitCount == 0
|
||||
cachemap.Store(t, c)
|
||||
return c
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user