Skip to content

Commit

Permalink
[nspcc-dev#79] Implement type for subnet ID
Browse files Browse the repository at this point in the history
Create `subnet` package. Define `ID` type of subnet identifiers.
Implement encoding and support NeoFS API V2 protocol. Provide method to
init instance from integer. Implement function which checks if `ID`
instance refers to zero subnet.
  • Loading branch information
Leonard Lyubich committed Nov 23, 2021
1 parent d9317cb commit 69644c3
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 2 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ require (
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
google.golang.org/grpc v1.41.0
)

replace github.com/nspcc-dev/neofs-api-go/v2 => github.com/cthulhu-rider/neofs-api-go/v2 v2.0.0-20211123141115-f6e3cf42766d
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cthulhu-rider/neofs-api-go/v2 v2.0.0-20211123141115-f6e3cf42766d h1:NW2UhTfYL6dHvsTWNDx9Ln+Qw6luA8o2RJLMvs0jxIY=
github.com/cthulhu-rider/neofs-api-go/v2 v2.0.0-20211123141115-f6e3cf42766d/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -62,8 +64,6 @@ github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU=
github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211118144033-580f6c5554ff h1:j3NbdVKYPMh9/cQLD/LhY7gGKyVA6qtOIsJ/cKiXWUQ=
github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211118144033-580f6c5554ff/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs=
github.com/nspcc-dev/neofs-crypto v0.3.0 h1:zlr3pgoxuzrmGCxc5W8dGVfA9Rro8diFvVnBg0L4ifM=
github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw=
github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE=
Expand Down
89 changes: 89 additions & 0 deletions subnet/id/id.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package subnetid

import (
"fmt"

"github.com/nspcc-dev/neofs-api-go/v2/refs"
)

// ID represents NeoFS subnet identifier.
//
// The type is compatible with the corresponding message from NeoFS API V2 protocol.
//
// Zero value and nil pointer is equivalent to zero subnet ID.
type ID refs.SubnetID

// FromV2 initializes ID from refs.SubnetID message structure. Must not be called on nil.
//
// Note: nil refs.SubnetID corresponds to zero ID value or nil pointer to it.
func (x *ID) FromV2(msg refs.SubnetID) {
*x = ID(msg)
}

// WriteToV2 writes ID to refs.SubnetID message structure. The message must not be nil.
//
// Note: nil ID corresponds to zero refs.SubnetID value or nil pointer to it.
func (x ID) WriteToV2(msg *refs.SubnetID) {
*msg = refs.SubnetID(x)
}

// Equals returns true iff both instances identify the same subnet.
//
// Method is NPE-safe: nil pointer equals to pointer to zero value.
func (x *ID) Equals(x2 *ID) bool {
return (*refs.SubnetID)(x).GetValue() == (*refs.SubnetID)(x2).GetValue()
}

// MarshalText encodes ID into text format according to particular NeoFS API protocol.
// Supported versions:
// * V2 (see refs.SubnetID type).
//
// Implements encoding.TextMarshaler.
func (x *ID) MarshalText() ([]byte, error) {
return (*refs.SubnetID)(x).MarshalText()
}

// UnmarshalText decodes ID from the text according to particular NeoFS API protocol.
// Must not be called on nil. Supported versions:
// * V2 (see refs.SubnetID type).
//
// Implements encoding.TextUnmarshaler.
func (x *ID) UnmarshalText(text []byte) error {
return (*refs.SubnetID)(x).UnmarshalText(text)
}

// String returns string representation of ID using MarshalText.
// Returns string with message on error.
//
// Implements fmt.Stringer.
func (x *ID) String() string {
text, err := x.MarshalText()
if err != nil {
return fmt.Sprintf("<invalid> %v", err)
}

return string(text)
}

// Marshal encodes ID into a binary format of NeoFS API V2 protocol (Protocol Buffers with direct field order).
func (x *ID) Marshal() ([]byte, error) {
return (*refs.SubnetID)(x).StableMarshal(nil)
}

// Unmarshal decodes ID from NeoFS API V2 binary format (see Marshal). Must not be called on nil.
//
// Note: empty data corresponds to zero ID value or nil pointer to it.
func (x *ID) Unmarshal(data []byte) error {
return (*refs.SubnetID)(x).Unmarshal(data)
}

// SetNumber sets ID value in uint32 format. Must not be called on nil.
// By default, number is 0 which refers to zero subnet.
func (x *ID) SetNumber(num uint32) {
(*refs.SubnetID)(x).SetValue(num)
}

// IsZero returns true iff the ID refers to zero subnet.
func IsZero(id ID) bool {
return id.Equals(nil)
}
94 changes: 94 additions & 0 deletions subnet/id/id_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package subnetid_test

import (
"testing"

"github.com/nspcc-dev/neofs-api-go/v2/refs"
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
subnetidtest "github.com/nspcc-dev/neofs-sdk-go/subnet/id/test"
"github.com/stretchr/testify/require"
)

func TestIsZero(t *testing.T) {
var id subnetid.ID

require.True(t, subnetid.IsZero(id))

id.SetNumber(13)
require.False(t, subnetid.IsZero(id))

id.SetNumber(0)
require.True(t, subnetid.IsZero(id))
}

func TestID_FromV2(t *testing.T) {
const num = 13

var id1 subnetid.ID
id1.SetNumber(num)

var idv2 refs.SubnetID
idv2.SetValue(num)

var id2 subnetid.ID
id2.FromV2(idv2)

require.True(t, id1.Equals(&id2))
}

func TestID_WriteToV2(t *testing.T) {
const num = 13

var (
id subnetid.ID
idv2 refs.SubnetID
)

id.WriteToV2(&idv2)
require.Zero(t, idv2.GetValue())

id.SetNumber(num)

id.WriteToV2(&idv2)
require.EqualValues(t, num, idv2.GetValue())
}

func TestID_Equals(t *testing.T) {
const num = 13

var id1, id2, id_, id0 subnetid.ID

id0.Equals(nil)

id1.SetNumber(num)
id2.SetNumber(num)
id_.SetNumber(num + 1)

require.True(t, id1.Equals(&id2))
require.False(t, id1.Equals(&id_))
require.False(t, id2.Equals(&id_))
}

func TestSubnetIDEncoding(t *testing.T) {
id := subnetidtest.GenerateID()

t.Run("binary", func(t *testing.T) {
data, err := id.Marshal()
require.NoError(t, err)

var id2 subnetid.ID
require.NoError(t, id2.Unmarshal(data))

require.True(t, id2.Equals(id))
})

t.Run("text", func(t *testing.T) {
data, err := id.MarshalText()
require.NoError(t, err)

var id2 subnetid.ID
require.NoError(t, id2.UnmarshalText(data))

require.True(t, id2.Equals(id))
})
}
16 changes: 16 additions & 0 deletions subnet/id/test/id.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package subnetidtest

import (
"math/rand"

subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
)

// GenerateID generates and returns random subnetid.ID using math/rand.Uint32.
func GenerateID() *subnetid.ID {
var id subnetid.ID

id.SetNumber(rand.Uint32())

return &id
}

0 comments on commit 69644c3

Please sign in to comment.