浏览代码

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.
Felix Lange 10 年之前
父节点
当前提交
fc92abec2c
共有 4 个文件被更改,包括 23 次插入3 次删除
  1. 4 1
      rlp/decode.go
  2. 5 0
      rlp/decode_test.go
  3. 1 2
      rlp/encode.go
  4. 13 0
      rlp/encode_test.go

+ 4 - 1
rlp/decode.go

@@ -137,7 +137,7 @@ func makeDecoder(typ reflect.Type) (dec decoder, err error) {
 		return makeStructDecoder(typ)
 	case kind == reflect.Ptr:
 		return makePtrDecoder(typ)
-	case kind == reflect.Interface && typ.NumMethod() == 0:
+	case kind == reflect.Interface:
 		return decodeInterface, nil
 	default:
 		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{}{})
 
 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()
 	if err != nil {
 		return err

+ 5 - 0
rlp/decode_test.go

@@ -325,6 +325,11 @@ var decodeTests = []decodeTest{
 	{input: "850505050505", ptr: new(interface{}), value: []byte{5, 5, 5, 5, 5}},
 	{input: "C0", ptr: new(interface{}), value: []interface{}{}},
 	{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 }

+ 1 - 2
rlp/encode.go

@@ -280,7 +280,6 @@ func (r *encReader) next() []byte {
 
 var (
 	encoderInterface = reflect.TypeOf(new(Encoder)).Elem()
-	emptyInterface   = reflect.TypeOf(new(interface{})).Elem()
 	big0             = big.NewInt(0)
 )
 
@@ -292,7 +291,7 @@ func makeWriter(typ reflect.Type) (writer, error) {
 		return writeEncoder, nil
 	case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface):
 		return writeEncoderNoPtr, nil
-	case typ == emptyInterface:
+	case kind == reflect.Interface:
 		return writeInterface, nil
 	case typ.AssignableTo(reflect.PtrTo(bigInt)):
 		return writeBigIntPtr, nil

+ 13 - 0
rlp/encode_test.go

@@ -32,9 +32,19 @@ func (e byteEncoder) EncodeRLP(w io.Writer) error {
 	return nil
 }
 
+type encodableReader struct {
+	A, B uint
+}
+
+func (e *encodableReader) Read(b []byte) (int, error) {
+	panic("called")
+}
+
 var (
 	_ = Encoder(&testEncoder{})
 	_ = Encoder(byteEncoder(0))
+
+	reader io.Reader = &encodableReader{1, 2}
 )
 
 type encTest struct {
@@ -176,6 +186,9 @@ var encTests = []encTest{
 	{val: (*[]struct{ uint })(nil), output: "C0"},
 	{val: (*interface{})(nil), output: "C0"},
 
+	// interfaces
+	{val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct
+
 	// Encoder
 	{val: (*testEncoder)(nil), output: "00000000"},
 	{val: &testEncoder{}, output: "00010001000100010001"},