forked from TrueCloudLab/frostfs-sdk-go
[#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 202 additions and 3 deletions
2
go.mod
2
go.mod
|
@ -9,7 +9,7 @@ require (
|
||||||
github.com/hashicorp/golang-lru v0.5.4
|
github.com/hashicorp/golang-lru v0.5.4
|
||||||
github.com/mr-tron/base58 v1.2.0
|
github.com/mr-tron/base58 v1.2.0
|
||||||
github.com/nspcc-dev/hrw v1.0.9
|
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/neofs-crypto v0.3.0
|
||||||
github.com/nspcc-dev/rfc6979 v0.2.0
|
github.com/nspcc-dev/rfc6979 v0.2.0
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -62,8 +62,8 @@ 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/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 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
|
||||||
github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU=
|
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.20211124141318-d93828f46514 h1:ccZ+d8nJa8H2IWCLlr6YSanqwtTP6YiWa8RmCtT8aOs=
|
||||||
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-api-go/v2 v2.11.0-pre.0.20211124141318-d93828f46514/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 h1:zlr3pgoxuzrmGCxc5W8dGVfA9Rro8diFvVnBg0L4ifM=
|
||||||
github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw=
|
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=
|
github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE=
|
||||||
|
|
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