diff --git a/pkg/object/address.go b/pkg/object/address.go index a1c2475..9f61c9f 100644 --- a/pkg/object/address.go +++ b/pkg/object/address.go @@ -6,7 +6,6 @@ import ( "github.com/nspcc-dev/neofs-api-go/internal" "github.com/nspcc-dev/neofs-api-go/pkg/container" "github.com/nspcc-dev/neofs-api-go/v2/refs" - "github.com/pkg/errors" ) // Address represents v2-compatible object address. @@ -38,16 +37,6 @@ func (a *Address) ToV2() *refs.Address { return (*refs.Address)(a) } -// AddressFromBytes restores Address from a binary representation. -func AddressFromBytes(data []byte) (*Address, error) { - addrV2 := new(refs.Address) - if err := addrV2.StableUnmarshal(data); err != nil { - return nil, errors.Wrap(err, "could not unmarshal object address") - } - - return NewAddressFromV2(addrV2), nil -} - // GetContainerID returns container identifier. func (a *Address) GetContainerID() *container.ID { return container.NewIDFromV2( @@ -102,3 +91,35 @@ func (a *Address) String() string { a.GetObjectID().String(), }, addressSeparator) } + +// Marshal marshals Address into a protobuf binary form. +// +// Buffer is allocated when the argument is empty. +// Otherwise, the first buffer is used. +func (a *Address) Marshal(b ...[]byte) ([]byte, error) { + var buf []byte + if len(b) > 0 { + buf = b[0] + } + + return (*refs.Address)(a). + StableMarshal(buf) +} + +// Unmarshal unmarshals protobuf binary representation of Address. +func (a *Address) Unmarshal(data []byte) error { + return (*refs.Address)(a). + Unmarshal(data) +} + +// MarshalJSON encodes Address to protobuf JSON format. +func (a *Address) MarshalJSON() ([]byte, error) { + return (*refs.Address)(a). + MarshalJSON() +} + +// UnmarshalJSON decodes Address from protobuf JSON format. +func (a *Address) UnmarshalJSON(data []byte) error { + return (*refs.Address)(a). + UnmarshalJSON(data) +} diff --git a/pkg/object/address_test.go b/pkg/object/address_test.go index 5b4ae1b..aa67e58 100644 --- a/pkg/object/address_test.go +++ b/pkg/object/address_test.go @@ -60,3 +60,29 @@ func TestAddress_Parse(t *testing.T) { require.EqualError(t, NewAddress().Parse(s), ErrBadID.Error()) }) } + +func TestAddressEncoding(t *testing.T) { + a := NewAddress() + a.SetObjectID(randID(t)) + a.SetContainerID(randCID(t)) + + t.Run("binary", func(t *testing.T) { + data, err := a.Marshal() + require.NoError(t, err) + + a2 := NewAddress() + 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 := NewAddress() + require.NoError(t, a2.UnmarshalJSON(data)) + + require.Equal(t, a, a2) + }) +} diff --git a/pkg/object/raw_test.go b/pkg/object/raw_test.go index 344bd28..1c40ea9 100644 --- a/pkg/object/raw_test.go +++ b/pkg/object/raw_test.go @@ -20,6 +20,13 @@ func randID(t *testing.T) *ID { return id } +func randCID(t *testing.T) *container.ID { + id := container.NewID() + id.SetSHA256(randSHA256Checksum(t)) + + return id +} + func randSHA256Checksum(t *testing.T) (cs [sha256.Size]byte) { _, err := rand.Read(cs[:]) require.NoError(t, err) diff --git a/v2/refs/json.go b/v2/refs/json.go new file mode 100644 index 0000000..f8c20d6 --- /dev/null +++ b/v2/refs/json.go @@ -0,0 +1,26 @@ +package refs + +import ( + refs "github.com/nspcc-dev/neofs-api-go/v2/refs/grpc" + "google.golang.org/protobuf/encoding/protojson" +) + +func (a *Address) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{ + EmitUnpopulated: true, + }.Marshal( + AddressToGRPCMessage(a), + ) +} + +func (a *Address) UnmarshalJSON(data []byte) error { + msg := new(refs.Address) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + *a = *AddressFromGRPCMessage(msg) + + return nil +} diff --git a/v2/refs/json_test.go b/v2/refs/json_test.go new file mode 100644 index 0000000..ce40de7 --- /dev/null +++ b/v2/refs/json_test.go @@ -0,0 +1,20 @@ +package refs_test + +import ( + "testing" + + "github.com/nspcc-dev/neofs-api-go/v2/refs" + "github.com/stretchr/testify/require" +) + +func TestAddressJSON(t *testing.T) { + a := generateAddress([]byte{1}, []byte{2}) + + data, err := a.MarshalJSON() + require.NoError(t, err) + + a2 := new(refs.Address) + require.NoError(t, a2.UnmarshalJSON(data)) + + require.Equal(t, a, a2) +} diff --git a/v2/refs/marshal.go b/v2/refs/marshal.go index 868b157..c39ce81 100644 --- a/v2/refs/marshal.go +++ b/v2/refs/marshal.go @@ -142,11 +142,7 @@ func (a *Address) StableSize() (size int) { return size } -func (a *Address) StableUnmarshal(data []byte) error { - if a == nil { - return nil - } - +func (a *Address) Unmarshal(data []byte) error { addrGRPC := new(refs.Address) if err := goproto.Unmarshal(data, addrGRPC); err != nil { return err diff --git a/v2/refs/marshal_test.go b/v2/refs/marshal_test.go index 4745147..3d8bfac 100644 --- a/v2/refs/marshal_test.go +++ b/v2/refs/marshal_test.go @@ -69,16 +69,13 @@ func TestAddress_StableMarshal(t *testing.T) { addressFrom := generateAddress(cid, oid) - addressTransport := new(grpc.Address) - t.Run("non empty", func(t *testing.T) { wire, err := addressFrom.StableMarshal(nil) require.NoError(t, err) - err = goproto.Unmarshal(wire, addressTransport) - require.NoError(t, err) + addressTo := new(refs.Address) + require.NoError(t, addressTo.Unmarshal(wire)) - addressTo := refs.AddressFromGRPCMessage(addressTransport) require.Equal(t, addressFrom, addressTo) }) } @@ -161,15 +158,3 @@ func generateAddress(bCid, bOid []byte) *refs.Address { return addr } - -func TestAddress_StableUnmarshal(t *testing.T) { - addr := generateAddress([]byte("container id"), []byte("object id")) - - data, err := addr.StableMarshal(nil) - require.NoError(t, err) - - addr2 := new(refs.Address) - require.NoError(t, addr2.StableUnmarshal(data)) - - require.Equal(t, addr, addr2) -}