Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
ce0c4e5d
Commit
ce0c4e5d
authored
Dec 09, 2014
by
Jeffrey Wilcke
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #203 from fjl/rlp-fixes
RLP: remove signed integer support and other fixes
parents
195b2d2e
6cf4e032
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
145 additions
and
147 deletions
+145
-147
decode.go
rlp/decode.go
+110
-83
decode_test.go
rlp/decode_test.go
+30
-30
typecache.go
rlp/typecache.go
+5
-34
No files found.
rlp/decode.go
View file @
ce0c4e5d
...
...
@@ -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
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
}
case
errNotAtEOL
:
return
decodeError
{
"input list has too many elements"
,
typ
}
}
return
err
}
func
decodeInt
(
s
*
Stream
,
val
reflect
.
Value
)
error
{
typ
:=
val
.
Type
()
num
,
err
:=
s
.
uint
(
typ
.
Bits
())
if
err
==
errUintOverflow
{
return
decodeError
{
"input string too long"
,
typ
}
}
else
if
err
!=
nil
{
return
err
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
)
}
val
.
SetInt
(
int64
(
num
))
return
nil
}
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,55 +179,41 @@ func makeListDecoder(typ reflect.Type) (decoder, error) {
if
err
!=
nil
{
return
nil
,
err
}
var
maxLen
=
maxInt
if
typ
.
Kind
()
==
reflect
.
Array
{
maxLen
=
typ
.
Len
()
}
dec
:=
func
(
s
*
Stream
,
val
reflect
.
Value
)
error
{
return
decodeList
(
s
,
val
,
etypeinfo
.
decoder
,
maxLen
)
return
func
(
s
*
Stream
,
val
reflect
.
Value
)
error
{
return
decodeListArray
(
s
,
val
,
etypeinfo
.
decoder
)
},
nil
}
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
)
}
val
.
Set
(
reflect
.
MakeSlice
(
val
.
Type
(),
0
,
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
{
// grow slice if necessary
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
)
for
;
;
i
++
{
// grow slice if necessary
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
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
{
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
)
}
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
,
maxI
nt
)
return
decodeList
Slice
(
s
,
val
,
decodeUi
nt
)
}
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
bi
g"
,
val
.
Type
()}
return
decodeError
{
"input string too
lon
g"
,
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
bi
g"
,
val
.
Type
()}
return
decodeError
{
"input string too
lon
g"
,
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
decodeList
Array
(
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
:=
decodeList
Slice
(
s
,
slice
,
decodeInterface
);
err
!=
nil
{
return
err
}
val
.
Set
(
slice
)
...
...
rlp/decode_test.go
View file @
ce0c4e5d
...
...
@@ -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
(
u
int
));
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
u
int
B
string
}
type
recstruct
struct
{
I
int
I
u
int
Child
*
recstruct
}
...
...
@@ -202,7 +202,7 @@ var (
var
(
sharedByteArray
[
5
]
byte
sharedPtr
=
new
(
*
int
)
sharedPtr
=
new
(
*
u
int
)
)
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
bi
g for uint32"
},
{
input
:
"C0"
,
ptr
:
new
(
uint32
),
error
:
ErrExpectedString
.
Error
()
},
{
input
:
"850505050505"
,
ptr
:
new
(
uint32
),
error
:
"rlp: input string too
lon
g 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
:
[]
u
int
{}},
{
input
:
"C80102030405060708"
,
ptr
:
new
([]
uint
),
value
:
[]
u
int
{
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
]
u
int
{}},
{
input
:
"C50102030405"
,
ptr
:
new
([
5
]
uint
),
value
:
[
5
]
u
int
{
1
,
2
,
3
,
4
,
5
}},
{
input
:
"C6010203040506"
,
ptr
:
new
([
5
]
uint
),
error
:
"rlp: input list has too many elements for [5]u
int"
},
// 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
bi
g for uint8"
},
{
input
:
"C3820102"
,
ptr
:
new
([]
byte
),
error
:
"rlp: input string too
lon
g 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
bi
g for uint8"
},
{
input
:
"86010203040506"
,
ptr
:
new
([
5
]
byte
),
error
:
"rlp: input string too
bi
g for [5]uint8"
},
{
input
:
"C3820102"
,
ptr
:
new
([
5
]
byte
),
error
:
"rlp: input string too
lon
g for uint8"
},
{
input
:
"86010203040506"
,
ptr
:
new
([
5
]
byte
),
error
:
"rlp: input string too
lon
g 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
bi
g for [0]uint8"
},
{
input
:
"8101"
,
ptr
:
new
([
0
]
byte
),
error
:
"rlp: input string too
bi
g for [0]uint8"
},
{
input
:
"01"
,
ptr
:
new
([
0
]
byte
),
error
:
"rlp: input string too
lon
g for [0]uint8"
},
{
input
:
"8101"
,
ptr
:
new
([
0
]
byte
),
error
:
"rlp: input string too
lon
g for [0]uint8"
},
// strings
{
input
:
"00"
,
ptr
:
new
(
string
),
value
:
"
\0
00"
},
{
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
:
(
*
u
int
)(
nil
)},
{
input
:
"80"
,
ptr
:
new
(
*
uint
),
value
:
(
*
u
int
)(
nil
)},
{
input
:
"C0"
,
ptr
:
new
(
*
uint
),
value
:
(
*
u
int
)(
nil
)},
{
input
:
"07"
,
ptr
:
new
(
*
uint
),
value
:
u
intp
(
7
)},
{
input
:
"8108"
,
ptr
:
new
(
*
uint
),
value
:
u
intp
(
8
)},
{
input
:
"C109"
,
ptr
:
new
(
*
[]
uint
),
value
:
&
[]
u
int
{
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
:
u
intp
(
5
)},
{
input
:
"80"
,
ptr
:
sharedPtr
,
value
:
(
*
u
int
)(
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
)
*
u
int
{
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
u
int
private
u
int
// 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:0x
0, String:"foobar"}
}
func
ExampleStream
()
{
...
...
rlp/typecache.go
View file @
ce0c4e5d
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
is
Integer
(
k
reflect
.
Kind
)
bool
{
return
k
>=
reflect
.
I
nt
&&
k
<=
reflect
.
Uintptr
func
is
Uint
(
k
reflect
.
Kind
)
bool
{
return
k
>=
reflect
.
Ui
nt
&&
k
<=
reflect
.
Uintptr
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment