github.com/prajjawalk/go-ethereum@v1.9.7/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 // ListSize returns the encoded size of an RLP list with the given 32 // content size. 33 func ListSize(contentSize uint64) uint64 { 34 return uint64(headsize(contentSize)) + contentSize 35 } 36 37 // Split returns the content of first RLP value and any 38 // bytes after the value as subslices of b. 39 func Split(b []byte) (k Kind, content, rest []byte, err error) { 40 k, ts, cs, err := readKind(b) 41 if err != nil { 42 return 0, nil, b, err 43 } 44 return k, b[ts : ts+cs], b[ts+cs:], nil 45 } 46 47 // SplitString splits b into the content of an RLP string 48 // and any remaining bytes after the string. 49 func SplitString(b []byte) (content, rest []byte, err error) { 50 k, content, rest, err := Split(b) 51 if err != nil { 52 return nil, b, err 53 } 54 if k == List { 55 return nil, b, ErrExpectedString 56 } 57 return content, rest, nil 58 } 59 60 // SplitList splits b into the content of a list and any remaining 61 // bytes after the list. 62 func SplitList(b []byte) (content, rest []byte, err error) { 63 k, content, rest, err := Split(b) 64 if err != nil { 65 return nil, b, err 66 } 67 if k != List { 68 return nil, b, ErrExpectedList 69 } 70 return content, rest, nil 71 } 72 73 // CountValues counts the number of encoded values in b. 74 func CountValues(b []byte) (int, error) { 75 i := 0 76 for ; len(b) > 0; i++ { 77 _, tagsize, size, err := readKind(b) 78 if err != nil { 79 return 0, err 80 } 81 b = b[tagsize+size:] 82 } 83 return i, nil 84 } 85 86 func readKind(buf []byte) (k Kind, tagsize, contentsize uint64, err error) { 87 if len(buf) == 0 { 88 return 0, 0, 0, io.ErrUnexpectedEOF 89 } 90 b := buf[0] 91 switch { 92 case b < 0x80: 93 k = Byte 94 tagsize = 0 95 contentsize = 1 96 case b < 0xB8: 97 k = String 98 tagsize = 1 99 contentsize = uint64(b - 0x80) 100 // Reject strings that should've been single bytes. 101 if contentsize == 1 && len(buf) > 1 && buf[1] < 128 { 102 return 0, 0, 0, ErrCanonSize 103 } 104 case b < 0xC0: 105 k = String 106 tagsize = uint64(b-0xB7) + 1 107 contentsize, err = readSize(buf[1:], b-0xB7) 108 case b < 0xF8: 109 k = List 110 tagsize = 1 111 contentsize = uint64(b - 0xC0) 112 default: 113 k = List 114 tagsize = uint64(b-0xF7) + 1 115 contentsize, err = readSize(buf[1:], b-0xF7) 116 } 117 if err != nil { 118 return 0, 0, 0, err 119 } 120 // Reject values larger than the input slice. 121 if contentsize > uint64(len(buf))-tagsize { 122 return 0, 0, 0, ErrValueTooLarge 123 } 124 return k, tagsize, contentsize, err 125 } 126 127 func readSize(b []byte, slen byte) (uint64, error) { 128 if int(slen) > len(b) { 129 return 0, io.ErrUnexpectedEOF 130 } 131 var s uint64 132 switch slen { 133 case 1: 134 s = uint64(b[0]) 135 case 2: 136 s = uint64(b[0])<<8 | uint64(b[1]) 137 case 3: 138 s = uint64(b[0])<<16 | uint64(b[1])<<8 | uint64(b[2]) 139 case 4: 140 s = uint64(b[0])<<24 | uint64(b[1])<<16 | uint64(b[2])<<8 | uint64(b[3]) 141 case 5: 142 s = uint64(b[0])<<32 | uint64(b[1])<<24 | uint64(b[2])<<16 | uint64(b[3])<<8 | uint64(b[4]) 143 case 6: 144 s = uint64(b[0])<<40 | uint64(b[1])<<32 | uint64(b[2])<<24 | uint64(b[3])<<16 | uint64(b[4])<<8 | uint64(b[5]) 145 case 7: 146 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]) 147 case 8: 148 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]) 149 } 150 // Reject sizes < 56 (shouldn't have separate size) and sizes with 151 // leading zero bytes. 152 if s < 56 || b[0] == 0 { 153 return 0, ErrCanonSize 154 } 155 return s, nil 156 }