Merge branch 'poc8' into develop
This commit is contained in:
		
						commit
						9ff7be68fb
					
				
							
								
								
									
										169
									
								
								rlp/decode.go
									
									
									
									
									
								
							
							
						
						
									
										169
									
								
								rlp/decode.go
									
									
									
									
									
								
							| @ -54,7 +54,7 @@ type Decoder interface { | ||||
| // To decode into a Go string, the input must be an RLP string. The
 | ||||
| // bytes are taken as-is and will not necessarily be valid UTF-8.
 | ||||
| //
 | ||||
| // To decode into an integer type, the input must also be an RLP
 | ||||
| // 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.
 | ||||
| @ -66,8 +66,9 @@ type Decoder interface { | ||||
| //	[]interface{}, for RLP lists
 | ||||
| //	[]byte, for RLP strings
 | ||||
| //
 | ||||
| // Non-empty interface types are not supported, nor are bool, float32,
 | ||||
| // float64, maps, channel types and functions.
 | ||||
| // Non-empty interface types are not supported, nor are booleans,
 | ||||
| // signed integers, floating point numbers, maps, channels and
 | ||||
| // functions.
 | ||||
| func Decode(r io.Reader, val interface{}) error { | ||||
| 	return NewStream(r).Decode(val) | ||||
| } | ||||
| @ -81,37 +82,58 @@ func (err decodeError) Error() string { | ||||
| 	return fmt.Sprintf("rlp: %s for %v", err.msg, err.typ) | ||||
| } | ||||
| 
 | ||||
| func makeNumDecoder(typ reflect.Type) decoder { | ||||
| 	kind := typ.Kind() | ||||
| 	switch { | ||||
| 	case kind <= reflect.Int64: | ||||
| 		return decodeInt | ||||
| 	case kind <= reflect.Uint64: | ||||
| 		return decodeUint | ||||
| 	default: | ||||
| 		panic("fallthrough") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func decodeInt(s *Stream, val reflect.Value) error { | ||||
| 	typ := val.Type() | ||||
| 	num, err := s.uint(typ.Bits()) | ||||
| 	if err == errUintOverflow { | ||||
| func wrapStreamError(err error, typ reflect.Type) error { | ||||
| 	switch err { | ||||
| 	case ErrExpectedList: | ||||
| 		return decodeError{"expected input list", typ} | ||||
| 	case ErrExpectedString: | ||||
| 		return decodeError{"expected input string or byte", typ} | ||||
| 	case errUintOverflow: | ||||
| 		return decodeError{"input string too long", typ} | ||||
| 	} else if err != nil { | ||||
| 	case errNotAtEOL: | ||||
| 		return decodeError{"input list has too many elements", typ} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 	val.SetInt(int64(num)) | ||||
| 	return nil | ||||
| 
 | ||||
| var ( | ||||
| 	decoderInterface = reflect.TypeOf(new(Decoder)).Elem() | ||||
| 	bigInt           = reflect.TypeOf(big.Int{}) | ||||
| ) | ||||
| 
 | ||||
| func makeDecoder(typ reflect.Type) (dec decoder, err error) { | ||||
| 	kind := typ.Kind() | ||||
| 	switch { | ||||
| 	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 isUint(kind): | ||||
| 		return decodeUint, nil | ||||
| 	case kind == reflect.String: | ||||
| 		return decodeString, nil | ||||
| 	case kind == reflect.Slice || kind == reflect.Array: | ||||
| 		return makeListDecoder(typ) | ||||
| 	case kind == reflect.Struct: | ||||
| 		return makeStructDecoder(typ) | ||||
| 	case kind == reflect.Ptr: | ||||
| 		return makePtrDecoder(typ) | ||||
| 	case kind == reflect.Interface && typ.NumMethod() == 0: | ||||
| 		return decodeInterface, nil | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func decodeUint(s *Stream, val reflect.Value) error { | ||||
| 	typ := val.Type() | ||||
| 	num, err := s.uint(typ.Bits()) | ||||
| 	if err == errUintOverflow { | ||||
| 		return decodeError{"input string too big", typ} | ||||
| 	} else if err != nil { | ||||
| 		return err | ||||
| 	if err != nil { | ||||
| 		return wrapStreamError(err, val.Type()) | ||||
| 	} | ||||
| 	val.SetUint(num) | ||||
| 	return nil | ||||
| @ -120,7 +142,7 @@ func decodeUint(s *Stream, val reflect.Value) error { | ||||
| func decodeString(s *Stream, val reflect.Value) error { | ||||
| 	b, err := s.Bytes() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return wrapStreamError(err, val.Type()) | ||||
| 	} | ||||
| 	val.SetString(string(b)) | ||||
| 	return nil | ||||
| @ -133,7 +155,7 @@ func decodeBigIntNoPtr(s *Stream, val reflect.Value) error { | ||||
| func decodeBigInt(s *Stream, val reflect.Value) error { | ||||
| 	b, err := s.Bytes() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return wrapStreamError(err, val.Type()) | ||||
| 	} | ||||
| 	i := val.Interface().(*big.Int) | ||||
| 	if i == nil { | ||||
| @ -144,8 +166,6 @@ func decodeBigInt(s *Stream, val reflect.Value) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| const maxInt = int(^uint(0) >> 1) | ||||
| 
 | ||||
| func makeListDecoder(typ reflect.Type) (decoder, error) { | ||||
| 	etype := typ.Elem() | ||||
| 	if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) { | ||||
| @ -159,42 +179,29 @@ func makeListDecoder(typ reflect.Type) (decoder, error) { | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var maxLen = maxInt | ||||
| 
 | ||||
| 	if typ.Kind() == reflect.Array { | ||||
| 		maxLen = typ.Len() | ||||
| 		return func(s *Stream, val reflect.Value) error { | ||||
| 			return decodeListArray(s, val, etypeinfo.decoder) | ||||
| 		}, nil | ||||
| 	} | ||||
| 	dec := func(s *Stream, val reflect.Value) error { | ||||
| 		return decodeList(s, val, etypeinfo.decoder, maxLen) | ||||
| 	} | ||||
| 	return dec, nil | ||||
| 	return func(s *Stream, val reflect.Value) error { | ||||
| 		return decodeListSlice(s, val, etypeinfo.decoder) | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // decodeList decodes RLP list elements into slices and arrays.
 | ||||
| //
 | ||||
| // The approach here is stolen from package json, although we differ
 | ||||
| // in the semantics for arrays. package json discards remaining
 | ||||
| // elements that would not fit into the array. We generate an error in
 | ||||
| // this case because we'd be losing information.
 | ||||
| func decodeList(s *Stream, val reflect.Value, elemdec decoder, maxelem int) error { | ||||
| func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error { | ||||
| 	size, err := s.List() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return wrapStreamError(err, val.Type()) | ||||
| 	} | ||||
| 	if size == 0 { | ||||
| 		if val.Kind() == reflect.Slice { | ||||
| 		val.Set(reflect.MakeSlice(val.Type(), 0, 0)) | ||||
| 		} else { | ||||
| 			zero(val, 0) | ||||
| 		} | ||||
| 		return s.ListEnd() | ||||
| 	} | ||||
| 
 | ||||
| 	i := 0 | ||||
| 	for { | ||||
| 		if i > maxelem { | ||||
| 			return decodeError{"input list has too many elements", val.Type()} | ||||
| 		} | ||||
| 		if val.Kind() == reflect.Slice { | ||||
| 	for ; ; i++ { | ||||
| 		// grow slice if necessary
 | ||||
| 		if i >= val.Cap() { | ||||
| 			newcap := val.Cap() + val.Cap()/2 | ||||
| @ -208,33 +215,55 @@ func decodeList(s *Stream, val reflect.Value, elemdec decoder, maxelem int) erro | ||||
| 		if i >= val.Len() { | ||||
| 			val.SetLen(i + 1) | ||||
| 		} | ||||
| 		} | ||||
| 		// decode into element
 | ||||
| 		if err := elemdec(s, val.Index(i)); err == EOL { | ||||
| 			break | ||||
| 		} else if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		i++ | ||||
| 	} | ||||
| 	if i < val.Len() { | ||||
| 		if val.Kind() == reflect.Array { | ||||
| 			// zero the rest of the array.
 | ||||
| 			zero(val, i) | ||||
| 		} else { | ||||
| 		val.SetLen(i) | ||||
| 	} | ||||
| 	} | ||||
| 	return s.ListEnd() | ||||
| } | ||||
| 
 | ||||
| func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error { | ||||
| 	size, err := s.List() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if size == 0 { | ||||
| 		zero(val, 0) | ||||
| 		return s.ListEnd() | ||||
| 	} | ||||
| 
 | ||||
| 	// The approach here is stolen from package json, although we differ
 | ||||
| 	// in the semantics for arrays. package json discards remaining
 | ||||
| 	// elements that would not fit into the array. We generate an error in
 | ||||
| 	// this case because we'd be losing information.
 | ||||
| 	vlen := val.Len() | ||||
| 	i := 0 | ||||
| 	for ; i < vlen; i++ { | ||||
| 		if err := elemdec(s, val.Index(i)); err == EOL { | ||||
| 			break | ||||
| 		} else if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if i < vlen { | ||||
| 		zero(val, i) | ||||
| 	} | ||||
| 	return wrapStreamError(s.ListEnd(), val.Type()) | ||||
| } | ||||
| 
 | ||||
| func decodeByteSlice(s *Stream, val reflect.Value) error { | ||||
| 	kind, _, err := s.Kind() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if kind == List { | ||||
| 		return decodeList(s, val, decodeUint, maxInt) | ||||
| 		return decodeListSlice(s, val, decodeUint) | ||||
| 	} | ||||
| 	b, err := s.Bytes() | ||||
| 	if err == nil { | ||||
| @ -251,14 +280,14 @@ func decodeByteArray(s *Stream, val reflect.Value) error { | ||||
| 	switch kind { | ||||
| 	case Byte: | ||||
| 		if val.Len() == 0 { | ||||
| 			return decodeError{"input string too big", val.Type()} | ||||
| 			return decodeError{"input string too long", val.Type()} | ||||
| 		} | ||||
| 		bv, _ := s.Uint() | ||||
| 		val.Index(0).SetUint(bv) | ||||
| 		zero(val, 1) | ||||
| 	case String: | ||||
| 		if uint64(val.Len()) < size { | ||||
| 			return decodeError{"input string too big", val.Type()} | ||||
| 			return decodeError{"input string too long", val.Type()} | ||||
| 		} | ||||
| 		slice := val.Slice(0, int(size)).Interface().([]byte) | ||||
| 		if err := s.readFull(slice); err != nil { | ||||
| @ -266,14 +295,15 @@ func decodeByteArray(s *Stream, val reflect.Value) error { | ||||
| 		} | ||||
| 		zero(val, int(size)) | ||||
| 	case List: | ||||
| 		return decodeList(s, val, decodeUint, val.Len()) | ||||
| 		return decodeListArray(s, val, decodeUint) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func zero(val reflect.Value, start int) { | ||||
| 	z := reflect.Zero(val.Type().Elem()) | ||||
| 	for i := start; i < val.Len(); i++ { | ||||
| 	end := val.Len() | ||||
| 	for i := start; i < end; i++ { | ||||
| 		val.Index(i).Set(z) | ||||
| 	} | ||||
| } | ||||
| @ -296,7 +326,7 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) { | ||||
| 	} | ||||
| 	dec := func(s *Stream, val reflect.Value) (err error) { | ||||
| 		if _, err = s.List(); err != nil { | ||||
| 			return err | ||||
| 			return wrapStreamError(err, typ) | ||||
| 		} | ||||
| 		for _, f := range fields { | ||||
| 			err = f.info.decoder(s, val.Field(f.index)) | ||||
| @ -307,10 +337,7 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		if err = s.ListEnd(); err == errNotAtEOL { | ||||
| 			err = decodeError{"input list has too many elements", typ} | ||||
| 		} | ||||
| 		return err | ||||
| 		return wrapStreamError(s.ListEnd(), typ) | ||||
| 	} | ||||
| 	return dec, nil | ||||
| } | ||||
| @ -348,7 +375,7 @@ func decodeInterface(s *Stream, val reflect.Value) error { | ||||
| 	} | ||||
| 	if kind == List { | ||||
| 		slice := reflect.New(ifsliceType).Elem() | ||||
| 		if err := decodeList(s, slice, decodeInterface, maxInt); err != nil { | ||||
| 		if err := decodeListSlice(s, slice, decodeInterface); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		val.Set(slice) | ||||
|  | ||||
| @ -171,7 +171,7 @@ func TestDecodeErrors(t *testing.T) { | ||||
| 		t.Errorf("Decode(r, new(chan bool)) error mismatch, got %q, want %q", err, expectErr) | ||||
| 	} | ||||
| 
 | ||||
| 	if err := Decode(r, new(int)); err != io.EOF { | ||||
| 	if err := Decode(r, new(uint)); err != io.EOF { | ||||
| 		t.Errorf("Decode(r, new(int)) error mismatch, got %q, want %q", err, io.EOF) | ||||
| 	} | ||||
| } | ||||
| @ -184,12 +184,12 @@ type decodeTest struct { | ||||
| } | ||||
| 
 | ||||
| type simplestruct struct { | ||||
| 	A int | ||||
| 	A uint | ||||
| 	B string | ||||
| } | ||||
| 
 | ||||
| type recstruct struct { | ||||
| 	I     int | ||||
| 	I     uint | ||||
| 	Child *recstruct | ||||
| } | ||||
| 
 | ||||
| @ -202,7 +202,7 @@ var ( | ||||
| 
 | ||||
| var ( | ||||
| 	sharedByteArray [5]byte | ||||
| 	sharedPtr       = new(*int) | ||||
| 	sharedPtr       = new(*uint) | ||||
| ) | ||||
| 
 | ||||
| var decodeTests = []decodeTest{ | ||||
| @ -213,17 +213,17 @@ var decodeTests = []decodeTest{ | ||||
| 	{input: "820505", ptr: new(uint32), value: uint32(0x0505)}, | ||||
| 	{input: "83050505", ptr: new(uint32), value: uint32(0x050505)}, | ||||
| 	{input: "8405050505", ptr: new(uint32), value: uint32(0x05050505)}, | ||||
| 	{input: "850505050505", ptr: new(uint32), error: "rlp: input string too big for uint32"}, | ||||
| 	{input: "C0", ptr: new(uint32), error: ErrExpectedString.Error()}, | ||||
| 	{input: "850505050505", ptr: new(uint32), error: "rlp: input string too long for uint32"}, | ||||
| 	{input: "C0", ptr: new(uint32), error: "rlp: expected input string or byte for uint32"}, | ||||
| 
 | ||||
| 	// slices
 | ||||
| 	{input: "C0", ptr: new([]int), value: []int{}}, | ||||
| 	{input: "C80102030405060708", ptr: new([]int), value: []int{1, 2, 3, 4, 5, 6, 7, 8}}, | ||||
| 	{input: "C0", ptr: new([]uint), value: []uint{}}, | ||||
| 	{input: "C80102030405060708", ptr: new([]uint), value: []uint{1, 2, 3, 4, 5, 6, 7, 8}}, | ||||
| 
 | ||||
| 	// arrays
 | ||||
| 	{input: "C0", ptr: new([5]int), value: [5]int{}}, | ||||
| 	{input: "C50102030405", ptr: new([5]int), value: [5]int{1, 2, 3, 4, 5}}, | ||||
| 	{input: "C6010203040506", ptr: new([5]int), error: "rlp: input list has too many elements for [5]int"}, | ||||
| 	{input: "C0", ptr: new([5]uint), value: [5]uint{}}, | ||||
| 	{input: "C50102030405", ptr: new([5]uint), value: [5]uint{1, 2, 3, 4, 5}}, | ||||
| 	{input: "C6010203040506", ptr: new([5]uint), error: "rlp: input list has too many elements for [5]uint"}, | ||||
| 
 | ||||
| 	// byte slices
 | ||||
| 	{input: "01", ptr: new([]byte), value: []byte{1}}, | ||||
| @ -231,7 +231,7 @@ var decodeTests = []decodeTest{ | ||||
| 	{input: "8D6162636465666768696A6B6C6D", ptr: new([]byte), value: []byte("abcdefghijklm")}, | ||||
| 	{input: "C0", ptr: new([]byte), value: []byte{}}, | ||||
| 	{input: "C3010203", ptr: new([]byte), value: []byte{1, 2, 3}}, | ||||
| 	{input: "C3820102", ptr: new([]byte), error: "rlp: input string too big for uint8"}, | ||||
| 	{input: "C3820102", ptr: new([]byte), error: "rlp: input string too long for uint8"}, | ||||
| 
 | ||||
| 	// byte arrays
 | ||||
| 	{input: "01", ptr: new([5]byte), value: [5]byte{1}}, | ||||
| @ -239,8 +239,8 @@ var decodeTests = []decodeTest{ | ||||
| 	{input: "850102030405", ptr: new([5]byte), value: [5]byte{1, 2, 3, 4, 5}}, | ||||
| 	{input: "C0", ptr: new([5]byte), value: [5]byte{}}, | ||||
| 	{input: "C3010203", ptr: new([5]byte), value: [5]byte{1, 2, 3, 0, 0}}, | ||||
| 	{input: "C3820102", ptr: new([5]byte), error: "rlp: input string too big for uint8"}, | ||||
| 	{input: "86010203040506", ptr: new([5]byte), error: "rlp: input string too big for [5]uint8"}, | ||||
| 	{input: "C3820102", ptr: new([5]byte), error: "rlp: input string too long for uint8"}, | ||||
| 	{input: "86010203040506", ptr: new([5]byte), error: "rlp: input string too long for [5]uint8"}, | ||||
| 	{input: "850101", ptr: new([5]byte), error: io.ErrUnexpectedEOF.Error()}, | ||||
| 
 | ||||
| 	// byte array reuse (should be zeroed)
 | ||||
| @ -254,19 +254,19 @@ var decodeTests = []decodeTest{ | ||||
| 	// zero sized byte arrays
 | ||||
| 	{input: "80", ptr: new([0]byte), value: [0]byte{}}, | ||||
| 	{input: "C0", ptr: new([0]byte), value: [0]byte{}}, | ||||
| 	{input: "01", ptr: new([0]byte), error: "rlp: input string too big for [0]uint8"}, | ||||
| 	{input: "8101", ptr: new([0]byte), error: "rlp: input string too big for [0]uint8"}, | ||||
| 	{input: "01", ptr: new([0]byte), error: "rlp: input string too long for [0]uint8"}, | ||||
| 	{input: "8101", ptr: new([0]byte), error: "rlp: input string too long for [0]uint8"}, | ||||
| 
 | ||||
| 	// strings
 | ||||
| 	{input: "00", ptr: new(string), value: "\000"}, | ||||
| 	{input: "8D6162636465666768696A6B6C6D", ptr: new(string), value: "abcdefghijklm"}, | ||||
| 	{input: "C0", ptr: new(string), error: ErrExpectedString.Error()}, | ||||
| 	{input: "C0", ptr: new(string), error: "rlp: expected input string or byte for string"}, | ||||
| 
 | ||||
| 	// big ints
 | ||||
| 	{input: "01", ptr: new(*big.Int), value: big.NewInt(1)}, | ||||
| 	{input: "89FFFFFFFFFFFFFFFFFF", ptr: new(*big.Int), value: veryBigInt}, | ||||
| 	{input: "10", ptr: new(big.Int), value: *big.NewInt(16)}, // non-pointer also works
 | ||||
| 	{input: "C0", ptr: new(*big.Int), error: ErrExpectedString.Error()}, | ||||
| 	{input: "C0", ptr: new(*big.Int), error: "rlp: expected input string or byte for *big.Int"}, | ||||
| 
 | ||||
| 	// structs
 | ||||
| 	{input: "C0", ptr: new(simplestruct), value: simplestruct{0, ""}}, | ||||
| @ -280,17 +280,17 @@ var decodeTests = []decodeTest{ | ||||
| 	}, | ||||
| 
 | ||||
| 	// pointers
 | ||||
| 	{input: "00", ptr: new(*int), value: (*int)(nil)}, | ||||
| 	{input: "80", ptr: new(*int), value: (*int)(nil)}, | ||||
| 	{input: "C0", ptr: new(*int), value: (*int)(nil)}, | ||||
| 	{input: "07", ptr: new(*int), value: intp(7)}, | ||||
| 	{input: "8108", ptr: new(*int), value: intp(8)}, | ||||
| 	{input: "C109", ptr: new(*[]int), value: &[]int{9}}, | ||||
| 	{input: "00", ptr: new(*uint), value: (*uint)(nil)}, | ||||
| 	{input: "80", ptr: new(*uint), value: (*uint)(nil)}, | ||||
| 	{input: "C0", ptr: new(*uint), value: (*uint)(nil)}, | ||||
| 	{input: "07", ptr: new(*uint), value: uintp(7)}, | ||||
| 	{input: "8108", ptr: new(*uint), value: uintp(8)}, | ||||
| 	{input: "C109", ptr: new(*[]uint), value: &[]uint{9}}, | ||||
| 	{input: "C58403030303", ptr: new(*[][]byte), value: &[][]byte{{3, 3, 3, 3}}}, | ||||
| 
 | ||||
| 	// pointer should be reset to nil
 | ||||
| 	{input: "05", ptr: sharedPtr, value: intp(5)}, | ||||
| 	{input: "80", ptr: sharedPtr, value: (*int)(nil)}, | ||||
| 	{input: "05", ptr: sharedPtr, value: uintp(5)}, | ||||
| 	{input: "80", ptr: sharedPtr, value: (*uint)(nil)}, | ||||
| 
 | ||||
| 	// interface{}
 | ||||
| 	{input: "00", ptr: new(interface{}), value: []byte{0}}, | ||||
| @ -301,7 +301,7 @@ var decodeTests = []decodeTest{ | ||||
| 	{input: "C50183040404", ptr: new(interface{}), value: []interface{}{[]byte{1}, []byte{4, 4, 4}}}, | ||||
| } | ||||
| 
 | ||||
| func intp(i int) *int { return &i } | ||||
| func uintp(i uint) *uint { return &i } | ||||
| 
 | ||||
| func runTests(t *testing.T, decode func([]byte, interface{}) error) { | ||||
| 	for i, test := range decodeTests { | ||||
| @ -434,8 +434,8 @@ func ExampleDecode() { | ||||
| 	input, _ := hex.DecodeString("C90A1486666F6F626172") | ||||
| 
 | ||||
| 	type example struct { | ||||
| 		A, B    int | ||||
| 		private int // private fields are ignored
 | ||||
| 		A, B    uint | ||||
| 		private uint // private fields are ignored
 | ||||
| 		String  string | ||||
| 	} | ||||
| 
 | ||||
| @ -447,7 +447,7 @@ func ExampleDecode() { | ||||
| 		fmt.Printf("Decoded value: %#v\n", s) | ||||
| 	} | ||||
| 	// Output:
 | ||||
| 	// Decoded value: rlp.example{A:10, B:20, private:0, String:"foobar"}
 | ||||
| 	// Decoded value: rlp.example{A:0xa, B:0x14, private:0x0, String:"foobar"}
 | ||||
| } | ||||
| 
 | ||||
| func ExampleStream() { | ||||
|  | ||||
| @ -1,8 +1,6 @@ | ||||
| package rlp | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"reflect" | ||||
| 	"sync" | ||||
| ) | ||||
| @ -51,41 +49,14 @@ func cachedTypeInfo1(typ reflect.Type) (*typeinfo, error) { | ||||
| 	return typeCache[typ], err | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	decoderInterface = reflect.TypeOf(new(Decoder)).Elem() | ||||
| 	bigInt           = reflect.TypeOf(big.Int{}) | ||||
| ) | ||||
| 
 | ||||
| func genTypeInfo(typ reflect.Type) (info *typeinfo, err error) { | ||||
| 	info = new(typeinfo) | ||||
| 	kind := typ.Kind() | ||||
| 	switch { | ||||
| 	case typ.Implements(decoderInterface): | ||||
| 		info.decoder = decodeDecoder | ||||
| 	case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(decoderInterface): | ||||
| 		info.decoder = decodeDecoderNoPtr | ||||
| 	case typ.AssignableTo(reflect.PtrTo(bigInt)): | ||||
| 		info.decoder = decodeBigInt | ||||
| 	case typ.AssignableTo(bigInt): | ||||
| 		info.decoder = decodeBigIntNoPtr | ||||
| 	case isInteger(kind): | ||||
| 		info.decoder = makeNumDecoder(typ) | ||||
| 	case kind == reflect.String: | ||||
| 		info.decoder = decodeString | ||||
| 	case kind == reflect.Slice || kind == reflect.Array: | ||||
| 		info.decoder, err = makeListDecoder(typ) | ||||
| 	case kind == reflect.Struct: | ||||
| 		info.decoder, err = makeStructDecoder(typ) | ||||
| 	case kind == reflect.Ptr: | ||||
| 		info.decoder, err = makePtrDecoder(typ) | ||||
| 	case kind == reflect.Interface && typ.NumMethod() == 0: | ||||
| 		info.decoder = decodeInterface | ||||
| 	default: | ||||
| 		err = fmt.Errorf("rlp: type %v is not RLP-serializable", typ) | ||||
| 	if info.decoder, err = makeDecoder(typ); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return info, err | ||||
| 	return info, nil | ||||
| } | ||||
| 
 | ||||
| func isInteger(k reflect.Kind) bool { | ||||
| 	return k >= reflect.Int && k <= reflect.Uintptr | ||||
| func isUint(k reflect.Kind) bool { | ||||
| 	return k >= reflect.Uint && k <= reflect.Uintptr | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user