// 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 . 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, ok := w.(*encBuffer); ok { return buf.encode(val) } if ebuf, ok := w.(EncoderBuffer); ok { return ebuf.buf.encode(val) } buf := getEncBuffer() defer encBufferPool.Put(buf) if err := buf.encode(val); err != nil { return err } return buf.toWriter(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.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) { 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 } } }