M marshal.go => marshal.go +11 -0
@@ 26,6 26,11 @@ var encoderBufferPool = sync.Pool{
//
// Go "int" and "uint" types are represented as BARE u32 and i32 types
// respectively, for message compatibility with both 32-bit and 64-bit systems.
+//
+// The encoding of each struct field can be customized by the format string
+// stored under the "bare" key in the struct field's tag.
+//
+// As a special case, if the field tag is "-", the field is always omitted.
func Marshal(val interface{}) ([]byte, error) {
// reuse buffers from previous serializations
b := encoderBufferPool.Get().(*bytes.Buffer)
@@ 127,11 132,17 @@ func encodeStruct(t reflect.Type) encodeFunc {
encoders := make([]encodeFunc, n)
for i := 0; i < n; i++ {
field := t.Field(i)
+ if field.Tag.Get("bare") == "-" {
+ continue
+ }
encoders[i] = getEncoder(field.Type)
}
return func(w *Writer, v reflect.Value) error {
for i := 0; i < n; i++ {
+ if encoders[i] == nil {
+ continue
+ }
err := encoders[i](w, v.Field(i))
if err != nil {
return err
M marshal_test.go => marshal_test.go +13 -0
@@ 162,6 162,19 @@ func TestMarshalStruct(t *testing.T) {
assert.Equal(t, reference, data)
}
+func TestMarshalOmittedFields(t *testing.T) {
+ type Coordinates struct {
+ X uint
+ Y uint
+ Z uint `bare:"-"`
+ }
+ coords := Coordinates{1, 2, 3}
+ reference := []byte{0x01, 0x02}
+ data, err := Marshal(&coords)
+ assert.Nil(t, err)
+ assert.Equal(t, reference, data)
+}
+
func TestMarshalArray(t *testing.T) {
val := [4]uint8{0x11, 0x22, 0x33, 0x44}
reference := []byte{0x11, 0x22, 0x33, 0x44}
M unmarshal.go => unmarshal.go +6 -0
@@ 125,11 125,17 @@ func decodeStruct(t reflect.Type) decodeFunc {
decoders := make([]decodeFunc, n)
for i := 0; i < n; i++ {
field := t.Field(i)
+ if field.Tag.Get("bare") == "-" {
+ continue
+ }
decoders[i] = getDecoder(field.Type)
}
return func(r *Reader, v reflect.Value) error {
for i := 0; i < n; i++ {
+ if decoders[i] == nil {
+ continue
+ }
err := decoders[i](r, v.Field(i))
if err != nil {
return err
M unmarshal_test.go => unmarshal_test.go +15 -0
@@ 135,6 135,21 @@ func TestUnmarshalStruct(t *testing.T) {
assert.Equal(t, uint(3), coords.Z, "Expected Unmarshal to read {1, 2, 3}")
}
+func TestUnmarshalOmittedFields(t *testing.T) {
+ type Coordinates struct {
+ X uint
+ Y uint
+ Z uint `bare:"-"`
+ }
+ payload := []byte{0x01, 0x02}
+ var coords Coordinates
+ err := Unmarshal(payload, &coords)
+ assert.Nil(t, err, "Expected Unmarshal to return without error")
+ assert.Equal(t, uint(1), coords.X, "Expected Unmarshal to read {1, 2}")
+ assert.Equal(t, uint(2), coords.Y, "Expected Unmarshal to read {1, 2}")
+ assert.Equal(t, uint(0), coords.Z, "Expected Unmarshal to ignore field")
+}
+
func TestUnmarshalArray(t *testing.T) {
var val [4]uint8
err := Unmarshal([]byte{0x11, 0x22, 0x33, 0x44}, &val)