diff options
Diffstat (limited to 'rlp/typecache.go')
-rw-r--r-- | rlp/typecache.go | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/rlp/typecache.go b/rlp/typecache.go index 0ab096695..a2f217c66 100644 --- a/rlp/typecache.go +++ b/rlp/typecache.go @@ -17,7 +17,9 @@ package rlp import ( + "fmt" "reflect" + "strings" "sync" ) @@ -33,7 +35,13 @@ type typeinfo struct { // represents struct tags type tags struct { + // rlp:"nil" controls whether empty input results in a nil pointer. nilOK bool + + // rlp:"tail" controls whether this field swallows additional list + // elements. It can only be set for the last field, which must be + // of slice type. + tail bool } type typekey struct { @@ -89,7 +97,10 @@ type field struct { func structFields(typ reflect.Type) (fields []field, err error) { for i := 0; i < typ.NumField(); i++ { if f := typ.Field(i); f.PkgPath == "" { // exported - tags := parseStructTag(f.Tag.Get("rlp")) + tags, err := parseStructTag(typ, i) + if err != nil { + return nil, err + } info, err := cachedTypeInfo1(f.Type, tags) if err != nil { return nil, err @@ -100,8 +111,27 @@ func structFields(typ reflect.Type) (fields []field, err error) { return fields, nil } -func parseStructTag(tag string) tags { - return tags{nilOK: tag == "nil"} +func parseStructTag(typ reflect.Type, fi int) (tags, error) { + f := typ.Field(fi) + var ts tags + for _, t := range strings.Split(f.Tag.Get("rlp"), ",") { + switch t = strings.TrimSpace(t); t { + case "": + case "nil": + ts.nilOK = true + case "tail": + ts.tail = true + if fi != typ.NumField()-1 { + return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (must be on last field)`, typ, f.Name) + } + if f.Type.Kind() != reflect.Slice { + return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (field type is not slice)`, typ, f.Name) + } + default: + return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name) + } + } + return ts, nil } func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) { @@ -109,7 +139,7 @@ func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) { if info.decoder, err = makeDecoder(typ, tags); err != nil { return nil, err } - if info.writer, err = makeWriter(typ); err != nil { + if info.writer, err = makeWriter(typ, tags); err != nil { return nil, err } return info, nil |