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