|
|
@@ -55,81 +55,23 @@ var (
|
|
|
}
|
|
|
)
|
|
|
|
|
|
-// Decoder is implemented by types that require custom RLP
|
|
|
-// decoding rules or need to decode into private fields.
|
|
|
+// Decoder is implemented by types that require custom RLP decoding rules or need to decode
|
|
|
+// into private fields.
|
|
|
//
|
|
|
-// The DecodeRLP method should read one value from the given
|
|
|
-// Stream. It is not forbidden to read less or more, but it might
|
|
|
-// be confusing.
|
|
|
+// The DecodeRLP method should read one value from the given Stream. It is not forbidden to
|
|
|
+// read less or more, but it might be confusing.
|
|
|
type Decoder interface {
|
|
|
DecodeRLP(*Stream) error
|
|
|
}
|
|
|
|
|
|
-// Decode parses RLP-encoded data from r and stores the result in the
|
|
|
-// value pointed to by val. Val must be a non-nil pointer. If r does
|
|
|
-// not implement ByteReader, Decode will do its own buffering.
|
|
|
+// Decode parses RLP-encoded data from r and stores the result in the value pointed to by
|
|
|
+// val. Please see package-level documentation for the decoding rules. Val must be a
|
|
|
+// non-nil pointer.
|
|
|
//
|
|
|
-// Decode uses the following type-dependent decoding rules:
|
|
|
+// If r does not implement ByteReader, Decode will do its own buffering.
|
|
|
//
|
|
|
-// If the type implements the Decoder interface, decode calls
|
|
|
-// DecodeRLP.
|
|
|
-//
|
|
|
-// To decode into a pointer, Decode will decode into the value pointed
|
|
|
-// to. If the pointer is nil, a new value of the pointer's element
|
|
|
-// type is allocated. If the pointer is non-nil, the existing value
|
|
|
-// will be reused.
|
|
|
-//
|
|
|
-// To decode into a struct, Decode expects the input to be an RLP
|
|
|
-// list. The decoded elements of the list are assigned to each public
|
|
|
-// field in the order given by the struct's definition. The input list
|
|
|
-// must contain an element for each decoded field. Decode returns an
|
|
|
-// error if there are too few or too many elements.
|
|
|
-//
|
|
|
-// The decoding of struct fields honours certain struct tags, "tail",
|
|
|
-// "nil" and "-".
|
|
|
-//
|
|
|
-// The "-" tag ignores fields.
|
|
|
-//
|
|
|
-// For an explanation of "tail", see the example.
|
|
|
-//
|
|
|
-// The "nil" tag applies to pointer-typed fields and changes the decoding
|
|
|
-// rules for the field such that input values of size zero decode as a nil
|
|
|
-// pointer. This tag can be useful when decoding recursive types.
|
|
|
-//
|
|
|
-// type StructWithEmptyOK struct {
|
|
|
-// Foo *[20]byte `rlp:"nil"`
|
|
|
-// }
|
|
|
-//
|
|
|
-// To decode into a slice, the input must be a list and the resulting
|
|
|
-// slice will contain the input elements in order. For byte slices,
|
|
|
-// the input must be an RLP string. Array types decode similarly, with
|
|
|
-// the additional restriction that the number of input elements (or
|
|
|
-// bytes) must match the array's length.
|
|
|
-//
|
|
|
-// To decode into a Go string, the input must be an RLP string. The
|
|
|
-// input bytes are taken as-is and will not necessarily be valid UTF-8.
|
|
|
-//
|
|
|
-// To decode into an unsigned integer type, the input must also be an RLP
|
|
|
-// string. The bytes are interpreted as a big endian representation of
|
|
|
-// the integer. If the RLP string is larger than the bit size of the
|
|
|
-// type, Decode will return an error. Decode also supports *big.Int.
|
|
|
-// There is no size limit for big integers.
|
|
|
-//
|
|
|
-// To decode into a boolean, the input must contain an unsigned integer
|
|
|
-// of value zero (false) or one (true).
|
|
|
-//
|
|
|
-// To decode into an interface value, Decode stores one of these
|
|
|
-// in the value:
|
|
|
-//
|
|
|
-// []interface{}, for RLP lists
|
|
|
-// []byte, for RLP strings
|
|
|
-//
|
|
|
-// Non-empty interface types are not supported, nor are signed integers,
|
|
|
-// floating point numbers, maps, channels and functions.
|
|
|
-//
|
|
|
-// Note that Decode does not set an input limit for all readers
|
|
|
-// and may be vulnerable to panics cause by huge value sizes. If
|
|
|
-// you need an input limit, use
|
|
|
+// Note that Decode does not set an input limit for all readers and may be vulnerable to
|
|
|
+// panics cause by huge value sizes. If you need an input limit, use
|
|
|
//
|
|
|
// NewStream(r, limit).Decode(val)
|
|
|
func Decode(r io.Reader, val interface{}) error {
|
|
|
@@ -140,9 +82,8 @@ func Decode(r io.Reader, val interface{}) error {
|
|
|
return stream.Decode(val)
|
|
|
}
|
|
|
|
|
|
-// DecodeBytes parses RLP data from b into val.
|
|
|
-// Please see the documentation of Decode for the decoding rules.
|
|
|
-// The input must contain exactly one value and no trailing data.
|
|
|
+// DecodeBytes parses RLP data from b into val. Please see package-level documentation for
|
|
|
+// the decoding rules. The input must contain exactly one value and no trailing data.
|
|
|
func DecodeBytes(b []byte, val interface{}) error {
|
|
|
r := bytes.NewReader(b)
|
|
|
|
|
|
@@ -211,14 +152,15 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
|
|
|
switch {
|
|
|
case typ == rawValueType:
|
|
|
return decodeRawValue, nil
|
|
|
- case typ.Implements(decoderInterface):
|
|
|
return decodeDecoder, nil
|
|
|
- case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(decoderInterface):
|
|
|
- return decodeDecoderNoPtr, nil
|
|
|
case typ.AssignableTo(reflect.PtrTo(bigInt)):
|
|
|
return decodeBigInt, nil
|
|
|
case typ.AssignableTo(bigInt):
|
|
|
return decodeBigIntNoPtr, nil
|
|
|
+ case kind == reflect.Ptr:
|
|
|
+ return makePtrDecoder(typ, tags)
|
|
|
+ case reflect.PtrTo(typ).Implements(decoderInterface):
|
|
|
+ return decodeDecoder, nil
|
|
|
case isUint(kind):
|
|
|
return decodeUint, nil
|
|
|
case kind == reflect.Bool:
|
|
|
@@ -229,11 +171,6 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
|
|
|
return makeListDecoder(typ, tags)
|
|
|
case kind == reflect.Struct:
|
|
|
return makeStructDecoder(typ)
|
|
|
- case kind == reflect.Ptr:
|
|
|
- if tags.nilOK {
|
|
|
- return makeOptionalPtrDecoder(typ)
|
|
|
- }
|
|
|
- return makePtrDecoder(typ)
|
|
|
case kind == reflect.Interface:
|
|
|
return decodeInterface, nil
|
|
|
default:
|
|
|
@@ -448,6 +385,11 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) {
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
+ for _, f := range fields {
|
|
|
+ if f.info.decoderErr != nil {
|
|
|
+ return nil, structFieldError{typ, f.index, f.info.decoderErr}
|
|
|
+ }
|
|
|
+ }
|
|
|
dec := func(s *Stream, val reflect.Value) (err error) {
|
|
|
if _, err := s.List(); err != nil {
|
|
|
return wrapStreamError(err, typ)
|
|
|
@@ -465,15 +407,22 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) {
|
|
|
return dec, nil
|
|
|
}
|
|
|
|
|
|
-// makePtrDecoder creates a decoder that decodes into
|
|
|
-// the pointer's element type.
|
|
|
-func makePtrDecoder(typ reflect.Type) (decoder, error) {
|
|
|
+// makePtrDecoder creates a decoder that decodes into the pointer's element type.
|
|
|
+func makePtrDecoder(typ reflect.Type, tag tags) (decoder, error) {
|
|
|
etype := typ.Elem()
|
|
|
etypeinfo := cachedTypeInfo1(etype, tags{})
|
|
|
- if etypeinfo.decoderErr != nil {
|
|
|
+ switch {
|
|
|
+ case etypeinfo.decoderErr != nil:
|
|
|
return nil, etypeinfo.decoderErr
|
|
|
+ case !tag.nilOK:
|
|
|
+ return makeSimplePtrDecoder(etype, etypeinfo), nil
|
|
|
+ default:
|
|
|
+ return makeNilPtrDecoder(etype, etypeinfo, tag.nilKind), nil
|
|
|
}
|
|
|
- dec := func(s *Stream, val reflect.Value) (err error) {
|
|
|
+}
|
|
|
+
|
|
|
+func makeSimplePtrDecoder(etype reflect.Type, etypeinfo *typeinfo) decoder {
|
|
|
+ return func(s *Stream, val reflect.Value) (err error) {
|
|
|
newval := val
|
|
|
if val.IsNil() {
|
|
|
newval = reflect.New(etype)
|
|
|
@@ -483,30 +432,35 @@ func makePtrDecoder(typ reflect.Type) (decoder, error) {
|
|
|
}
|
|
|
return err
|
|
|
}
|
|
|
- return dec, nil
|
|
|
}
|
|
|
|
|
|
-// makeOptionalPtrDecoder creates a decoder that decodes empty values
|
|
|
-// as nil. Non-empty values are decoded into a value of the element type,
|
|
|
-// just like makePtrDecoder does.
|
|
|
+// makeNilPtrDecoder creates a decoder that decodes empty values as nil. Non-empty
|
|
|
+// values are decoded into a value of the element type, just like makePtrDecoder does.
|
|
|
//
|
|
|
// This decoder is used for pointer-typed struct fields with struct tag "nil".
|
|
|
-func makeOptionalPtrDecoder(typ reflect.Type) (decoder, error) {
|
|
|
- etype := typ.Elem()
|
|
|
- etypeinfo := cachedTypeInfo1(etype, tags{})
|
|
|
- if etypeinfo.decoderErr != nil {
|
|
|
- return nil, etypeinfo.decoderErr
|
|
|
- }
|
|
|
- dec := func(s *Stream, val reflect.Value) (err error) {
|
|
|
+func makeNilPtrDecoder(etype reflect.Type, etypeinfo *typeinfo, nilKind Kind) decoder {
|
|
|
+ typ := reflect.PtrTo(etype)
|
|
|
+ nilPtr := reflect.Zero(typ)
|
|
|
+ return func(s *Stream, val reflect.Value) (err error) {
|
|
|
kind, size, err := s.Kind()
|
|
|
- if err != nil || size == 0 && kind != Byte {
|
|
|
+ if err != nil {
|
|
|
+ val.Set(nilPtr)
|
|
|
+ return wrapStreamError(err, typ)
|
|
|
+ }
|
|
|
+ // Handle empty values as a nil pointer.
|
|
|
+ if kind != Byte && size == 0 {
|
|
|
+ if kind != nilKind {
|
|
|
+ return &decodeError{
|
|
|
+ msg: fmt.Sprintf("wrong kind of empty value (got %v, want %v)", kind, nilKind),
|
|
|
+ typ: typ,
|
|
|
+ }
|
|
|
+ }
|
|
|
// rearm s.Kind. This is important because the input
|
|
|
// position must advance to the next value even though
|
|
|
// we don't read anything.
|
|
|
s.kind = -1
|
|
|
- // set the pointer to nil.
|
|
|
- val.Set(reflect.Zero(typ))
|
|
|
- return err
|
|
|
+ val.Set(nilPtr)
|
|
|
+ return nil
|
|
|
}
|
|
|
newval := val
|
|
|
if val.IsNil() {
|
|
|
@@ -517,7 +471,6 @@ func makeOptionalPtrDecoder(typ reflect.Type) (decoder, error) {
|
|
|
}
|
|
|
return err
|
|
|
}
|
|
|
- return dec, nil
|
|
|
}
|
|
|
|
|
|
var ifsliceType = reflect.TypeOf([]interface{}{})
|
|
|
@@ -546,21 +499,8 @@ func decodeInterface(s *Stream, val reflect.Value) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-// This decoder is used for non-pointer values of types
|
|
|
-// that implement the Decoder interface using a pointer receiver.
|
|
|
-func decodeDecoderNoPtr(s *Stream, val reflect.Value) error {
|
|
|
- return val.Addr().Interface().(Decoder).DecodeRLP(s)
|
|
|
-}
|
|
|
-
|
|
|
func decodeDecoder(s *Stream, val reflect.Value) error {
|
|
|
- // Decoder instances are not handled using the pointer rule if the type
|
|
|
- // implements Decoder with pointer receiver (i.e. always)
|
|
|
- // because it might handle empty values specially.
|
|
|
- // We need to allocate one here in this case, like makePtrDecoder does.
|
|
|
- if val.Kind() == reflect.Ptr && val.IsNil() {
|
|
|
- val.Set(reflect.New(val.Type().Elem()))
|
|
|
- }
|
|
|
- return val.Interface().(Decoder).DecodeRLP(s)
|
|
|
+ return val.Addr().Interface().(Decoder).DecodeRLP(s)
|
|
|
}
|
|
|
|
|
|
// Kind represents the kind of value contained in an RLP stream.
|