diff options
author | Jeffrey Wilcke <geffobscura@gmail.com> | 2015-06-30 08:22:19 +0800 |
---|---|---|
committer | Jeffrey Wilcke <geffobscura@gmail.com> | 2015-06-30 08:22:19 +0800 |
commit | 7625b07dd9a2a7b5c5a504c1276eea04596ac871 (patch) | |
tree | ce2a757cd4e0591fc15815b2dfae528ae517d36e /rlp | |
parent | 72e2613a9fe3205fa5a67b72b832e03b2357ee88 (diff) | |
parent | 8f504063f465e0ca10c6bb53ee914d10a3d45c86 (diff) | |
download | go-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.go | 80 | ||||
-rw-r--r-- | rlp/encode_test.go | 9 |
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"}, |