rlp: allow encoding non-empty interface values
This needs to be supported because []someInterface does occur sometimes. Funny enough, the fix involves changes to the decoder. makeDecoder cannot return an error for non-empty interfaces anymore because the type cache builds both decoder and writer. Do the check at 'runtime' instead.
This commit is contained in:
parent
29c46cdf34
commit
fc92abec2c
@ -137,7 +137,7 @@ func makeDecoder(typ reflect.Type) (dec decoder, err error) {
|
|||||||
return makeStructDecoder(typ)
|
return makeStructDecoder(typ)
|
||||||
case kind == reflect.Ptr:
|
case kind == reflect.Ptr:
|
||||||
return makePtrDecoder(typ)
|
return makePtrDecoder(typ)
|
||||||
case kind == reflect.Interface && typ.NumMethod() == 0:
|
case kind == reflect.Interface:
|
||||||
return decodeInterface, nil
|
return decodeInterface, nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ)
|
return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ)
|
||||||
@ -378,6 +378,9 @@ func makePtrDecoder(typ reflect.Type) (decoder, error) {
|
|||||||
var ifsliceType = reflect.TypeOf([]interface{}{})
|
var ifsliceType = reflect.TypeOf([]interface{}{})
|
||||||
|
|
||||||
func decodeInterface(s *Stream, val reflect.Value) error {
|
func decodeInterface(s *Stream, val reflect.Value) error {
|
||||||
|
if val.Type().NumMethod() != 0 {
|
||||||
|
return fmt.Errorf("rlp: type %v is not RLP-serializable", val.Type())
|
||||||
|
}
|
||||||
kind, _, err := s.Kind()
|
kind, _, err := s.Kind()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -325,6 +325,11 @@ var decodeTests = []decodeTest{
|
|||||||
{input: "850505050505", ptr: new(interface{}), value: []byte{5, 5, 5, 5, 5}},
|
{input: "850505050505", ptr: new(interface{}), value: []byte{5, 5, 5, 5, 5}},
|
||||||
{input: "C0", ptr: new(interface{}), value: []interface{}{}},
|
{input: "C0", ptr: new(interface{}), value: []interface{}{}},
|
||||||
{input: "C50183040404", ptr: new(interface{}), value: []interface{}{[]byte{1}, []byte{4, 4, 4}}},
|
{input: "C50183040404", ptr: new(interface{}), value: []interface{}{[]byte{1}, []byte{4, 4, 4}}},
|
||||||
|
{
|
||||||
|
input: "C3010203",
|
||||||
|
ptr: new([]io.Reader),
|
||||||
|
error: "rlp: type io.Reader is not RLP-serializable",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func uintp(i uint) *uint { return &i }
|
func uintp(i uint) *uint { return &i }
|
||||||
|
@ -280,7 +280,6 @@ func (r *encReader) next() []byte {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
encoderInterface = reflect.TypeOf(new(Encoder)).Elem()
|
encoderInterface = reflect.TypeOf(new(Encoder)).Elem()
|
||||||
emptyInterface = reflect.TypeOf(new(interface{})).Elem()
|
|
||||||
big0 = big.NewInt(0)
|
big0 = big.NewInt(0)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -292,7 +291,7 @@ func makeWriter(typ reflect.Type) (writer, error) {
|
|||||||
return writeEncoder, nil
|
return writeEncoder, nil
|
||||||
case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface):
|
case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface):
|
||||||
return writeEncoderNoPtr, nil
|
return writeEncoderNoPtr, nil
|
||||||
case typ == emptyInterface:
|
case kind == reflect.Interface:
|
||||||
return writeInterface, nil
|
return writeInterface, nil
|
||||||
case typ.AssignableTo(reflect.PtrTo(bigInt)):
|
case typ.AssignableTo(reflect.PtrTo(bigInt)):
|
||||||
return writeBigIntPtr, nil
|
return writeBigIntPtr, nil
|
||||||
|
@ -32,9 +32,19 @@ func (e byteEncoder) EncodeRLP(w io.Writer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type encodableReader struct {
|
||||||
|
A, B uint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encodableReader) Read(b []byte) (int, error) {
|
||||||
|
panic("called")
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ = Encoder(&testEncoder{})
|
_ = Encoder(&testEncoder{})
|
||||||
_ = Encoder(byteEncoder(0))
|
_ = Encoder(byteEncoder(0))
|
||||||
|
|
||||||
|
reader io.Reader = &encodableReader{1, 2}
|
||||||
)
|
)
|
||||||
|
|
||||||
type encTest struct {
|
type encTest struct {
|
||||||
@ -176,6 +186,9 @@ var encTests = []encTest{
|
|||||||
{val: (*[]struct{ uint })(nil), output: "C0"},
|
{val: (*[]struct{ uint })(nil), output: "C0"},
|
||||||
{val: (*interface{})(nil), output: "C0"},
|
{val: (*interface{})(nil), output: "C0"},
|
||||||
|
|
||||||
|
// interfaces
|
||||||
|
{val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct
|
||||||
|
|
||||||
// Encoder
|
// Encoder
|
||||||
{val: (*testEncoder)(nil), output: "00000000"},
|
{val: (*testEncoder)(nil), output: "00000000"},
|
||||||
{val: &testEncoder{}, output: "00010001000100010001"},
|
{val: &testEncoder{}, output: "00010001000100010001"},
|
||||||
|
Loading…
Reference in New Issue
Block a user