Browse Source

rlp: add RawValue

Felix Lange 10 years ago
parent
commit
24bb68e7cf
5 changed files with 39 additions and 1 deletions
  1. 11 0
      rlp/decode.go
  2. 5 0
      rlp/decode_test.go
  3. 7 0
      rlp/encode.go
  4. 5 0
      rlp/encode_test.go
  5. 11 1
      rlp/raw.go

+ 11 - 0
rlp/decode.go

@@ -173,6 +173,8 @@ var (
 func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
 	kind := typ.Kind()
 	switch {
+	case typ == rawValueType:
+		return decodeRawValue, nil
 	case typ.Implements(decoderInterface):
 		return decodeDecoder, nil
 	case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(decoderInterface):
@@ -203,6 +205,15 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
 	}
 }
 
+func decodeRawValue(s *Stream, val reflect.Value) error {
+	r, err := s.Raw()
+	if err != nil {
+		return err
+	}
+	val.SetBytes(r)
+	return nil
+}
+
 func decodeUint(s *Stream, val reflect.Value) error {
 	typ := val.Type()
 	num, err := s.uint(typ.Bits())

+ 5 - 0
rlp/decode_test.go

@@ -438,6 +438,11 @@ var decodeTests = []decodeTest{
 		error: "rlp: expected input string or byte for uint, decoding into (rlp.recstruct).Child.I",
 	},
 
+	// RawValue
+	{input: "01", ptr: new(RawValue), value: RawValue(unhex("01"))},
+	{input: "82FFFF", ptr: new(RawValue), value: RawValue(unhex("82FFFF"))},
+	{input: "C20102", ptr: new([]RawValue), value: []RawValue{unhex("01"), unhex("02")}},
+
 	// pointers
 	{input: "00", ptr: new(*[]byte), value: &[]byte{0}},
 	{input: "80", ptr: new(*uint), value: uintp(0)},

+ 7 - 0
rlp/encode.go

@@ -354,6 +354,8 @@ var (
 func makeWriter(typ reflect.Type) (writer, error) {
 	kind := typ.Kind()
 	switch {
+	case typ == rawValueType:
+		return writeRawValue, nil
 	case typ.Implements(encoderInterface):
 		return writeEncoder, nil
 	case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface):
@@ -389,6 +391,11 @@ func isByte(typ reflect.Type) bool {
 	return typ.Kind() == reflect.Uint8 && !typ.Implements(encoderInterface)
 }
 
+func writeRawValue(val reflect.Value, w *encbuf) error {
+	w.str = append(w.str, val.Bytes()...)
+	return nil
+}
+
 func writeUint(val reflect.Value, w *encbuf) error {
 	i := val.Uint()
 	if i == 0 {

+ 5 - 0
rlp/encode_test.go

@@ -204,6 +204,11 @@ var encTests = []encTest{
 		output: "F90200CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376",
 	},
 
+	// RawValue
+	{val: RawValue(unhex("01")), output: "01"},
+	{val: RawValue(unhex("82FFFF")), output: "82FFFF"},
+	{val: []RawValue{unhex("01"), unhex("02")}, output: "C20102"},
+
 	// structs
 	{val: simplestruct{}, output: "C28080"},
 	{val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"},

+ 11 - 1
rlp/raw.go

@@ -16,7 +16,17 @@
 
 package rlp
 
-import "io"
+import (
+	"io"
+	"reflect"
+)
+
+// RawValue represents an encoded RLP value and can be used to delay
+// RLP decoding or precompute an encoding. Note that the decoder does
+// not verify whether the content of RawValues is valid RLP.
+type RawValue []byte
+
+var rawValueType = reflect.TypeOf(RawValue{})
 
 // Split returns the content of first RLP value and any
 // bytes after the value as subslices of b.