[#79] Implement type for subnet ID
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. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
d9317cbea1
commit
b8989e3abb
5 changed files with 200 additions and 1 deletions
2
go.mod
2
go.mod
|
@ -9,7 +9,7 @@ require (
|
|||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/mr-tron/base58 v1.2.0
|
||||
github.com/nspcc-dev/hrw v1.0.9
|
||||
github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211118144033-580f6c5554ff
|
||||
github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211124141318-d93828f46514
|
||||
github.com/nspcc-dev/neofs-crypto v0.3.0
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
|
|
BIN
go.sum
BIN
go.sum
Binary file not shown.
89
subnet/id/id.go
Normal file
89
subnet/id/id.go
Normal file
|
@ -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
subnet/id/id_test.go
Normal file
94
subnet/id/id_test.go
Normal file
|
@ -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, idOther, id0 subnetid.ID
|
||||
|
||||
id0.Equals(nil)
|
||||
|
||||
id1.SetNumber(num)
|
||||
id2.SetNumber(num)
|
||||
idOther.SetNumber(num + 1)
|
||||
|
||||
require.True(t, id1.Equals(&id2))
|
||||
require.False(t, id1.Equals(&idOther))
|
||||
require.False(t, id2.Equals(&idOther))
|
||||
}
|
||||
|
||||
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
subnet/id/test/id.go
Normal file
16
subnet/id/test/id.go
Normal file
|
@ -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
|
||||
}
|
Loading…
Reference in a new issue