github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/common/rlp.go (about)

     1  // Copyright 2014 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 common
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"math/big"
    23  	"reflect"
    24  )
    25  
    26  type RlpEncode interface {
    27  	RlpEncode() []byte
    28  }
    29  
    30  type RlpEncodeDecode interface {
    31  	RlpEncode
    32  	RlpValue() []interface{}
    33  }
    34  
    35  type RlpEncodable interface {
    36  	RlpData() interface{}
    37  }
    38  
    39  func Rlp(encoder RlpEncode) []byte {
    40  	return encoder.RlpEncode()
    41  }
    42  
    43  type RlpEncoder struct {
    44  	rlpData []byte
    45  }
    46  
    47  func NewRlpEncoder() *RlpEncoder {
    48  	encoder := &RlpEncoder{}
    49  
    50  	return encoder
    51  }
    52  func (coder *RlpEncoder) EncodeData(rlpData interface{}) []byte {
    53  	return Encode(rlpData)
    54  }
    55  
    56  const (
    57  	RlpEmptyList = 0x80
    58  	RlpEmptyStr  = 0x40
    59  )
    60  
    61  const rlpEof = -1
    62  
    63  func Char(c []byte) int {
    64  	if len(c) > 0 {
    65  		return int(c[0])
    66  	}
    67  
    68  	return rlpEof
    69  }
    70  
    71  func DecodeWithReader(reader *bytes.Buffer) interface{} {
    72  	var slice []interface{}
    73  
    74  	// Read the next byte
    75  	char := Char(reader.Next(1))
    76  	switch {
    77  	case char <= 0x7f:
    78  		return char
    79  
    80  	case char <= 0xb7:
    81  		return reader.Next(int(char - 0x80))
    82  
    83  	case char <= 0xbf:
    84  		length := ReadVarInt(reader.Next(int(char - 0xb7)))
    85  
    86  		return reader.Next(int(length))
    87  
    88  	case char <= 0xf7:
    89  		length := int(char - 0xc0)
    90  		for i := 0; i < length; i++ {
    91  			obj := DecodeWithReader(reader)
    92  			slice = append(slice, obj)
    93  		}
    94  
    95  		return slice
    96  	case char <= 0xff:
    97  		length := ReadVarInt(reader.Next(int(char - 0xf7)))
    98  		for i := uint64(0); i < length; i++ {
    99  			obj := DecodeWithReader(reader)
   100  			slice = append(slice, obj)
   101  		}
   102  
   103  		return slice
   104  	default:
   105  		panic(fmt.Sprintf("byte not supported: %q", char))
   106  	}
   107  
   108  	return slice
   109  }
   110  
   111  var (
   112  	directRlp = big.NewInt(0x7f)
   113  	numberRlp = big.NewInt(0xb7)
   114  	zeroRlp   = big.NewInt(0x0)
   115  )
   116  
   117  func intlen(i int64) (length int) {
   118  	for i > 0 {
   119  		i = i >> 8
   120  		length++
   121  	}
   122  	return
   123  }
   124  
   125  func Encode(object interface{}) []byte {
   126  	var buff bytes.Buffer
   127  
   128  	if object != nil {
   129  		switch t := object.(type) {
   130  		case *Value:
   131  			buff.Write(Encode(t.Val))
   132  		case RlpEncodable:
   133  			buff.Write(Encode(t.RlpData()))
   134  		// Code dup :-/
   135  		case int:
   136  			buff.Write(Encode(big.NewInt(int64(t))))
   137  		case uint:
   138  			buff.Write(Encode(big.NewInt(int64(t))))
   139  		case int8:
   140  			buff.Write(Encode(big.NewInt(int64(t))))
   141  		case int16:
   142  			buff.Write(Encode(big.NewInt(int64(t))))
   143  		case int32:
   144  			buff.Write(Encode(big.NewInt(int64(t))))
   145  		case int64:
   146  			buff.Write(Encode(big.NewInt(t)))
   147  		case uint16:
   148  			buff.Write(Encode(big.NewInt(int64(t))))
   149  		case uint32:
   150  			buff.Write(Encode(big.NewInt(int64(t))))
   151  		case uint64:
   152  			buff.Write(Encode(big.NewInt(int64(t))))
   153  		case byte:
   154  			buff.Write(Encode(big.NewInt(int64(t))))
   155  		case *big.Int:
   156  			// Not sure how this is possible while we check for nil
   157  			if t == nil {
   158  				buff.WriteByte(0xc0)
   159  			} else {
   160  				buff.Write(Encode(t.Bytes()))
   161  			}
   162  		case Bytes:
   163  			buff.Write(Encode([]byte(t)))
   164  		case []byte:
   165  			if len(t) == 1 && t[0] <= 0x7f {
   166  				buff.Write(t)
   167  			} else if len(t) < 56 {
   168  				buff.WriteByte(byte(len(t) + 0x80))
   169  				buff.Write(t)
   170  			} else {
   171  				b := big.NewInt(int64(len(t)))
   172  				buff.WriteByte(byte(len(b.Bytes()) + 0xb7))
   173  				buff.Write(b.Bytes())
   174  				buff.Write(t)
   175  			}
   176  		case string:
   177  			buff.Write(Encode([]byte(t)))
   178  		case []interface{}:
   179  			// Inline function for writing the slice header
   180  			WriteSliceHeader := func(length int) {
   181  				if length < 56 {
   182  					buff.WriteByte(byte(length + 0xc0))
   183  				} else {
   184  					b := big.NewInt(int64(length))
   185  					buff.WriteByte(byte(len(b.Bytes()) + 0xf7))
   186  					buff.Write(b.Bytes())
   187  				}
   188  			}
   189  
   190  			var b bytes.Buffer
   191  			for _, val := range t {
   192  				b.Write(Encode(val))
   193  			}
   194  			WriteSliceHeader(len(b.Bytes()))
   195  			buff.Write(b.Bytes())
   196  		default:
   197  			// This is how it should have been from the start
   198  			// needs refactoring (@fjl)
   199  			v := reflect.ValueOf(t)
   200  			switch v.Kind() {
   201  			case reflect.Slice:
   202  				var b bytes.Buffer
   203  				for i := 0; i < v.Len(); i++ {
   204  					b.Write(Encode(v.Index(i).Interface()))
   205  				}
   206  
   207  				blen := b.Len()
   208  				if blen < 56 {
   209  					buff.WriteByte(byte(blen) + 0xc0)
   210  				} else {
   211  					ilen := byte(intlen(int64(blen)))
   212  					buff.WriteByte(ilen + 0xf7)
   213  					t := make([]byte, ilen)
   214  					for i := byte(0); i < ilen; i++ {
   215  						t[ilen-i-1] = byte(blen >> (i * 8))
   216  					}
   217  					buff.Write(t)
   218  				}
   219  				buff.ReadFrom(&b)
   220  			}
   221  		}
   222  	} else {
   223  		// Empty list for nil
   224  		buff.WriteByte(0xc0)
   225  	}
   226  
   227  	return buff.Bytes()
   228  }
   229  
   230  // TODO Use a bytes.Buffer instead of a raw byte slice.
   231  // Cleaner code, and use draining instead of seeking the next bytes to read
   232  func Decode(data []byte, pos uint64) (interface{}, uint64) {
   233  	var slice []interface{}
   234  	char := int(data[pos])
   235  	switch {
   236  	case char <= 0x7f:
   237  		return data[pos], pos + 1
   238  
   239  	case char <= 0xb7:
   240  		b := uint64(data[pos]) - 0x80
   241  
   242  		return data[pos+1 : pos+1+b], pos + 1 + b
   243  
   244  	case char <= 0xbf:
   245  		b := uint64(data[pos]) - 0xb7
   246  
   247  		b2 := ReadVarInt(data[pos+1 : pos+1+b])
   248  
   249  		return data[pos+1+b : pos+1+b+b2], pos + 1 + b + b2
   250  
   251  	case char <= 0xf7:
   252  		b := uint64(data[pos]) - 0xc0
   253  		prevPos := pos
   254  		pos++
   255  		for i := uint64(0); i < b; {
   256  			var obj interface{}
   257  
   258  			// Get the next item in the data list and append it
   259  			obj, prevPos = Decode(data, pos)
   260  			slice = append(slice, obj)
   261  
   262  			// Increment i by the amount bytes read in the previous
   263  			// read
   264  			i += (prevPos - pos)
   265  			pos = prevPos
   266  		}
   267  		return slice, pos
   268  
   269  	case char <= 0xff:
   270  		l := uint64(data[pos]) - 0xf7
   271  		b := ReadVarInt(data[pos+1 : pos+1+l])
   272  
   273  		pos = pos + l + 1
   274  
   275  		prevPos := b
   276  		for i := uint64(0); i < uint64(b); {
   277  			var obj interface{}
   278  
   279  			obj, prevPos = Decode(data, pos)
   280  			slice = append(slice, obj)
   281  
   282  			i += (prevPos - pos)
   283  			pos = prevPos
   284  		}
   285  		return slice, pos
   286  
   287  	default:
   288  		panic(fmt.Sprintf("byte not supported: %q", char))
   289  	}
   290  
   291  	return slice, 0
   292  }