github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/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 {
    34  	case len(s) == 0:
    35  		return 1
    36  	case len(s) == 1:
    37  		if s[0] <= 0x7f {
    38  			return 1
    39  		} else {
    40  			return 2
    41  		}
    42  	default:
    43  		return uint64(headsize(uint64(len(s))) + len(s))
    44  	}
    45  }
    46  
    47  // BytesSize returns the encoded size of a byte slice.
    48  func BytesSize(b []byte) uint64 {
    49  	switch {
    50  	case len(b) == 0:
    51  		return 1
    52  	case len(b) == 1:
    53  		if b[0] <= 0x7f {
    54  			return 1
    55  		} else {
    56  			return 2
    57  		}
    58  	default:
    59  		return uint64(headsize(uint64(len(b))) + len(b))
    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 {
   109  	case len(content) == 0:
   110  		return 0, rest, nil
   111  	case len(content) == 1:
   112  		if content[0] == 0 {
   113  			return 0, b, ErrCanonInt
   114  		}
   115  		return uint64(content[0]), rest, nil
   116  	case len(content) > 8:
   117  		return 0, b, errUintOverflow
   118  	default:
   119  		x, err = readSize(content, byte(len(content)))
   120  		if err != nil {
   121  			return 0, b, ErrCanonInt
   122  		}
   123  		return x, rest, nil
   124  	}
   125  }
   126  
   127  // SplitList splits b into the content of a list and any remaining
   128  // bytes after the list.
   129  func SplitList(b []byte) (content, rest []byte, err error) {
   130  	k, content, rest, err := Split(b)
   131  	if err != nil {
   132  		return nil, b, err
   133  	}
   134  	if k != List {
   135  		return nil, b, ErrExpectedList
   136  	}
   137  	return content, rest, nil
   138  }
   139  
   140  // CountValues counts the number of encoded values in b.
   141  func CountValues(b []byte) (int, error) {
   142  	i := 0
   143  	for ; len(b) > 0; i++ {
   144  		_, tagsize, size, err := readKind(b)
   145  		if err != nil {
   146  			return 0, err
   147  		}
   148  		b = b[tagsize+size:]
   149  	}
   150  	return i, nil
   151  }
   152  
   153  func readKind(buf []byte) (k Kind, tagsize, contentsize uint64, err error) {
   154  	if len(buf) == 0 {
   155  		return 0, 0, 0, io.ErrUnexpectedEOF
   156  	}
   157  	b := buf[0]
   158  	switch {
   159  	case b < 0x80:
   160  		k = Byte
   161  		tagsize = 0
   162  		contentsize = 1
   163  	case b < 0xB8:
   164  		k = String
   165  		tagsize = 1
   166  		contentsize = uint64(b - 0x80)
   167  		// Reject strings that should've been single bytes.
   168  		if contentsize == 1 && len(buf) > 1 && buf[1] < 128 {
   169  			return 0, 0, 0, ErrCanonSize
   170  		}
   171  	case b < 0xC0:
   172  		k = String
   173  		tagsize = uint64(b-0xB7) + 1
   174  		contentsize, err = readSize(buf[1:], b-0xB7)
   175  	case b < 0xF8:
   176  		k = List
   177  		tagsize = 1
   178  		contentsize = uint64(b - 0xC0)
   179  	default:
   180  		k = List
   181  		tagsize = uint64(b-0xF7) + 1
   182  		contentsize, err = readSize(buf[1:], b-0xF7)
   183  	}
   184  	if err != nil {
   185  		return 0, 0, 0, err
   186  	}
   187  	// Reject values larger than the input slice.
   188  	if contentsize > uint64(len(buf))-tagsize {
   189  		return 0, 0, 0, ErrValueTooLarge
   190  	}
   191  	return k, tagsize, contentsize, err
   192  }
   193  
   194  func readSize(b []byte, slen byte) (uint64, error) {
   195  	if int(slen) > len(b) {
   196  		return 0, io.ErrUnexpectedEOF
   197  	}
   198  	var s uint64
   199  	switch slen {
   200  	case 1:
   201  		s = uint64(b[0])
   202  	case 2:
   203  		s = uint64(b[0])<<8 | uint64(b[1])
   204  	case 3:
   205  		s = uint64(b[0])<<16 | uint64(b[1])<<8 | uint64(b[2])
   206  	case 4:
   207  		s = uint64(b[0])<<24 | uint64(b[1])<<16 | uint64(b[2])<<8 | uint64(b[3])
   208  	case 5:
   209  		s = uint64(b[0])<<32 | uint64(b[1])<<24 | uint64(b[2])<<16 | uint64(b[3])<<8 | uint64(b[4])
   210  	case 6:
   211  		s = uint64(b[0])<<40 | uint64(b[1])<<32 | uint64(b[2])<<24 | uint64(b[3])<<16 | uint64(b[4])<<8 | uint64(b[5])
   212  	case 7:
   213  		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])
   214  	case 8:
   215  		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])
   216  	}
   217  	// Reject sizes < 56 (shouldn't have separate size) and sizes with
   218  	// leading zero bytes.
   219  	if s < 56 || b[0] == 0 {
   220  		return 0, ErrCanonSize
   221  	}
   222  	return s, nil
   223  }
   224  
   225  // AppendUint64 appends the RLP encoding of i to b, and returns the resulting slice.
   226  func AppendUint64(b []byte, i uint64) []byte {
   227  	if i == 0 {
   228  		return append(b, 0x80)
   229  	} else if i < 128 {
   230  		return append(b, byte(i))
   231  	}
   232  	switch {
   233  	case i < (1 << 8):
   234  		return append(b, 0x81, byte(i))
   235  	case i < (1 << 16):
   236  		return append(b, 0x82,
   237  			byte(i>>8),
   238  			byte(i),
   239  		)
   240  	case i < (1 << 24):
   241  		return append(b, 0x83,
   242  			byte(i>>16),
   243  			byte(i>>8),
   244  			byte(i),
   245  		)
   246  	case i < (1 << 32):
   247  		return append(b, 0x84,
   248  			byte(i>>24),
   249  			byte(i>>16),
   250  			byte(i>>8),
   251  			byte(i),
   252  		)
   253  	case i < (1 << 40):
   254  		return append(b, 0x85,
   255  			byte(i>>32),
   256  			byte(i>>24),
   257  			byte(i>>16),
   258  			byte(i>>8),
   259  			byte(i),
   260  		)
   261  
   262  	case i < (1 << 48):
   263  		return append(b, 0x86,
   264  			byte(i>>40),
   265  			byte(i>>32),
   266  			byte(i>>24),
   267  			byte(i>>16),
   268  			byte(i>>8),
   269  			byte(i),
   270  		)
   271  	case i < (1 << 56):
   272  		return append(b, 0x87,
   273  			byte(i>>48),
   274  			byte(i>>40),
   275  			byte(i>>32),
   276  			byte(i>>24),
   277  			byte(i>>16),
   278  			byte(i>>8),
   279  			byte(i),
   280  		)
   281  
   282  	default:
   283  		return append(b, 0x88,
   284  			byte(i>>56),
   285  			byte(i>>48),
   286  			byte(i>>40),
   287  			byte(i>>32),
   288  			byte(i>>24),
   289  			byte(i>>16),
   290  			byte(i>>8),
   291  			byte(i),
   292  		)
   293  	}
   294  }