diff --git a/pkg/object/attribute.go b/pkg/object/attribute.go index 0b43bcce..6af3d21f 100644 --- a/pkg/object/attribute.go +++ b/pkg/object/attribute.go @@ -43,3 +43,35 @@ func (a *Attribute) SetValue(v string) { func (a *Attribute) ToV2() *object.Attribute { return (*object.Attribute)(a) } + +// Marshal marshals Attribute into a protobuf binary form. +// +// Buffer is allocated when the argument is empty. +// Otherwise, the first buffer is used. +func (d *Attribute) Marshal(b ...[]byte) ([]byte, error) { + var buf []byte + if len(b) > 0 { + buf = b[0] + } + + return (*object.Attribute)(d). + StableMarshal(buf) +} + +// Unmarshal unmarshals protobuf binary representation of Attribute. +func (d *Attribute) Unmarshal(data []byte) error { + return (*object.Attribute)(d). + Unmarshal(data) +} + +// MarshalJSON encodes Attribute to protobuf JSON format. +func (d *Attribute) MarshalJSON() ([]byte, error) { + return (*object.Attribute)(d). + MarshalJSON() +} + +// UnmarshalJSON decodes Attribute from protobuf JSON format. +func (d *Attribute) UnmarshalJSON(data []byte) error { + return (*object.Attribute)(d). + UnmarshalJSON(data) +} diff --git a/pkg/object/attribute_test.go b/pkg/object/attribute_test.go index cc503e49..500ec2c4 100644 --- a/pkg/object/attribute_test.go +++ b/pkg/object/attribute_test.go @@ -21,3 +21,29 @@ func TestAttribute(t *testing.T) { require.Equal(t, key, aV2.GetKey()) require.Equal(t, val, aV2.GetValue()) } + +func TestAttributeEncoding(t *testing.T) { + a := NewAttribute() + a.SetKey("key") + a.SetValue("value") + + t.Run("binary", func(t *testing.T) { + data, err := a.Marshal() + require.NoError(t, err) + + a2 := NewAttribute() + require.NoError(t, a2.Unmarshal(data)) + + require.Equal(t, a, a2) + }) + + t.Run("json", func(t *testing.T) { + data, err := a.MarshalJSON() + require.NoError(t, err) + + a2 := NewAttribute() + require.NoError(t, a2.UnmarshalJSON(data)) + + require.Equal(t, a, a2) + }) +} diff --git a/v2/object/json.go b/v2/object/json.go index 8038523b..7a3c2463 100644 --- a/v2/object/json.go +++ b/v2/object/json.go @@ -24,3 +24,23 @@ func (h *ShortHeader) UnmarshalJSON(data []byte) error { return nil } + +func (a *Attribute) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{ + EmitUnpopulated: true, + }.Marshal( + AttributeToGRPCMessage(a), + ) +} + +func (a *Attribute) UnmarshalJSON(data []byte) error { + msg := new(object.Header_Attribute) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + *a = *AttributeFromGRPCMessage(msg) + + return nil +} diff --git a/v2/object/json_test.go b/v2/object/json_test.go index 51d0aee8..aa82f633 100644 --- a/v2/object/json_test.go +++ b/v2/object/json_test.go @@ -18,3 +18,15 @@ func TestShortHeaderJSON(t *testing.T) { require.Equal(t, h, h2) } + +func TestAttributeJSON(t *testing.T) { + a := generateAttribute("key", "value") + + data, err := a.MarshalJSON() + require.NoError(t, err) + + a2 := new(object.Attribute) + require.NoError(t, a2.UnmarshalJSON(data)) + + require.Equal(t, a, a2) +} diff --git a/v2/object/marshal.go b/v2/object/marshal.go index 5e080c92..657ddf15 100644 --- a/v2/object/marshal.go +++ b/v2/object/marshal.go @@ -213,6 +213,17 @@ func (a *Attribute) StableSize() (size int) { return size } +func (a *Attribute) Unmarshal(data []byte) error { + m := new(object.Header_Attribute) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + *a = *AttributeFromGRPCMessage(m) + + return nil +} + func (h *SplitHeader) StableMarshal(buf []byte) ([]byte, error) { if h == nil { return []byte{}, nil diff --git a/v2/object/marshal_test.go b/v2/object/marshal_test.go index 505c6b1c..f73766e3 100644 --- a/v2/object/marshal_test.go +++ b/v2/object/marshal_test.go @@ -29,16 +29,14 @@ func TestShortHeader_StableMarshal(t *testing.T) { func TestAttribute_StableMarshal(t *testing.T) { from := generateAttribute("Key", "Value") - transport := new(grpc.Header_Attribute) t.Run("non empty", func(t *testing.T) { wire, err := from.StableMarshal(nil) require.NoError(t, err) - err = goproto.Unmarshal(wire, transport) - require.NoError(t, err) + to := new(object.Attribute) + require.NoError(t, to.Unmarshal(wire)) - to := object.AttributeFromGRPCMessage(transport) require.Equal(t, from, to) }) }