summaryrefslogtreecommitdiff
path: root/cli/vendor/github.com/ethereum/go-ethereum/rlp/encode.go
diff options
context:
space:
mode:
Diffstat (limited to 'cli/vendor/github.com/ethereum/go-ethereum/rlp/encode.go')
-rw-r--r--cli/vendor/github.com/ethereum/go-ethereum/rlp/encode.go471
1 files changed, 471 insertions, 0 deletions
diff --git a/cli/vendor/github.com/ethereum/go-ethereum/rlp/encode.go b/cli/vendor/github.com/ethereum/go-ethereum/rlp/encode.go
new file mode 100644
index 0000000..b96505f
--- /dev/null
+++ b/cli/vendor/github.com/ethereum/go-ethereum/rlp/encode.go
@@ -0,0 +1,471 @@
+// 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 (
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "reflect"
+
+ "github.com/ethereum/go-ethereum/rlp/internal/rlpstruct"
+)
+
+var (
+ // Common encoded values.
+ // These are useful when implementing EncodeRLP.
+ EmptyString = []byte{0x80}
+ EmptyList = []byte{0xC0}
+)
+
+var ErrNegativeBigInt = errors.New("rlp: cannot encode negative big.Int")
+
+// 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.
+//
+// Please see package-level documentation of encoding rules.
+func Encode(w io.Writer, val interface{}) error {
+ // Optimization: reuse *encBuffer when called by EncodeRLP.
+ if buf := encBufferFromWriter(w); buf != nil {
+ return buf.encode(val)
+ }
+
+ buf := getEncBuffer()
+ defer encBufferPool.Put(buf)
+ if err := buf.encode(val); err != nil {
+ return err
+ }
+ return buf.writeTo(w)
+}
+
+// EncodeToBytes returns the RLP encoding of val.
+// Please see package-level documentation for the encoding rules.
+func EncodeToBytes(val interface{}) ([]byte, error) {
+ buf := getEncBuffer()
+ defer encBufferPool.Put(buf)
+
+ if err := buf.encode(val); err != nil {
+ return nil, err
+ }
+ return buf.makeBytes(), 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) {
+ buf := getEncBuffer()
+ if err := buf.encode(val); err != nil {
+ encBufferPool.Put(buf)
+ return 0, nil, err
+ }
+ // Note: can't put the reader back into the pool here
+ // because it is held by encReader. The reader puts it
+ // back when it has been fully consumed.
+ return buf.size(), &encReader{buf: buf}, nil
+}
+
+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
+}
+
+var encoderInterface = reflect.TypeOf(new(Encoder)).Elem()
+
+// makeWriter creates a writer function for the given type.
+func makeWriter(typ reflect.Type, ts rlpstruct.Tags) (writer, error) {
+ kind := typ.Kind()
+ switch {
+ case typ == rawValueType:
+ return writeRawValue, nil
+ case typ.AssignableTo(reflect.PtrTo(bigInt)):
+ return writeBigIntPtr, nil
+ case typ.AssignableTo(bigInt):
+ return writeBigIntNoPtr, nil
+ case kind == reflect.Ptr:
+ return makePtrWriter(typ, ts)
+ case reflect.PtrTo(typ).Implements(encoderInterface):
+ return makeEncoderWriter(typ), 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 makeByteArrayWriter(typ), nil
+ case kind == reflect.Slice || kind == reflect.Array:
+ return makeSliceWriter(typ, ts)
+ case kind == reflect.Struct:
+ return makeStructWriter(typ)
+ case kind == reflect.Interface:
+ return writeInterface, nil
+ default:
+ return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ)
+ }
+}
+
+func writeRawValue(val reflect.Value, w *encBuffer) error {
+ w.str = append(w.str, val.Bytes()...)
+ return nil
+}
+
+func writeUint(val reflect.Value, w *encBuffer) error {
+ w.writeUint64(val.Uint())
+ return nil
+}
+
+func writeBool(val reflect.Value, w *encBuffer) error {
+ w.writeBool(val.Bool())
+ return nil
+}
+
+func writeBigIntPtr(val reflect.Value, w *encBuffer) error {
+ ptr := val.Interface().(*big.Int)
+ if ptr == nil {
+ w.str = append(w.str, 0x80)
+ return nil
+ }
+ if ptr.Sign() == -1 {
+ return ErrNegativeBigInt
+ }
+ w.writeBigInt(ptr)
+ return nil
+}
+
+func writeBigIntNoPtr(val reflect.Value, w *encBuffer) error {
+ i := val.Interface().(big.Int)
+ if i.Sign() == -1 {
+ return ErrNegativeBigInt
+ }
+ w.writeBigInt(&i)
+ return nil
+}
+
+func writeBytes(val reflect.Value, w *encBuffer) error {
+ w.writeBytes(val.Bytes())
+ return nil
+}
+
+func makeByteArrayWriter(typ reflect.Type) writer {
+ switch typ.Len() {
+ case 0:
+ return writeLengthZeroByteArray
+ case 1:
+ return writeLengthOneByteArray
+ default:
+ length := typ.Len()
+ return func(val reflect.Value, w *encBuffer) error {
+ if !val.CanAddr() {
+ // Getting the byte slice of val requires it to be addressable. Make it
+ // addressable by copying.
+ copy := reflect.New(val.Type()).Elem()
+ copy.Set(val)
+ val = copy
+ }
+ slice := byteArrayBytes(val, length)
+ w.encodeStringHeader(len(slice))
+ w.str = append(w.str, slice...)
+ return nil
+ }
+ }
+}
+
+func writeLengthZeroByteArray(val reflect.Value, w *encBuffer) error {
+ w.str = append(w.str, 0x80)
+ return nil
+}
+
+func writeLengthOneByteArray(val reflect.Value, w *encBuffer) error {
+ b := byte(val.Index(0).Uint())
+ if b <= 0x7f {
+ w.str = append(w.str, b)
+ } else {
+ w.str = append(w.str, 0x81, b)
+ }
+ return nil
+}
+
+func writeString(val reflect.Value, w *encBuffer) 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 writeInterface(val reflect.Value, w *encBuffer) 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 rlpstruct.Tags) (writer, error) {
+ etypeinfo := theTC.infoWhileGenerating(typ.Elem(), rlpstruct.Tags{})
+ if etypeinfo.writerErr != nil {
+ return nil, etypeinfo.writerErr
+ }
+
+ var wfn writer
+ if ts.Tail {
+ // This is for struct tail slices.
+ // w.list is not called for them.
+ wfn = func(val reflect.Value, w *encBuffer) error {
+ vlen := val.Len()
+ for i := 0; i < vlen; i++ {
+ if err := etypeinfo.writer(val.Index(i), w); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ } else {
+ // This is for regular slices and arrays.
+ wfn = func(val reflect.Value, w *encBuffer) error {
+ vlen := val.Len()
+ if vlen == 0 {
+ w.str = append(w.str, 0xC0)
+ return nil
+ }
+ listOffset := w.list()
+ for i := 0; i < vlen; i++ {
+ if err := etypeinfo.writer(val.Index(i), w); err != nil {
+ return err
+ }
+ }
+ w.listEnd(listOffset)
+ return nil
+ }
+ }
+ return wfn, nil
+}
+
+func makeStructWriter(typ reflect.Type) (writer, error) {
+ fields, err := structFields(typ)
+ if err != nil {
+ return nil, err
+ }
+ for _, f := range fields {
+ if f.info.writerErr != nil {
+ return nil, structFieldError{typ, f.index, f.info.writerErr}
+ }
+ }
+
+ var writer writer
+ firstOptionalField := firstOptionalField(fields)
+ if firstOptionalField == len(fields) {
+ // This is the writer function for structs without any optional fields.
+ writer = func(val reflect.Value, w *encBuffer) 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
+ }
+ } else {
+ // If there are any "optional" fields, the writer needs to perform additional
+ // checks to determine the output list length.
+ writer = func(val reflect.Value, w *encBuffer) error {
+ lastField := len(fields) - 1
+ for ; lastField >= firstOptionalField; lastField-- {
+ if !val.Field(fields[lastField].index).IsZero() {
+ break
+ }
+ }
+ lh := w.list()
+ for i := 0; i <= lastField; i++ {
+ if err := fields[i].info.writer(val.Field(fields[i].index), w); err != nil {
+ return err
+ }
+ }
+ w.listEnd(lh)
+ return nil
+ }
+ }
+ return writer, nil
+}
+
+func makePtrWriter(typ reflect.Type, ts rlpstruct.Tags) (writer, error) {
+ nilEncoding := byte(0xC0)
+ if typeNilKind(typ.Elem(), ts) == String {
+ nilEncoding = 0x80
+ }
+
+ etypeinfo := theTC.infoWhileGenerating(typ.Elem(), rlpstruct.Tags{})
+ if etypeinfo.writerErr != nil {
+ return nil, etypeinfo.writerErr
+ }
+
+ writer := func(val reflect.Value, w *encBuffer) error {
+ if ev := val.Elem(); ev.IsValid() {
+ return etypeinfo.writer(ev, w)
+ }
+ w.str = append(w.str, nilEncoding)
+ return nil
+ }
+ return writer, nil
+}
+
+func makeEncoderWriter(typ reflect.Type) writer {
+ if typ.Implements(encoderInterface) {
+ return func(val reflect.Value, w *encBuffer) error {
+ return val.Interface().(Encoder).EncodeRLP(w)
+ }
+ }
+ w := func(val reflect.Value, w *encBuffer) error {
+ if !val.CanAddr() {
+ // package json simply doesn't call MarshalJSON for this case, 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: unadressable value of type %v, EncodeRLP is pointer method", val.Type())
+ }
+ return val.Addr().Interface().(Encoder).EncodeRLP(w)
+ }
+ return w
+}
+
+// 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
+ }
+ }
+}