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) | ||||
| 	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 | ||||
|  | ||||
| @ -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 } | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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"}, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user