From eee96a5bb7439ccee583d23e53be018fe7c35cfb Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 7 Mar 2017 12:37:53 +0100
Subject: [PATCH] rlp: add support for "-" struct tag

---
 rlp/decode.go      | 16 ++++++++++------
 rlp/decode_test.go | 13 +++++++++++++
 rlp/encode_test.go |  1 +
 rlp/typecache.go   |  8 +++++++-
 4 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/rlp/decode.go b/rlp/decode.go
index c4e5869cc..ee0b7dbcd 100644
--- a/rlp/decode.go
+++ b/rlp/decode.go
@@ -63,12 +63,16 @@ type Decoder interface {
 // must contain an element for each decoded field. Decode returns an
 // error if there are too few or too many elements.
 //
-// The decoding of struct fields honours two struct tags, "tail" and
-// "nil". For an explanation of "tail", see the example.
-// The "nil" tag applies to pointer-typed fields and changes the
-// decoding rules for the field such that input values of size zero
-// decode as a nil pointer. This tag can be useful when decoding
-// recursive types.
+// The decoding of struct fields honours certain struct tags, "tail",
+// "nil" and "-".
+//
+// The "-" tag ignores fields.
+//
+// For an explanation of "tail", see the example.
+//
+// The "nil" tag applies to pointer-typed fields and changes the decoding
+// rules for the field such that input values of size zero decode as a nil
+// pointer. This tag can be useful when decoding recursive types.
 //
 //     type StructWithEmptyOK struct {
 //         Foo *[20]byte `rlp:"nil"`
diff --git a/rlp/decode_test.go b/rlp/decode_test.go
index 2d465b74d..d762e195d 100644
--- a/rlp/decode_test.go
+++ b/rlp/decode_test.go
@@ -339,6 +339,12 @@ var (
 	)
 )
 
+type hasIgnoredField struct {
+	A uint
+	B uint `rlp:"-"`
+	C uint
+}
+
 var decodeTests = []decodeTest{
 	// booleans
 	{input: "01", ptr: new(bool), value: true},
@@ -490,6 +496,13 @@ var decodeTests = []decodeTest{
 		value: tailRaw{A: 1, Tail: []RawValue{}},
 	},
 
+	// struct tag "-"
+	{
+		input: "C20102",
+		ptr:   new(hasIgnoredField),
+		value: hasIgnoredField{A: 1, C: 2},
+	},
+
 	// RawValue
 	{input: "01", ptr: new(RawValue), value: RawValue(unhex("01"))},
 	{input: "82FFFF", ptr: new(RawValue), value: RawValue(unhex("82FFFF"))},
diff --git a/rlp/encode_test.go b/rlp/encode_test.go
index 6f38294e4..827960f7c 100644
--- a/rlp/encode_test.go
+++ b/rlp/encode_test.go
@@ -218,6 +218,7 @@ var encTests = []encTest{
 	{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"},
 	{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
 	{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
+	{val: &hasIgnoredField{A: 1, B: 2, C: 3}, output: "C20103"},
 
 	// nil
 	{val: (*uint)(nil), output: "80"},
diff --git a/rlp/typecache.go b/rlp/typecache.go
index a2f217c66..3df799e1e 100644
--- a/rlp/typecache.go
+++ b/rlp/typecache.go
@@ -37,11 +37,12 @@ type typeinfo struct {
 type tags struct {
 	// rlp:"nil" controls whether empty input results in a nil pointer.
 	nilOK bool
-
 	// rlp:"tail" controls whether this field swallows additional list
 	// elements. It can only be set for the last field, which must be
 	// of slice type.
 	tail bool
+	// rlp:"-" ignores fields.
+	ignored bool
 }
 
 type typekey struct {
@@ -101,6 +102,9 @@ func structFields(typ reflect.Type) (fields []field, err error) {
 			if err != nil {
 				return nil, err
 			}
+			if tags.ignored {
+				continue
+			}
 			info, err := cachedTypeInfo1(f.Type, tags)
 			if err != nil {
 				return nil, err
@@ -117,6 +121,8 @@ func parseStructTag(typ reflect.Type, fi int) (tags, error) {
 	for _, t := range strings.Split(f.Tag.Get("rlp"), ",") {
 		switch t = strings.TrimSpace(t); t {
 		case "":
+		case "-":
+			ts.ignored = true
 		case "nil":
 			ts.nilOK = true
 		case "tail":
-- 
GitLab