decode.gno
2.34 Kb · 127 lines
1package rlp
2
3// DecodeValue decodes exactly one RLP item.
4func DecodeValue(b []byte) (Value, error) {
5 v, rest, err := decodeValue(b, 0)
6 if err != nil {
7 return Value{}, err
8 }
9
10 if len(rest) != 0 {
11 return Value{}, ErrTrailingBytes
12 }
13
14 return v, nil
15}
16
17func split(b []byte) (Kind, []byte, []byte, error) {
18 k, tagSize, contentSize, err := readKind(b)
19 if err != nil {
20 return 0, nil, b, err
21 }
22
23 end := tagSize + contentSize
24
25 return k, b[tagSize:end], b[end:], nil
26}
27
28func decodeValue(b []byte, depth int) (Value, []byte, error) {
29 if depth > maxDecodeDepth {
30 return Value{}, b, ErrDepthLimit
31 }
32
33 k, content, rest, err := split(b)
34 if err != nil {
35 return Value{}, b, err
36 }
37
38 if k != KindList {
39 return Value{Kind: k, Bytes: content}, rest, nil
40 }
41
42 var items []Value
43 for len(content) > 0 {
44 var item Value
45
46 item, content, err = decodeValue(content, depth+1)
47 if err != nil {
48 return Value{}, b, err
49 }
50
51 items = append(items, item)
52 }
53
54 return Value{Kind: KindList, List: items}, rest, nil
55}
56
57func readKind(b []byte) (Kind, int, int, error) {
58 if len(b) == 0 {
59 return 0, 0, 0, ErrUnexpectedEOF
60 }
61
62 prefix := b[0]
63 switch {
64 case prefix < 0x80:
65 return KindByte, 0, 1, nil
66 case prefix < 0xB8:
67 size := int(prefix - 0x80)
68 if size == 1 && len(b) > 1 && b[1] < 0x80 {
69 return 0, 0, 0, ErrCanonSize
70 }
71
72 if len(b) < 1+size {
73 return 0, 0, 0, ErrValueTooLarge
74 }
75
76 return KindString, 1, size, nil
77 case prefix < 0xC0:
78 return readLongItem(b, int(prefix-0xB7), KindString)
79 case prefix < 0xF8:
80 size := int(prefix - 0xC0)
81 if len(b) < 1+size {
82 return 0, 0, 0, ErrValueTooLarge
83 }
84
85 return KindList, 1, size, nil
86 default:
87 return readLongItem(b, int(prefix-0xF7), KindList)
88 }
89}
90
91func readLongItem(b []byte, sizeLen int, kind Kind) (Kind, int, int, error) {
92 size, err := readSize(b[1:], sizeLen)
93 if err != nil {
94 return 0, 0, 0, err
95 }
96
97 if size > len(b)-1-sizeLen {
98 return 0, 0, 0, ErrValueTooLarge
99 }
100
101 return kind, 1 + sizeLen, size, nil
102}
103
104func readSize(b []byte, sizeLen int) (int, error) {
105 if sizeLen == 0 || sizeLen > 8 || len(b) < sizeLen {
106 return 0, ErrUnexpectedEOF
107 }
108
109 if b[0] == 0 {
110 return 0, ErrCanonSize
111 }
112
113 var size uint64
114 for i := 0; i < sizeLen; i++ {
115 size = (size << 8) | uint64(b[i])
116 }
117
118 if size < 56 {
119 return 0, ErrCanonSize
120 }
121
122 if size > uint64(maxInt) {
123 return 0, ErrValueTooLarge
124 }
125
126 return int(size), nil
127}