aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/ethereum/go-ethereum/rlp/encode.go
diff options
context:
space:
mode:
authorWei-Ning Huang <w@byzantine-lab.io>2019-06-12 17:31:08 +0800
committerWei-Ning Huang <w@byzantine-lab.io>2019-09-17 16:57:29 +0800
commitac088de6322fc16ebe75c2e5554be73754bf1fe2 (patch)
tree086b7827d46a4d07b834cd94be73beaabb77b734 /vendor/github.com/ethereum/go-ethereum/rlp/encode.go
parent67d565f3f0e398e99bef96827f729e3e4b0edf31 (diff)
downloadgo-tangerine-ac088de6322fc16ebe75c2e5554be73754bf1fe2.tar
go-tangerine-ac088de6322fc16ebe75c2e5554be73754bf1fe2.tar.gz
go-tangerine-ac088de6322fc16ebe75c2e5554be73754bf1fe2.tar.bz2
go-tangerine-ac088de6322fc16ebe75c2e5554be73754bf1fe2.tar.lz
go-tangerine-ac088de6322fc16ebe75c2e5554be73754bf1fe2.tar.xz
go-tangerine-ac088de6322fc16ebe75c2e5554be73754bf1fe2.tar.zst
go-tangerine-ac088de6322fc16ebe75c2e5554be73754bf1fe2.zip
Rebrand as tangerine-network/go-tangerine
Diffstat (limited to 'vendor/github.com/ethereum/go-ethereum/rlp/encode.go')
-rw-r--r--vendor/github.com/ethereum/go-ethereum/rlp/encode.go651
1 files changed, 651 insertions, 0 deletions
diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/encode.go b/vendor/github.com/ethereum/go-ethereum/rlp/encode.go
new file mode 100644
index 000000000..f255c38a9
--- /dev/null
+++ b/vendor/github.com/ethereum/go-ethereum/rlp/encode.go
@@ -0,0 +1,651 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package rlp
+
+import (
+ "fmt"
+ "io"
+ "math/big"
+ "reflect"
+ "sync"
+)
+
+var (
+ // Common encoded values.
+ // These are useful when implementing EncodeRLP.
+ EmptyString = []byte{0x80}
+ EmptyList = []byte{0xC0}
+)
+
+// Encoder is implemented by types that require custom
+// encoding rules or want to encode private fields.
+type Encoder interface {
+ // EncodeRLP should write the RLP encoding of its receiver to w.
+ // If the implementation is a pointer method, it may also be
+ // called for nil pointers.
+ //
+ // Implementations should generate valid RLP. The data written is
+ // not verified at the moment, but a future version might. It is
+ // recommended to write only a single value but writing multiple
+ // values or no value at all is also permitted.
+ EncodeRLP(io.Writer) error
+}
+
+// Encode writes the RLP encoding of val to w. Note that Encode may
+// perform many small writes in some cases. Consider making w
+// buffered.
+//
+// Encode uses the following type-dependent encoding rules:
+//
+// If the type implements the Encoder interface, Encode calls
+// EncodeRLP. This is true even for nil pointers, please see the
+// documentation for Encoder.
+//
+// To encode a pointer, the value being pointed to is encoded. For nil
+// pointers, Encode will encode the zero value of the type. A nil
+// pointer to a struct type always encodes as an empty RLP list.
+// A nil pointer to an array encodes as an empty list (or empty string
+// if the array has element type byte).
+//
+// Struct values are encoded as an RLP list of all their encoded
+// public fields. Recursive struct types are supported.
+//
+// To encode slices and arrays, the elements are encoded as an RLP
+// list of the value's elements. Note that arrays and slices with
+// element type uint8 or byte are always encoded as an RLP string.
+//
+// A Go string is encoded as an RLP string.
+//
+// An unsigned integer value is encoded as an RLP string. Zero always
+// encodes as an empty RLP string. Encode also supports *big.Int.
+//
+// Boolean values are encoded as unsigned integers zero (false) and one (true).
+//
+// An interface value encodes as the value contained in the interface.
+//
+// Signed integers are not supported, nor are floating point numbers, maps,
+// channels and functions.
+func Encode(w io.Writer, val interface{}) error {
+ if outer, ok := w.(*encbuf); ok {
+ // Encode was called by some type's EncodeRLP.
+ // Avoid copying by writing to the outer encbuf directly.
+ return outer.encode(val)
+ }
+ eb := encbufPool.Get().(*encbuf)
+ defer encbufPool.Put(eb)
+ eb.reset()
+ if err := eb.encode(val); err != nil {
+ return err
+ }
+ return eb.toWriter(w)
+}
+
+// EncodeToBytes returns the RLP encoding of val.
+// Please see the documentation of Encode for the encoding rules.
+func EncodeToBytes(val interface{}) ([]byte, error) {
+ eb := encbufPool.Get().(*encbuf)
+ defer encbufPool.Put(eb)
+ eb.reset()
+ if err := eb.encode(val); err != nil {
+ return nil, err
+ }
+ return eb.toBytes(), nil
+}
+
+// EncodeToReader returns a reader from which the RLP encoding of val
+// can be read. The returned size is the total size of the encoded
+// data.
+//
+// Please see the documentation of Encode for the encoding rules.
+func EncodeToReader(val interface{}) (size int, r io.Reader, err error) {
+ eb := encbufPool.Get().(*encbuf)
+ eb.reset()
+ if err := eb.encode(val); err != nil {
+ return 0, nil, err
+ }
+ return eb.size(), &encReader{buf: eb}, nil
+}
+
+type encbuf struct {
+ str []byte // string data, contains everything except list headers
+ lheads []*listhead // all list headers
+ lhsize int // sum of sizes of all encoded list headers
+ sizebuf []byte // 9-byte auxiliary buffer for uint encoding
+}
+
+type listhead struct {
+ offset int // index of this header in string data
+ size int // total size of encoded data (including list headers)
+}
+
+// encode writes head to the given buffer, which must be at least
+// 9 bytes long. It returns the encoded bytes.
+func (head *listhead) encode(buf []byte) []byte {
+ return buf[:puthead(buf, 0xC0, 0xF7, uint64(head.size))]
+}
+
+// headsize returns the size of a list or string header
+// for a value of the given size.
+func headsize(size uint64) int {
+ if size < 56 {
+ return 1
+ }
+ return 1 + intsize(size)
+}
+
+// puthead writes a list or string header to buf.
+// buf must be at least 9 bytes long.
+func puthead(buf []byte, smalltag, largetag byte, size uint64) int {
+ if size < 56 {
+ buf[0] = smalltag + byte(size)
+ return 1
+ }
+ sizesize := putint(buf[1:], size)
+ buf[0] = largetag + byte(sizesize)
+ return sizesize + 1
+}
+
+// encbufs are pooled.
+var encbufPool = sync.Pool{
+ New: func() interface{} { return &encbuf{sizebuf: make([]byte, 9)} },
+}
+
+func (w *encbuf) reset() {
+ w.lhsize = 0
+ if w.str != nil {
+ w.str = w.str[:0]
+ }
+ if w.lheads != nil {
+ w.lheads = w.lheads[:0]
+ }
+}
+
+// encbuf implements io.Writer so it can be passed it into EncodeRLP.
+func (w *encbuf) Write(b []byte) (int, error) {
+ w.str = append(w.str, b...)
+ return len(b), nil
+}
+
+func (w *encbuf) encode(val interface{}) error {
+ rval := reflect.ValueOf(val)
+ writer, err := cachedWriter(rval.Type())
+ if err != nil {
+ return err
+ }
+ return writer(rval, w)
+}
+
+func (w *encbuf) encodeStringHeader(size int) {
+ if size < 56 {
+ w.str = append(w.str, 0x80+byte(size))
+ } else {
+ // TODO: encode to w.str directly
+ sizesize := putint(w.sizebuf[1:], uint64(size))
+ w.sizebuf[0] = 0xB7 + byte(sizesize)
+ w.str = append(w.str, w.sizebuf[:sizesize+1]...)
+ }
+}
+
+func (w *encbuf) encodeString(b []byte) {
+ if len(b) == 1 && b[0] <= 0x7F {
+ // fits single byte, no string header
+ w.str = append(w.str, b[0])
+ } else {
+ w.encodeStringHeader(len(b))
+ w.str = append(w.str, b...)
+ }
+}
+
+func (w *encbuf) list() *listhead {
+ lh := &listhead{offset: len(w.str), size: w.lhsize}
+ w.lheads = append(w.lheads, lh)
+ return lh
+}
+
+func (w *encbuf) listEnd(lh *listhead) {
+ lh.size = w.size() - lh.offset - lh.size
+ if lh.size < 56 {
+ w.lhsize++ // length encoded into kind tag
+ } else {
+ w.lhsize += 1 + intsize(uint64(lh.size))
+ }
+}
+
+func (w *encbuf) size() int {
+ return len(w.str) + w.lhsize
+}
+
+func (w *encbuf) toBytes() []byte {
+ out := make([]byte, w.size())
+ strpos := 0
+ pos := 0
+ for _, head := range w.lheads {
+ // write string data before header
+ n := copy(out[pos:], w.str[strpos:head.offset])
+ pos += n
+ strpos += n
+ // write the header
+ enc := head.encode(out[pos:])
+ pos += len(enc)
+ }
+ // copy string data after the last list header
+ copy(out[pos:], w.str[strpos:])
+ return out
+}
+
+func (w *encbuf) toWriter(out io.Writer) (err error) {
+ strpos := 0
+ for _, head := range w.lheads {
+ // write string data before header
+ if head.offset-strpos > 0 {
+ n, err := out.Write(w.str[strpos:head.offset])
+ strpos += n
+ if err != nil {
+ return err
+ }
+ }
+ // write the header
+ enc := head.encode(w.sizebuf)
+ if _, err = out.Write(enc); err != nil {
+ return err
+ }
+ }
+ if strpos < len(w.str) {
+ // write string data after the last list header
+ _, err = out.Write(w.str[strpos:])
+ }
+ return err
+}
+
+// encReader is the io.Reader returned by EncodeToReader.
+// It releases its encbuf at EOF.
+type encReader struct {
+ buf *encbuf // the buffer we're reading from. this is nil when we're at EOF.
+ lhpos int // index of list header that we're reading
+ strpos int // current position in string buffer
+ piece []byte // next piece to be read
+}
+
+func (r *encReader) Read(b []byte) (n int, err error) {
+ for {
+ if r.piece = r.next(); r.piece == nil {
+ // Put the encode buffer back into the pool at EOF when it
+ // is first encountered. Subsequent calls still return EOF
+ // as the error but the buffer is no longer valid.
+ if r.buf != nil {
+ encbufPool.Put(r.buf)
+ r.buf = nil
+ }
+ return n, io.EOF
+ }
+ nn := copy(b[n:], r.piece)
+ n += nn
+ if nn < len(r.piece) {
+ // piece didn't fit, see you next time.
+ r.piece = r.piece[nn:]
+ return n, nil
+ }
+ r.piece = nil
+ }
+}
+
+// next returns the next piece of data to be read.
+// it returns nil at EOF.
+func (r *encReader) next() []byte {
+ switch {
+ case r.buf == nil:
+ return nil
+
+ case r.piece != nil:
+ // There is still data available for reading.
+ return r.piece
+
+ case r.lhpos < len(r.buf.lheads):
+ // We're before the last list header.
+ head := r.buf.lheads[r.lhpos]
+ sizebefore := head.offset - r.strpos
+ if sizebefore > 0 {
+ // String data before header.
+ p := r.buf.str[r.strpos:head.offset]
+ r.strpos += sizebefore
+ return p
+ }
+ r.lhpos++
+ return head.encode(r.buf.sizebuf)
+
+ case r.strpos < len(r.buf.str):
+ // String data at the end, after all list headers.
+ p := r.buf.str[r.strpos:]
+ r.strpos = len(r.buf.str)
+ return p
+
+ default:
+ return nil
+ }
+}
+
+var (
+ encoderInterface = reflect.TypeOf(new(Encoder)).Elem()
+ big0 = big.NewInt(0)
+)
+
+// makeWriter creates a writer function for the given type.
+func makeWriter(typ reflect.Type, ts tags) (writer, error) {
+ kind := typ.Kind()
+ switch {
+ case typ == rawValueType:
+ return writeRawValue, nil
+ case typ.Implements(encoderInterface):
+ return writeEncoder, nil
+ case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface):
+ return writeEncoderNoPtr, nil
+ case kind == reflect.Interface:
+ return writeInterface, nil
+ case typ.AssignableTo(reflect.PtrTo(bigInt)):
+ return writeBigIntPtr, nil
+ case typ.AssignableTo(bigInt):
+ return writeBigIntNoPtr, nil
+ case isUint(kind):
+ return writeUint, nil
+ case kind == reflect.Bool:
+ return writeBool, nil
+ case kind == reflect.String:
+ return writeString, nil
+ case kind == reflect.Slice && isByte(typ.Elem()):
+ return writeBytes, nil
+ case kind == reflect.Array && isByte(typ.Elem()):
+ return writeByteArray, nil
+ case kind == reflect.Slice || kind == reflect.Array:
+ return makeSliceWriter(typ, ts)
+ case kind == reflect.Struct:
+ return makeStructWriter(typ)
+ case kind == reflect.Ptr:
+ return makePtrWriter(typ)
+ default:
+ return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ)
+ }
+}
+
+func isByte(typ reflect.Type) bool {
+ return typ.Kind() == reflect.Uint8 && !typ.Implements(encoderInterface)
+}
+
+func writeRawValue(val reflect.Value, w *encbuf) error {
+ w.str = append(w.str, val.Bytes()...)
+ return nil
+}
+
+func writeUint(val reflect.Value, w *encbuf) error {
+ i := val.Uint()
+ if i == 0 {
+ w.str = append(w.str, 0x80)
+ } else if i < 128 {
+ // fits single byte
+ w.str = append(w.str, byte(i))
+ } else {
+ // TODO: encode int to w.str directly
+ s := putint(w.sizebuf[1:], i)
+ w.sizebuf[0] = 0x80 + byte(s)
+ w.str = append(w.str, w.sizebuf[:s+1]...)
+ }
+ return nil
+}
+
+func writeBool(val reflect.Value, w *encbuf) error {
+ if val.Bool() {
+ w.str = append(w.str, 0x01)
+ } else {
+ w.str = append(w.str, 0x80)
+ }
+ return nil
+}
+
+func writeBigIntPtr(val reflect.Value, w *encbuf) error {
+ ptr := val.Interface().(*big.Int)
+ if ptr == nil {
+ w.str = append(w.str, 0x80)
+ return nil
+ }
+ return writeBigInt(ptr, w)
+}
+
+func writeBigIntNoPtr(val reflect.Value, w *encbuf) error {
+ i := val.Interface().(big.Int)
+ return writeBigInt(&i, w)
+}
+
+func writeBigInt(i *big.Int, w *encbuf) error {
+ if cmp := i.Cmp(big0); cmp == -1 {
+ return fmt.Errorf("rlp: cannot encode negative *big.Int")
+ } else if cmp == 0 {
+ w.str = append(w.str, 0x80)
+ } else {
+ w.encodeString(i.Bytes())
+ }
+ return nil
+}
+
+func writeBytes(val reflect.Value, w *encbuf) error {
+ w.encodeString(val.Bytes())
+ return nil
+}
+
+func writeByteArray(val reflect.Value, w *encbuf) error {
+ if !val.CanAddr() {
+ // Slice requires the value to be addressable.
+ // Make it addressable by copying.
+ copy := reflect.New(val.Type()).Elem()
+ copy.Set(val)
+ val = copy
+ }
+ size := val.Len()
+ slice := val.Slice(0, size).Bytes()
+ w.encodeString(slice)
+ return nil
+}
+
+func writeString(val reflect.Value, w *encbuf) error {
+ s := val.String()
+ if len(s) == 1 && s[0] <= 0x7f {
+ // fits single byte, no string header
+ w.str = append(w.str, s[0])
+ } else {
+ w.encodeStringHeader(len(s))
+ w.str = append(w.str, s...)
+ }
+ return nil
+}
+
+func writeEncoder(val reflect.Value, w *encbuf) error {
+ return val.Interface().(Encoder).EncodeRLP(w)
+}
+
+// writeEncoderNoPtr handles non-pointer values that implement Encoder
+// with a pointer receiver.
+func writeEncoderNoPtr(val reflect.Value, w *encbuf) error {
+ if !val.CanAddr() {
+ // We can't get the address. It would be possible to make the
+ // value addressable by creating a shallow copy, but this
+ // creates other problems so we're not doing it (yet).
+ //
+ // package json simply doesn't call MarshalJSON for cases like
+ // this, but encodes the value as if it didn't implement the
+ // interface. We don't want to handle it that way.
+ return fmt.Errorf("rlp: game over: unadressable value of type %v, EncodeRLP is pointer method", val.Type())
+ }
+ return val.Addr().Interface().(Encoder).EncodeRLP(w)
+}
+
+func writeInterface(val reflect.Value, w *encbuf) error {
+ if val.IsNil() {
+ // Write empty list. This is consistent with the previous RLP
+ // encoder that we had and should therefore avoid any
+ // problems.
+ w.str = append(w.str, 0xC0)
+ return nil
+ }
+ eval := val.Elem()
+ writer, err := cachedWriter(eval.Type())
+ if err != nil {
+ return err
+ }
+ return writer(eval, w)
+}
+
+func makeSliceWriter(typ reflect.Type, ts tags) (writer, error) {
+ etypeinfo := cachedTypeInfo1(typ.Elem(), tags{})
+ if etypeinfo.writerErr != nil {
+ return nil, etypeinfo.writerErr
+ }
+ writer := func(val reflect.Value, w *encbuf) error {
+ if !ts.tail {
+ defer w.listEnd(w.list())
+ }
+ vlen := val.Len()
+ for i := 0; i < vlen; i++ {
+ if err := etypeinfo.writer(val.Index(i), w); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ return writer, nil
+}
+
+func makeStructWriter(typ reflect.Type) (writer, error) {
+ fields, err := structFields(typ)
+ if err != nil {
+ return nil, err
+ }
+ writer := func(val reflect.Value, w *encbuf) error {
+ lh := w.list()
+ for _, f := range fields {
+ if err := f.info.writer(val.Field(f.index), w); err != nil {
+ return err
+ }
+ }
+ w.listEnd(lh)
+ return nil
+ }
+ return writer, nil
+}
+
+func makePtrWriter(typ reflect.Type) (writer, error) {
+ etypeinfo := cachedTypeInfo1(typ.Elem(), tags{})
+ if etypeinfo.writerErr != nil {
+ return nil, etypeinfo.writerErr
+ }
+
+ // determine nil pointer handler
+ var nilfunc func(*encbuf) error
+ kind := typ.Elem().Kind()
+ switch {
+ case kind == reflect.Array && isByte(typ.Elem().Elem()):
+ nilfunc = func(w *encbuf) error {
+ w.str = append(w.str, 0x80)
+ return nil
+ }
+ case kind == reflect.Struct || kind == reflect.Array:
+ nilfunc = func(w *encbuf) error {
+ // encoding the zero value of a struct/array could trigger
+ // infinite recursion, avoid that.
+ w.listEnd(w.list())
+ return nil
+ }
+ default:
+ zero := reflect.Zero(typ.Elem())
+ nilfunc = func(w *encbuf) error {
+ return etypeinfo.writer(zero, w)
+ }
+ }
+
+ writer := func(val reflect.Value, w *encbuf) error {
+ if val.IsNil() {
+ return nilfunc(w)
+ }
+ return etypeinfo.writer(val.Elem(), w)
+ }
+ return writer, nil
+}
+
+// putint writes i to the beginning of b in big endian byte
+// order, using the least number of bytes needed to represent i.
+func putint(b []byte, i uint64) (size int) {
+ switch {
+ case i < (1 << 8):
+ b[0] = byte(i)
+ return 1
+ case i < (1 << 16):
+ b[0] = byte(i >> 8)
+ b[1] = byte(i)
+ return 2
+ case i < (1 << 24):
+ b[0] = byte(i >> 16)
+ b[1] = byte(i >> 8)
+ b[2] = byte(i)
+ return 3
+ case i < (1 << 32):
+ b[0] = byte(i >> 24)
+ b[1] = byte(i >> 16)
+ b[2] = byte(i >> 8)
+ b[3] = byte(i)
+ return 4
+ case i < (1 << 40):
+ b[0] = byte(i >> 32)
+ b[1] = byte(i >> 24)
+ b[2] = byte(i >> 16)
+ b[3] = byte(i >> 8)
+ b[4] = byte(i)
+ return 5
+ case i < (1 << 48):
+ b[0] = byte(i >> 40)
+ b[1] = byte(i >> 32)
+ b[2] = byte(i >> 24)
+ b[3] = byte(i >> 16)
+ b[4] = byte(i >> 8)
+ b[5] = byte(i)
+ return 6
+ case i < (1 << 56):
+ b[0] = byte(i >> 48)
+ b[1] = byte(i >> 40)
+ b[2] = byte(i >> 32)
+ b[3] = byte(i >> 24)
+ b[4] = byte(i >> 16)
+ b[5] = byte(i >> 8)
+ b[6] = byte(i)
+ return 7
+ default:
+ b[0] = byte(i >> 56)
+ b[1] = byte(i >> 48)
+ b[2] = byte(i >> 40)
+ b[3] = byte(i >> 32)
+ b[4] = byte(i >> 24)
+ b[5] = byte(i >> 16)
+ b[6] = byte(i >> 8)
+ b[7] = byte(i)
+ return 8
+ }
+}
+
+// intsize computes the minimum number of bytes required to store i.
+func intsize(i uint64) (size int) {
+ for size = 1; ; size++ {
+ if i >>= 8; i == 0 {
+ return size
+ }
+ }
+}