diff --git a/pkg/container/container.go b/pkg/container/container.go index 3d64633..44efd9e 100644 --- a/pkg/container/container.go +++ b/pkg/container/container.go @@ -111,3 +111,35 @@ func (c *Container) PlacementPolicy() *netmap.PlacementPolicy { func (c *Container) SetPlacementPolicy(v *netmap.PlacementPolicy) { c.v2.SetPlacementPolicy(v.ToV2()) } + +// Marshal marshals Container into a protobuf binary form. +// +// Buffer is allocated when the argument is empty. +// Otherwise, the first buffer is used. +func (c *Container) Marshal(b ...[]byte) ([]byte, error) { + var buf []byte + if len(b) > 0 { + buf = b[0] + } + + return c.v2. + StableMarshal(buf) +} + +// Unmarshal unmarshals protobuf binary representation of Container. +func (c *Container) Unmarshal(data []byte) error { + return c.v2. + Unmarshal(data) +} + +// MarshalJSON encodes Container to protobuf JSON format. +func (c *Container) MarshalJSON() ([]byte, error) { + return c.v2. + MarshalJSON() +} + +// UnmarshalJSON decodes Container from protobuf JSON format. +func (c *Container) UnmarshalJSON(data []byte) error { + return c.v2. + UnmarshalJSON(data) +} diff --git a/pkg/container/container_test.go b/pkg/container/container_test.go index ec5e273..391b983 100644 --- a/pkg/container/container_test.go +++ b/pkg/container/container_test.go @@ -66,3 +66,29 @@ func generatePlacementPolicy() *netmap.PlacementPolicy { return p } + +func TestContainerEncoding(t *testing.T) { + c := container.New( + container.WithAttribute("key", "value"), + ) + + t.Run("binary", func(t *testing.T) { + data, err := c.Marshal() + require.NoError(t, err) + + c2 := container.New() + require.NoError(t, c2.Unmarshal(data)) + + require.Equal(t, c, c2) + }) + + t.Run("json", func(t *testing.T) { + data, err := c.MarshalJSON() + require.NoError(t, err) + + c2 := container.New() + require.NoError(t, c2.UnmarshalJSON(data)) + + require.Equal(t, c, c2) + }) +} diff --git a/v2/container/json.go b/v2/container/json.go index 0cf7c63..7ce52da 100644 --- a/v2/container/json.go +++ b/v2/container/json.go @@ -1,40 +1,10 @@ package container import ( - "errors" - container "github.com/nspcc-dev/neofs-api-go/v2/container/grpc" "google.golang.org/protobuf/encoding/protojson" ) -var ( - errEmptyInput = errors.New("empty input") -) - -func ContainerToJSON(c *Container) ([]byte, error) { - if c == nil { - return nil, errEmptyInput - } - - msg := ContainerToGRPCMessage(c) - - return protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(msg) -} - -func ContainerFromJSON(data []byte) (*Container, error) { - if len(data) == 0 { - return nil, errEmptyInput - } - - msg := new(container.Container) - - if err := protojson.Unmarshal(data, msg); err != nil { - return nil, err - } - - return ContainerFromGRPCMessage(msg), nil -} - func (a *Attribute) MarshalJSON() ([]byte, error) { return protojson.MarshalOptions{ EmitUnpopulated: true, @@ -54,3 +24,23 @@ func (a *Attribute) UnmarshalJSON(data []byte) error { return nil } + +func (c *Container) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{ + EmitUnpopulated: true, + }.Marshal( + ContainerToGRPCMessage(c), + ) +} + +func (c *Container) UnmarshalJSON(data []byte) error { + msg := new(container.Container) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + *c = *ContainerFromGRPCMessage(msg) + + return nil +} diff --git a/v2/container/json_test.go b/v2/container/json_test.go index d25b09d..40228a2 100644 --- a/v2/container/json_test.go +++ b/v2/container/json_test.go @@ -8,25 +8,15 @@ import ( ) func TestContainerJSON(t *testing.T) { - exp := generateContainer("container") + c := generateContainer("nonce") - t.Run("non empty", func(t *testing.T) { - data, err := container.ContainerToJSON(exp) - require.NoError(t, err) + data, err := c.MarshalJSON() + require.NoError(t, err) - got, err := container.ContainerFromJSON(data) - require.NoError(t, err) + c2 := new(container.Container) + require.NoError(t, c2.UnmarshalJSON(data)) - require.Equal(t, exp, got) - }) - - t.Run("empty", func(t *testing.T) { - _, err := container.ContainerToJSON(nil) - require.Error(t, err) - - _, err = container.ContainerFromJSON(nil) - require.Error(t, err) - }) + require.Equal(t, c, c2) } func TestAttributeJSON(t *testing.T) { diff --git a/v2/container/marshal.go b/v2/container/marshal.go index c89597d..8486b02 100644 --- a/v2/container/marshal.go +++ b/v2/container/marshal.go @@ -171,6 +171,17 @@ func (c *Container) StableSize() (size int) { return size } +func (c *Container) Unmarshal(data []byte) error { + m := new(container.Container) + if err := proto.Unmarshal(data, m); err != nil { + return err + } + + *c = *ContainerFromGRPCMessage(m) + + return nil +} + func (r *PutRequestBody) StableMarshal(buf []byte) ([]byte, error) { if r == nil { return []byte{}, nil diff --git a/v2/container/marshal_test.go b/v2/container/marshal_test.go index a46d11f..d2c25e5 100644 --- a/v2/container/marshal_test.go +++ b/v2/container/marshal_test.go @@ -28,16 +28,14 @@ func TestAttribute_StableMarshal(t *testing.T) { func TestContainer_StableMarshal(t *testing.T) { cnrFrom := generateContainer("nonce") - transport := new(grpc.Container) t.Run("non empty", func(t *testing.T) { wire, err := cnrFrom.StableMarshal(nil) require.NoError(t, err) - err = goproto.Unmarshal(wire, transport) - require.NoError(t, err) + cnrTo := new(container.Container) + require.NoError(t, cnrTo.Unmarshal(wire)) - cnrTo := container.ContainerFromGRPCMessage(transport) require.Equal(t, cnrFrom, cnrTo) }) }