diff options
Diffstat (limited to 'rlp/typecache.go')
-rw-r--r-- | rlp/typecache.go | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/rlp/typecache.go b/rlp/typecache.go index 398f25d90..d512012e9 100644 --- a/rlp/typecache.go +++ b/rlp/typecache.go @@ -7,7 +7,7 @@ import ( var ( typeCacheMutex sync.RWMutex - typeCache = make(map[reflect.Type]*typeinfo) + typeCache = make(map[typekey]*typeinfo) ) type typeinfo struct { @@ -15,13 +15,25 @@ type typeinfo struct { writer } +// represents struct tags +type tags struct { + nilOK bool +} + +type typekey struct { + reflect.Type + // the key must include the struct tags because they + // might generate a different decoder. + tags +} + type decoder func(*Stream, reflect.Value) error type writer func(reflect.Value, *encbuf) error -func cachedTypeInfo(typ reflect.Type) (*typeinfo, error) { +func cachedTypeInfo(typ reflect.Type, tags tags) (*typeinfo, error) { typeCacheMutex.RLock() - info := typeCache[typ] + info := typeCache[typekey{typ, tags}] typeCacheMutex.RUnlock() if info != nil { return info, nil @@ -29,11 +41,12 @@ func cachedTypeInfo(typ reflect.Type) (*typeinfo, error) { // not in the cache, need to generate info for this type. typeCacheMutex.Lock() defer typeCacheMutex.Unlock() - return cachedTypeInfo1(typ) + return cachedTypeInfo1(typ, tags) } -func cachedTypeInfo1(typ reflect.Type) (*typeinfo, error) { - info := typeCache[typ] +func cachedTypeInfo1(typ reflect.Type, tags tags) (*typeinfo, error) { + key := typekey{typ, tags} + info := typeCache[key] if info != nil { // another goroutine got the write lock first return info, nil @@ -41,21 +54,27 @@ func cachedTypeInfo1(typ reflect.Type) (*typeinfo, error) { // put a dummmy value into the cache before generating. // if the generator tries to lookup itself, it will get // the dummy value and won't call itself recursively. - typeCache[typ] = new(typeinfo) - info, err := genTypeInfo(typ) + typeCache[key] = new(typeinfo) + info, err := genTypeInfo(typ, tags) if err != nil { // remove the dummy value if the generator fails - delete(typeCache, typ) + delete(typeCache, key) return nil, err } - *typeCache[typ] = *info - return typeCache[typ], err + *typeCache[key] = *info + return typeCache[key], err +} + +type field struct { + index int + info *typeinfo } func structFields(typ reflect.Type) (fields []field, err error) { for i := 0; i < typ.NumField(); i++ { if f := typ.Field(i); f.PkgPath == "" { // exported - info, err := cachedTypeInfo1(f.Type) + tags := parseStructTag(f.Tag.Get("rlp")) + info, err := cachedTypeInfo1(f.Type, tags) if err != nil { return nil, err } @@ -65,9 +84,13 @@ func structFields(typ reflect.Type) (fields []field, err error) { return fields, nil } -func genTypeInfo(typ reflect.Type) (info *typeinfo, err error) { +func parseStructTag(tag string) tags { + return tags{nilOK: tag == "nil"} +} + +func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) { info = new(typeinfo) - if info.decoder, err = makeDecoder(typ); err != nil { + if info.decoder, err = makeDecoder(typ, tags); err != nil { return nil, err } if info.writer, err = makeWriter(typ); err != nil { |