aboutsummaryrefslogtreecommitdiffstats
path: root/rlp
diff options
context:
space:
mode:
authorJeffrey Wilcke <geffobscura@gmail.com>2015-06-30 08:22:19 +0800
committerJeffrey Wilcke <geffobscura@gmail.com>2015-06-30 08:22:19 +0800
commit7625b07dd9a2a7b5c5a504c1276eea04596ac871 (patch)
treece2a757cd4e0591fc15815b2dfae528ae517d36e /rlp
parent72e2613a9fe3205fa5a67b72b832e03b2357ee88 (diff)
parent8f504063f465e0ca10c6bb53ee914d10a3d45c86 (diff)
downloadgo-tangerine-7625b07dd9a2a7b5c5a504c1276eea04596ac871.tar
go-tangerine-7625b07dd9a2a7b5c5a504c1276eea04596ac871.tar.gz
go-tangerine-7625b07dd9a2a7b5c5a504c1276eea04596ac871.tar.bz2
go-tangerine-7625b07dd9a2a7b5c5a504c1276eea04596ac871.tar.lz
go-tangerine-7625b07dd9a2a7b5c5a504c1276eea04596ac871.tar.xz
go-tangerine-7625b07dd9a2a7b5c5a504c1276eea04596ac871.tar.zst
go-tangerine-7625b07dd9a2a7b5c5a504c1276eea04596ac871.zip
Merge branch 'release/0.9.34'v0.9.34
Diffstat (limited to 'rlp')
-rw-r--r--rlp/encode.go80
-rw-r--r--rlp/encode_test.go9
2 files changed, 31 insertions, 58 deletions
diff --git a/rlp/encode.go b/rlp/encode.go
index 10ff0ae79..b418fb501 100644
--- a/rlp/encode.go
+++ b/rlp/encode.go
@@ -5,12 +5,9 @@ import (
"io"
"math/big"
"reflect"
+ "sync"
)
-// TODO: put encbufs in a sync.Pool.
-// Doing that requires zeroing the buffers after use.
-// encReader will need to drop it's buffer when done.
-
var (
// Common encoded values.
// These are useful when implementing EncodeRLP.
@@ -32,46 +29,10 @@ type Encoder interface {
EncodeRLP(io.Writer) error
}
-// Flat wraps a value (which must encode as a list) so
-// it encodes as the list's elements.
-//
-// Example: suppose you have defined a type
-//
-// type foo struct { A, B uint }
-//
-// Under normal encoding rules,
-//
-// rlp.Encode(foo{1, 2}) --> 0xC20102
-//
-// This function can help you achieve the following encoding:
-//
-// rlp.Encode(rlp.Flat(foo{1, 2})) --> 0x0102
-func Flat(val interface{}) Encoder {
- return flatenc{val}
-}
-
-type flatenc struct{ val interface{} }
-
-func (e flatenc) EncodeRLP(out io.Writer) error {
- // record current output position
- var (
- eb = out.(*encbuf)
- prevstrsize = len(eb.str)
- prevnheads = len(eb.lheads)
- )
- if err := eb.encode(e.val); err != nil {
- return err
- }
- // check that a new list header has appeared
- if len(eb.lheads) == prevnheads || eb.lheads[prevnheads].offset == prevstrsize-1 {
- return fmt.Errorf("rlp.Flat: %T did not encode as list", e.val)
- }
- // remove the new list header
- newhead := eb.lheads[prevnheads]
- copy(eb.lheads[prevnheads:], eb.lheads[prevnheads+1:])
- eb.lheads = eb.lheads[:len(eb.lheads)-1]
- eb.lhsize -= headsize(uint64(newhead.size))
- return nil
+// ListSize returns the encoded size of an RLP list with the given
+// content size.
+func ListSize(contentSize uint64) uint64 {
+ return uint64(headsize(contentSize)) + contentSize
}
// Encode writes the RLP encoding of val to w. Note that Encode may
@@ -112,7 +73,9 @@ func Encode(w io.Writer, val interface{}) error {
// Avoid copying by writing to the outer encbuf directly.
return outer.encode(val)
}
- eb := newencbuf()
+ eb := encbufPool.Get().(*encbuf)
+ eb.reset()
+ defer encbufPool.Put(eb)
if err := eb.encode(val); err != nil {
return err
}
@@ -122,7 +85,9 @@ func Encode(w io.Writer, val interface{}) error {
// EncodeBytes returns the RLP encoding of val.
// Please see the documentation of Encode for the encoding rules.
func EncodeToBytes(val interface{}) ([]byte, error) {
- eb := newencbuf()
+ eb := encbufPool.Get().(*encbuf)
+ eb.reset()
+ defer encbufPool.Put(eb)
if err := eb.encode(val); err != nil {
return nil, err
}
@@ -135,7 +100,8 @@ func EncodeToBytes(val interface{}) ([]byte, error) {
//
// Please see the documentation of Encode for the encoding rules.
func EncodeToReader(val interface{}) (size int, r io.Reader, err error) {
- eb := newencbuf()
+ eb := encbufPool.Get().(*encbuf)
+ eb.reset()
if err := eb.encode(val); err != nil {
return 0, nil, err
}
@@ -182,8 +148,19 @@ func puthead(buf []byte, smalltag, largetag byte, size uint64) int {
}
}
-func newencbuf() *encbuf {
- return &encbuf{sizebuf: make([]byte, 9)}
+// 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.
@@ -295,6 +272,8 @@ type encReader struct {
func (r *encReader) Read(b []byte) (n int, err error) {
for {
if r.piece = r.next(); r.piece == nil {
+ encbufPool.Put(r.buf)
+ r.buf = nil
return n, io.EOF
}
nn := copy(b[n:], r.piece)
@@ -313,6 +292,9 @@ func (r *encReader) Read(b []byte) (n int, err error) {
// 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
diff --git a/rlp/encode_test.go b/rlp/encode_test.go
index 6eb930d6c..7b70a0629 100644
--- a/rlp/encode_test.go
+++ b/rlp/encode_test.go
@@ -189,15 +189,6 @@ var encTests = []encTest{
{val: &recstruct{5, nil}, output: "C205C0"},
{val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"},
- // flat
- {val: Flat(uint(1)), error: "rlp.Flat: uint did not encode as list"},
- {val: Flat(simplestruct{A: 3, B: "foo"}), output: "0383666F6F"},
- {
- // value generates more list headers after the Flat
- val: []interface{}{"foo", []uint{1, 2}, Flat([]uint{3, 4}), []uint{5, 6}, "bar"},
- output: "D083666F6FC201020304C2050683626172",
- },
-
// nil
{val: (*uint)(nil), output: "80"},
{val: (*string)(nil), output: "80"},