From 81754620503705f0e307ea5e25f1a593ebf3e91d Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 23 Nov 2021 21:20:12 +0300 Subject: [PATCH] [#79] Implement type for subnet information Create `subnet` package. Define `Info` type of the subnet info. Support encoding and transport over the NeoFS API V2 protocol. Add methods to work with identifier and owner. Signed-off-by: Leonard Lyubich --- subnet/subnet.go | 92 +++++++++++++++++++++++++++++++++++++++++++ subnet/subnet_test.go | 79 +++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 subnet/subnet.go create mode 100644 subnet/subnet_test.go diff --git a/subnet/subnet.go b/subnet/subnet.go new file mode 100644 index 0000000..996f449 --- /dev/null +++ b/subnet/subnet.go @@ -0,0 +1,92 @@ +package subnet + +import ( + "github.com/nspcc-dev/neofs-api-go/v2/refs" + "github.com/nspcc-dev/neofs-api-go/v2/subnet" + "github.com/nspcc-dev/neofs-sdk-go/owner" + subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id" +) + +// Info represents information about NeoFS subnet. +// +// The type is compatible with the corresponding message from NeoFS API V2 protocol. +// +// Zero value and nil pointer to it represents zero subnet w/o an owner. +type Info subnet.Info + +// FromV2 initializes Info from subnet.Info message structure. Must not be called on nil. +func (x *Info) FromV2(msg subnet.Info) { + *x = Info(msg) +} + +// WriteToV2 writes Info to subnet.Info message structure. The message must not be nil. +func (x Info) WriteToV2(msg *subnet.Info) { + *msg = subnet.Info(x) +} + +// Marshal encodes Info into a binary format of NeoFS API V2 protocol (Protocol Buffers with direct field order). +func (x *Info) Marshal() ([]byte, error) { + return (*subnet.Info)(x).StableMarshal(nil) +} + +// Unmarshal decodes Info from NeoFS API V2 binary format (see Marshal). Must not be called on nil. +// +// Note: empty data corresponds to zero Info value or nil pointer to it. +func (x *Info) Unmarshal(data []byte) error { + return (*subnet.Info)(x).Unmarshal(data) +} + +// SetID sets the identifier of the subnet that Info describes. +func (x *Info) SetID(id subnetid.ID) { + infov2 := (*subnet.Info)(x) + + idv2 := infov2.ID() + if idv2 == nil { + idv2 = new(refs.SubnetID) + infov2.SetID(idv2) + } + + id.WriteToV2(idv2) +} + +// ReadID reads the identifier of the subnet that Info describes. Arg must not be nil. +func (x Info) ReadID(id *subnetid.ID) { + infov2 := (subnet.Info)(x) + + idv2 := infov2.ID() + if idv2 == nil { + subnetid.MakeZero(id) + return + } + + id.FromV2(*idv2) +} + +// SetOwner sets subnet owner ID. +func (x *Info) SetOwner(id owner.ID) { + infov2 := (*subnet.Info)(x) + + idv2 := infov2.Owner() + if idv2 == nil { + idv2 = new(refs.OwnerID) + infov2.SetOwner(idv2) + } + + // FIXME: we need to implement and use owner.ID.WriteToV2() method + *idv2 = *id.ToV2() +} + +// HasOwner checks if subnet owner is set. +func (x Info) HasOwner() bool { + return (*subnet.Info)(&x).Owner() != nil +} + +// ReadOwner reads the identifier of the subnet that Info describes. +// Must be called only if owner is set (see HasOwner). Arg must not be nil. +func (x Info) ReadOwner(id *owner.ID) { + infov2 := (subnet.Info)(x) + + // FIXME: we need to implement and use owner.ID.FromV2 method + id2 := owner.NewIDFromV2(infov2.Owner()) + *id = *id2 +} diff --git a/subnet/subnet_test.go b/subnet/subnet_test.go new file mode 100644 index 0000000..763cb71 --- /dev/null +++ b/subnet/subnet_test.go @@ -0,0 +1,79 @@ +package subnet_test + +import ( + "testing" + + subnetv2 "github.com/nspcc-dev/neofs-api-go/v2/subnet" + subnettest "github.com/nspcc-dev/neofs-api-go/v2/subnet/test" + "github.com/nspcc-dev/neofs-sdk-go/owner" + ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test" + "github.com/nspcc-dev/neofs-sdk-go/subnet" + subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id" + "github.com/stretchr/testify/require" +) + +func TestInfoZero(t *testing.T) { + var info subnet.Info + + var id subnetid.ID + info.ReadID(&id) + + require.True(t, subnetid.IsZero(id)) + + require.False(t, info.HasOwner()) +} + +func TestInfo_SetID(t *testing.T) { + var ( + idFrom, idTo subnetid.ID + + info subnet.Info + ) + + idFrom.SetNumber(222) + + info.SetID(idFrom) + + info.ReadID(&idTo) + + require.True(t, idTo.Equals(&idFrom)) +} + +func TestInfo_SetOwner(t *testing.T) { + var ( + idFrom, idTo owner.ID + + info subnet.Info + ) + + idFrom = *ownertest.GenerateID() + + require.False(t, info.HasOwner()) + + info.SetOwner(idFrom) + + require.True(t, info.HasOwner()) + + info.ReadOwner(&idTo) + + require.True(t, idTo.Equal(&idFrom)) +} + +func TestInfo_WriteToV2(t *testing.T) { + var ( + infoTo, infoFrom subnet.Info + + infoV2From, infoV2To subnetv2.Info + ) + + infoV2From = *subnettest.GenerateSubnetInfo(false) + + infoFrom.FromV2(infoV2From) + + infoFrom.WriteToV2(&infoV2To) + + infoTo.FromV2(infoV2To) + + require.Equal(t, infoV2From, infoV2To) + require.Equal(t, infoFrom, infoTo) +}