github.com/ethereum/go-ethereum@v1.16.1/rlp/raw.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package rlp 18 19 import ( 20 "io" 21 "reflect" 22 ) 23 24 // RawValue represents an encoded RLP value and can be used to delay 25 // RLP decoding or to precompute an encoding. Note that the decoder does 26 // not verify whether the content of RawValues is valid RLP. 27 type RawValue []byte 28 29 var rawValueType = reflect.TypeOf(RawValue{}) 30 31 // StringSize returns the encoded size of a string. 32 func StringSize(s string) uint64 { 33 switch n := len(s); n { 34 case 0: 35 return 1 36 case 1: 37 if s[0] <= 0x7f { 38 return 1 39 } else { 40 return 2 41 } 42 default: 43 return uint64(headsize(uint64(n)) + n) 44 } 45 } 46 47 // BytesSize returns the encoded size of a byte slice. 48 func BytesSize(b []byte) uint64 { 49 switch n := len(b); n { 50 case 0: 51 return 1 52 case 1: 53 if b[0] <= 0x7f { 54 return 1 55 } else { 56 return 2 57 } 58 default: 59 return uint64(headsize(uint64(n)) + n) 60 } 61 } 62 63 // ListSize returns the encoded size of an RLP list with the given 64 // content size. 65 func ListSize(contentSize uint64) uint64 { 66 return uint64(headsize(contentSize)) + contentSize 67 } 68 69 // IntSize returns the encoded size of the integer x. Note: The return type of this 70 // function is 'int' for backwards-compatibility reasons. The result is always positive. 71 func IntSize(x uint64) int { 72 if x < 0x80 { 73 return 1 74 } 75 return 1 + intsize(x) 76 } 77 78 // Split returns the content of first RLP value and any 79 // bytes after the value as subslices of b. 80 func Split(b []byte) (k Kind, content, rest []byte, err error) { 81 k, ts, cs, err := readKind(b) 82 if err != nil { 83 return 0, nil, b, err 84 } 85 return k, b[ts : ts+cs], b[ts+cs:], nil 86 } 87 88 // SplitString splits b into the content of an RLP string 89 // and any remaining bytes after the string. 90 func SplitString(b []byte) (content, rest []byte, err error) { 91 k, content, rest, err := Split(b) 92 if err != nil { 93 return nil, b, err 94 } 95 if k == List { 96 return nil, b, ErrExpectedString 97 } 98 return content, rest, nil 99 } 100 101 // SplitUint64 decodes an integer at the beginning of b. 102 // It also returns the remaining data after the integer in 'rest'. 103 func SplitUint64(b []byte) (x uint64, rest []byte, err error) { 104 content, rest, err := SplitString(b) 105 if err != nil { 106 return 0, b, err 107 } 108 switch n := len(content); n { 109 case 0: 110 return 0, rest, nil 111 case 1: 112 if content[0] == 0 { 113 return 0, b, ErrCanonInt 114 } 115 return uint64(content[0]), rest, nil 116 default: 117 if n > 8 { 118 return 0, b, errUintOverflow 119 } 120 121 x, err = readSize(content, byte(n)) 122 if err != nil { 123 return 0, b, ErrCanonInt 124 } 125 return x, rest, nil 126 } 127 } 128 129 // SplitList splits b into the content of a list and any remaining 130 // bytes after the list. 131 func SplitList(b []byte) (content, rest []byte, err error) { 132 k, content, rest, err := Split(b) 133 if err != nil { 134 return nil, b, err 135 } 136 if k != List { 137 return nil, b, ErrExpectedList 138 } 139 return content, rest, nil 140 } 141 142 // CountValues counts the number of encoded values in b. 143 func CountValues(b []byte) (int, error) { 144 i := 0 145 for ; len(b) > 0; i++ { 146 _, tagsize, size, err := readKind(b) 147 if err != nil { 148 return 0, err 149 } 150 b = b[tagsize+size:] 151 } 152 return i, nil 153 } 154 155 func readKind(buf []byte) (k Kind, tagsize, contentsize uint64, err error) { 156 if len(buf) == 0 { 157 return 0, 0, 0, io.ErrUnexpectedEOF 158 } 159 b := buf[0] 160 switch { 161 case b < 0x80: 162 k = Byte 163 tagsize = 0 164 contentsize = 1 165 case b < 0xB8: 166 k = String 167 tagsize = 1 168 contentsize = uint64(b - 0x80) 169 // Reject strings that should've been single bytes. 170 if contentsize == 1 && len(buf) > 1 && buf[1] < 128 { 171 return 0, 0, 0, ErrCanonSize 172 } 173 case b < 0xC0: 174 k = String 175 tagsize = uint64(b-0xB7) + 1 176 contentsize, err = readSize(buf[1:], b-0xB7) 177 case b < 0xF8: 178 k = List 179 tagsize = 1 180 contentsize = uint64(b - 0xC0) 181 default: 182 k = List 183 tagsize = uint64(b-0xF7) + 1 184 contentsize, err = readSize(buf[1:], b-0xF7) 185 } 186 if err != nil { 187 return 0, 0, 0, err 188 } 189 // Reject values larger than the input slice. 190 if contentsize > uint64(len(buf))-tagsize { 191 return 0, 0, 0, ErrValueTooLarge 192 } 193 return k, tagsize, contentsize, err 194 } 195 196 func readSize(b []byte, slen byte) (uint64, error) { 197 if int(slen) > len(b) { 198 return 0, io.ErrUnexpectedEOF 199 } 200 var s uint64 201 switch slen { 202 case 1: 203 s = uint64(b[0]) 204 case 2: 205 s = uint64(b[0])<<8 | uint64(b[1]) 206 case 3: 207 s = uint64(b[0])<<16 | uint64(b[1])<<8 | uint64(b[2]) 208 case 4: 209 s = uint64(b[0])<<24 | uint64(b[1])<<16 | uint64(b[2])<<8 | uint64(b[3]) 210 case 5: 211 s = uint64(b[0])<<32 | uint64(b[1])<<24 | uint64(b[2])<<16 | uint64(b[3])<<8 | uint64(b[4]) 212 case 6: 213 s = uint64(b[0])<<40 | uint64(b[1])<<32 | uint64(b[2])<<24 | uint64(b[3])<<16 | uint64(b[4])<<8 | uint64(b[5]) 214 case 7: 215 s = uint64(b[0])<<48 | uint64(b[1])<<40 | uint64(b[2])<<32 | uint64(b[3])<<24 | uint64(b[4])<<16 | uint64(b[5])<<8 | uint64(b[6]) 216 case 8: 217 s = uint64(b[0])<<56 | uint64(b[1])<<48 | uint64(b[2])<<40 | uint64(b[3])<<32 | uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7]) 218 } 219 // Reject sizes < 56 (shouldn't have separate size) and sizes with 220 // leading zero bytes. 221 if s < 56 || b[0] == 0 { 222 return 0, ErrCanonSize 223 } 224 return s, nil 225 } 226 227 // AppendUint64 appends the RLP encoding of i to b, and returns the resulting slice. 228 func AppendUint64(b []byte, i uint64) []byte { 229 if i == 0 { 230 return append(b, 0x80) 231 } else if i < 128 { 232 return append(b, byte(i)) 233 } 234 switch { 235 case i < (1 << 8): 236 return append(b, 0x81, byte(i)) 237 case i < (1 << 16): 238 return append(b, 0x82, 239 byte(i>>8), 240 byte(i), 241 ) 242 case i < (1 << 24): 243 return append(b, 0x83, 244 byte(i>>16), 245 byte(i>>8), 246 byte(i), 247 ) 248 case i < (1 << 32): 249 return append(b, 0x84, 250 byte(i>>24), 251 byte(i>>16), 252 byte(i>>8), 253 byte(i), 254 ) 255 case i < (1 << 40): 256 return append(b, 0x85, 257 byte(i>>32), 258 byte(i>>24), 259 byte(i>>16), 260 byte(i>>8), 261 byte(i), 262 ) 263 264 case i < (1 << 48): 265 return append(b, 0x86, 266 byte(i>>40), 267 byte(i>>32), 268 byte(i>>24), 269 byte(i>>16), 270 byte(i>>8), 271 byte(i), 272 ) 273 case i < (1 << 56): 274 return append(b, 0x87, 275 byte(i>>48), 276 byte(i>>40), 277 byte(i>>32), 278 byte(i>>24), 279 byte(i>>16), 280 byte(i>>8), 281 byte(i), 282 ) 283 284 default: 285 return append(b, 0x88, 286 byte(i>>56), 287 byte(i>>48), 288 byte(i>>40), 289 byte(i>>32), 290 byte(i>>24), 291 byte(i>>16), 292 byte(i>>8), 293 byte(i), 294 ) 295 } 296 }