475 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			475 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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 is the encoding of an empty string.
 | 
						|
	EmptyString = []byte{0x80}
 | 
						|
	// EmptyList is the encoding of an empty list.
 | 
						|
	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
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |