aboutsummaryrefslogtreecommitdiffstats
path: root/rlp/encode.go
diff options
context:
space:
mode:
authorEthan Buchman <ethan@coinculture.info>2015-02-18 08:25:18 +0800
committerEthan Buchman <ethan@coinculture.info>2015-02-18 08:25:18 +0800
commit2ba65f4fbaea49c1e0d99959b0331e09b153f931 (patch)
treeadd8cabb05cd7fbf0ba4b4bbaf9460dacfc2082d /rlp/encode.go
parent2da367a2bee84d74d1bb0ea1b42d4c22fae486dd (diff)
parent60318c96d03bcaaf731802b1080a3d87cb482124 (diff)
downloaddexon-2ba65f4fbaea49c1e0d99959b0331e09b153f931.tar
dexon-2ba65f4fbaea49c1e0d99959b0331e09b153f931.tar.gz
dexon-2ba65f4fbaea49c1e0d99959b0331e09b153f931.tar.bz2
dexon-2ba65f4fbaea49c1e0d99959b0331e09b153f931.tar.lz
dexon-2ba65f4fbaea49c1e0d99959b0331e09b153f931.tar.xz
dexon-2ba65f4fbaea49c1e0d99959b0331e09b153f931.tar.zst
dexon-2ba65f4fbaea49c1e0d99959b0331e09b153f931.zip
Merge branch 'develop' of https://github.com/ethereum/go-ethereum into develop
Diffstat (limited to 'rlp/encode.go')
-rw-r--r--rlp/encode.go71
1 files changed, 70 insertions, 1 deletions
diff --git a/rlp/encode.go b/rlp/encode.go
index d80b66315..9d11d66bf 100644
--- a/rlp/encode.go
+++ b/rlp/encode.go
@@ -32,6 +32,48 @@ 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 -= newhead.tagsize()
+ return nil
+}
+
// Encode writes the RLP encoding of val to w. Note that Encode may
// perform many small writes in some cases. Consider making w
// buffered.
@@ -123,6 +165,13 @@ func (head *listhead) encode(buf []byte) []byte {
}
}
+func (head *listhead) tagsize() int {
+ if head.size < 56 {
+ return 1
+ }
+ return 1 + intsize(uint64(head.size))
+}
+
func newencbuf() *encbuf {
return &encbuf{sizebuf: make([]byte, 9)}
}
@@ -301,8 +350,10 @@ func makeWriter(typ reflect.Type) (writer, error) {
return writeUint, nil
case kind == reflect.String:
return writeString, nil
- case kind == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 && !typ.Elem().Implements(encoderInterface):
+ case kind == reflect.Slice && isByte(typ.Elem()):
return writeBytes, nil
+ case kind == reflect.Array && isByte(typ.Elem()):
+ return writeByteArray, nil
case kind == reflect.Slice || kind == reflect.Array:
return makeSliceWriter(typ)
case kind == reflect.Struct:
@@ -314,6 +365,10 @@ func makeWriter(typ reflect.Type) (writer, error) {
}
}
+func isByte(typ reflect.Type) bool {
+ return typ.Kind() == reflect.Uint8 && !typ.Implements(encoderInterface)
+}
+
func writeUint(val reflect.Value, w *encbuf) error {
i := val.Uint()
if i == 0 {
@@ -358,6 +413,20 @@ func writeBytes(val reflect.Value, w *encbuf) error {
return nil
}
+func writeByteArray(val reflect.Value, w *encbuf) error {
+ if !val.CanAddr() {
+ // Slice requires the value to be addressable.
+ // Make it addressable by copying.
+ copy := reflect.New(val.Type()).Elem()
+ copy.Set(val)
+ val = copy
+ }
+ size := val.Len()
+ slice := val.Slice(0, size).Bytes()
+ w.encodeString(slice)
+ return nil
+}
+
func writeString(val reflect.Value, w *encbuf) error {
s := val.String()
w.encodeStringHeader(len(s))