rlp: fixes for two corner cases and documentation (#19527)
These changes fix two corner cases related to internal handling of types in package rlp: The "tail" struct tag can only be applied to the last field. The check for this was wrong and didn't allow for private fields after the field with the tag. Unsupported types (e.g. structs containing int) which implement either the Encoder or Decoder interface but not both couldn't be encoded/decoded. Also fixes #19367
This commit is contained in:
@ -73,10 +73,12 @@ type Encoder interface {
|
||||
// An unsigned integer value is encoded as an RLP string. Zero always
|
||||
// encodes as an empty RLP string. Encode also supports *big.Int.
|
||||
//
|
||||
// Boolean values are encoded as unsigned integers zero (false) and one (true).
|
||||
//
|
||||
// An interface value encodes as the value contained in the interface.
|
||||
//
|
||||
// Boolean values are not supported, nor are signed integers, floating
|
||||
// point numbers, maps, channels and functions.
|
||||
// Signed integers are not supported, nor are floating point numbers, maps,
|
||||
// channels and functions.
|
||||
func Encode(w io.Writer, val interface{}) error {
|
||||
if outer, ok := w.(*encbuf); ok {
|
||||
// Encode was called by some type's EncodeRLP.
|
||||
@ -180,11 +182,11 @@ func (w *encbuf) Write(b []byte) (int, error) {
|
||||
|
||||
func (w *encbuf) encode(val interface{}) error {
|
||||
rval := reflect.ValueOf(val)
|
||||
ti, err := cachedTypeInfo(rval.Type(), tags{})
|
||||
writer, err := cachedWriter(rval.Type())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ti.writer(rval, w)
|
||||
return writer(rval, w)
|
||||
}
|
||||
|
||||
func (w *encbuf) encodeStringHeader(size int) {
|
||||
@ -497,17 +499,17 @@ func writeInterface(val reflect.Value, w *encbuf) error {
|
||||
return nil
|
||||
}
|
||||
eval := val.Elem()
|
||||
ti, err := cachedTypeInfo(eval.Type(), tags{})
|
||||
writer, err := cachedWriter(eval.Type())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ti.writer(eval, w)
|
||||
return writer(eval, w)
|
||||
}
|
||||
|
||||
func makeSliceWriter(typ reflect.Type, ts tags) (writer, error) {
|
||||
etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
etypeinfo := cachedTypeInfo1(typ.Elem(), tags{})
|
||||
if etypeinfo.writerErr != nil {
|
||||
return nil, etypeinfo.writerErr
|
||||
}
|
||||
writer := func(val reflect.Value, w *encbuf) error {
|
||||
if !ts.tail {
|
||||
@ -543,9 +545,9 @@ func makeStructWriter(typ reflect.Type) (writer, error) {
|
||||
}
|
||||
|
||||
func makePtrWriter(typ reflect.Type) (writer, error) {
|
||||
etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
etypeinfo := cachedTypeInfo1(typ.Elem(), tags{})
|
||||
if etypeinfo.writerErr != nil {
|
||||
return nil, etypeinfo.writerErr
|
||||
}
|
||||
|
||||
// determine nil pointer handler
|
||||
@ -577,7 +579,7 @@ func makePtrWriter(typ reflect.Type) (writer, error) {
|
||||
}
|
||||
return etypeinfo.writer(val.Elem(), w)
|
||||
}
|
||||
return writer, err
|
||||
return writer, nil
|
||||
}
|
||||
|
||||
// putint writes i to the beginning of b in big endian byte
|
||||
|
Reference in New Issue
Block a user