github.com/luckypickle/go-ethereum-vet@v1.14.2/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  }