aboutsummaryrefslogtreecommitdiffstats
path: root/rlp/typecache.go
diff options
context:
space:
mode:
Diffstat (limited to 'rlp/typecache.go')
-rw-r--r--rlp/typecache.go38
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