Skip to content

Commit

Permalink
api: Support stable marshaling for NeoFS messages
Browse files Browse the repository at this point in the history
Specific encoding of NeoFS messages is required to implement protocol
checksums and signatures.

Continues 51fa18f.

Signed-off-by: Leonard Lyubich <[email protected]>
  • Loading branch information
cthulhu-rider committed Jul 9, 2024
1 parent 519d1f5 commit 2185947
Show file tree
Hide file tree
Showing 33 changed files with 3,689 additions and 0 deletions.
82 changes: 82 additions & 0 deletions api/accounting/encoding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package accounting

import (
"github.com/nspcc-dev/neofs-sdk-go/internal/proto"
)

const (
_ = iota
fieldDecimalValue
fieldDecimalPrecision
)

// MarshaledSize returns size of the Decimal in Protocol Buffers V3 format in
// bytes. MarshaledSize is NPE-safe.
func (x *Decimal) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeVarint(fieldDecimalValue, x.Value) +
proto.SizeVarint(fieldDecimalPrecision, x.Precision)
}
return sz
}

// MarshalStable writes the Decimal in Protocol Buffers V3 format with ascending
// order of fields by number into b. MarshalStable uses exactly
// [Decimal.MarshaledSize] first bytes of b. MarshalStable is NPE-safe.
func (x *Decimal) MarshalStable(b []byte) {
if x != nil {
off := proto.MarshalToVarint(b, fieldDecimalValue, x.Value)
proto.MarshalToVarint(b[off:], fieldDecimalPrecision, x.Precision)
}
}

const (
_ = iota
fieldBalanceReqOwner
)

// MarshaledSize returns size of the BalanceRequest_Body in Protocol Buffers V3
// format in bytes. MarshaledSize is NPE-safe.
func (x *BalanceRequest_Body) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeEmbedded(fieldBalanceReqOwner, x.OwnerId)
}
return sz
}

// MarshalStable writes the BalanceRequest_Body in Protocol Buffers V3 format
// with ascending order of fields by number into b. MarshalStable uses exactly
// [BalanceRequest_Body.MarshaledSize] first bytes of b. MarshalStable is
// NPE-safe.
func (x *BalanceRequest_Body) MarshalStable(b []byte) {
if x != nil {
proto.MarshalToEmbedded(b, fieldBalanceReqOwner, x.OwnerId)
}
}

const (
_ = iota
fieldBalanceRespBalance
)

// MarshaledSize returns size of the BalanceResponse_Body in Protocol Buffers V3
// format in bytes. MarshaledSize is NPE-safe.
func (x *BalanceResponse_Body) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeEmbedded(fieldBalanceRespBalance, x.Balance)
}
return sz
}

// MarshalStable writes the BalanceResponse_Body in Protocol Buffers V3 format
// with ascending order of fields by number into b. MarshalStable uses exactly
// [BalanceResponse_Body.MarshaledSize] first bytes of b. MarshalStable is
// NPE-safe.
func (x *BalanceResponse_Body) MarshalStable(b []byte) {
if x != nil {
proto.MarshalToEmbedded(b, fieldBalanceRespBalance, x.Balance)
}
}
54 changes: 54 additions & 0 deletions api/accounting/encoding_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package accounting_test

import (
"testing"

"github.com/nspcc-dev/neofs-sdk-go/api/accounting"
apitest "github.com/nspcc-dev/neofs-sdk-go/api/internal/test"
"github.com/nspcc-dev/neofs-sdk-go/api/refs"
"github.com/stretchr/testify/require"
)

func assertEqualDecimals(t testing.TB, v1, v2 *accounting.Decimal, msg string) {
require.Equal(t, v1.GetValue(), v2.GetValue(), msg)
require.Equal(t, v1.GetPrecision(), v2.GetPrecision(), msg)
}

func TestDecimal_MarshalStable(t *testing.T) {
apitest.TestMarshalStable(t, assertEqualDecimals, []*accounting.Decimal{
nil,
new(accounting.Decimal),
{
Value: apitest.RandomInteger[int64](),
Precision: apitest.RandomInteger[uint32](),
},
})
}

func assertEqualBalanceRequestBodies(t testing.TB, v1, v2 *accounting.BalanceRequest_Body, msg string) {
apitest.AssertEqualOwnerIDs(t, v1.OwnerId, v2.OwnerId, msg)
}

func TestBalanceRequest_Body_MarshalStable(t *testing.T) {
apitest.TestMarshalStable(t, assertEqualBalanceRequestBodies, []*accounting.BalanceRequest_Body{
nil,
new(accounting.BalanceRequest_Body),
{OwnerId: new(refs.OwnerID)},
})
}

func assertEqualBalanceResponseBodies(t testing.TB, v1, v2 *accounting.BalanceResponse_Body, msg string) {
assertEqualDecimals(t, v1.Balance, v2.Balance, msg)
}

func TestBalanceResponse_Body_MarshalStable(t *testing.T) {
apitest.TestMarshalStable(t, assertEqualBalanceResponseBodies, []*accounting.BalanceResponse_Body{
nil,
new(accounting.BalanceResponse_Body),
{Balance: new(accounting.Decimal)},
{Balance: &accounting.Decimal{
Value: apitest.RandomInteger[int64](),
Precision: apitest.RandomInteger[uint32](),
}},
})
}
233 changes: 233 additions & 0 deletions api/acl/encoding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
package acl

import (
"github.com/nspcc-dev/neofs-sdk-go/internal/proto"
)

const (
_ = iota
fieldEACLVersion
fieldEACLContainer
fieldEACLRecords
)

// MarshaledSize returns size of the EACLTable in Protocol Buffers V3 format in
// bytes. MarshaledSize is NPE-safe.
func (x *EACLTable) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeEmbedded(fieldEACLVersion, x.Version) +
proto.SizeEmbedded(fieldEACLContainer, x.ContainerId)
for i := range x.Records {
sz += proto.SizeEmbedded(fieldEACLRecords, x.Records[i])
}
}
return sz
}

// MarshalStable writes the EACLTable in Protocol Buffers V3 format with
// ascending order of fields by number into b. MarshalStable uses exactly
// [EACLTable.MarshaledSize] first bytes of b. MarshalStable is NPE-safe.
func (x *EACLTable) MarshalStable(b []byte) {
if x != nil {
off := proto.MarshalToEmbedded(b, fieldEACLVersion, x.Version)
off += proto.MarshalToEmbedded(b[off:], fieldEACLContainer, x.ContainerId)
for i := range x.Records {
off += proto.MarshalToEmbedded(b[off:], fieldEACLRecords, x.Records[i])
}
}
}

const (
_ = iota
fieldEACLOp
fieldEACLAction
fieldEACLFilters
fieldEACLTargets
)

// MarshaledSize returns size of the EACLRecord in Protocol Buffers V3 format in
// bytes. MarshaledSize is NPE-safe.
func (x *EACLRecord) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeVarint(fieldEACLOp, int32(x.Operation)) +
proto.SizeVarint(fieldEACLAction, int32(x.Action))
for i := range x.Filters {
sz += proto.SizeEmbedded(fieldEACLFilters, x.Filters[i])
}
for i := range x.Targets {
sz += proto.SizeEmbedded(fieldEACLTargets, x.Targets[i])
}
}
return sz
}

// MarshalStable writes the EACLRecord in Protocol Buffers V3 format with
// ascending order of fields by number into b. MarshalStable uses exactly
// [EACLRecord.MarshaledSize] first bytes of b. MarshalStable is NPE-safe.
func (x *EACLRecord) MarshalStable(b []byte) {
if x != nil {
off := proto.MarshalToVarint(b, fieldEACLOp, int32(x.Operation))
off += proto.MarshalToVarint(b[off:], fieldEACLAction, int32(x.Action))
for i := range x.Filters {
off += proto.MarshalToEmbedded(b[off:], fieldEACLFilters, x.Filters[i])
}
for i := range x.Targets {
off += proto.MarshalToEmbedded(b[off:], fieldEACLTargets, x.Targets[i])
}
}
}

const (
_ = iota
fieldEACLHeader
fieldEACLMatcher
fieldEACLKey
fieldEACLValue
)

// MarshaledSize returns size of the EACLRecord_Filter in Protocol Buffers V3
// format in bytes. MarshaledSize is NPE-safe.
func (x *EACLRecord_Filter) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeVarint(fieldEACLHeader, int32(x.HeaderType)) +
proto.SizeVarint(fieldEACLMatcher, int32(x.MatchType)) +
proto.SizeBytes(fieldEACLKey, x.Key) +
proto.SizeBytes(fieldEACLValue, x.Value)
}
return sz
}

// MarshalStable writes the EACLRecord_Filter in Protocol Buffers V3 format with
// ascending order of fields by number into b. MarshalStable uses exactly
// [EACLRecord_Filter.MarshaledSize] first bytes of b. MarshalStable is
// NPE-safe.
func (x *EACLRecord_Filter) MarshalStable(b []byte) {
if x != nil {
off := proto.MarshalToVarint(b, fieldEACLHeader, int32(x.HeaderType))
off += proto.MarshalToVarint(b[off:], fieldEACLMatcher, int32(x.MatchType))
off += proto.MarshalToBytes(b[off:], fieldEACLKey, x.Key)
proto.MarshalToBytes(b[off:], fieldEACLValue, x.Value)
}
}

const (
_ = iota
fieldEACLRole
fieldEACLTargetKeys
)

// MarshaledSize returns size of the EACLRecord_Target in Protocol Buffers V3
// format in bytes. MarshaledSize is NPE-safe.
func (x *EACLRecord_Target) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeVarint(fieldEACLRole, int32(x.Role)) +
proto.SizeRepeatedBytes(fieldEACLTargetKeys, x.Keys)
}
return sz
}

// MarshalStable writes the EACLRecord_Target in Protocol Buffers V3 format with
// ascending order of fields by number into b. MarshalStable uses exactly
// [EACLRecord_Target.MarshaledSize] first bytes of b. MarshalStable is
// NPE-safe.
func (x *EACLRecord_Target) MarshalStable(b []byte) {
if x != nil {
off := proto.MarshalToVarint(b, fieldEACLRole, int32(x.Role))
proto.MarshalToRepeatedBytes(b[off:], fieldEACLTargetKeys, x.Keys)
}
}

const (
_ = iota
fieldBearerExp
fieldBearerNbf
fieldBearerIat
)

// MarshaledSize returns size of the BearerToken_Body_TokenLifetime in Protocol
// Buffers V3 format in bytes. MarshaledSize is NPE-safe.
func (x *BearerToken_Body_TokenLifetime) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeVarint(fieldBearerExp, x.Exp) +
proto.SizeVarint(fieldBearerNbf, x.Nbf) +
proto.SizeVarint(fieldBearerIat, x.Iat)
}
return sz
}

// MarshalStable writes the BearerToken_Body_TokenLifetime in Protocol Buffers
// V3 format with ascending order of fields by number into b. MarshalStable uses
// exactly [BearerToken_Body_TokenLifetime.MarshaledSize] first bytes of b.
// MarshalStable is NPE-safe.
func (x *BearerToken_Body_TokenLifetime) MarshalStable(b []byte) {
if x != nil {
off := proto.MarshalToVarint(b, fieldBearerExp, x.Exp)
off += proto.MarshalToVarint(b[off:], fieldBearerNbf, x.Nbf)
proto.MarshalToVarint(b[off:], fieldBearerIat, x.Iat)
}
}

const (
_ = iota
fieldBearerEACL
fieldBearerOwner
fieldBearerLifetime
fieldBearerIssuer
)

// MarshaledSize returns size of the BearerToken_Body in Protocol Buffers V3
// format in bytes. MarshaledSize is NPE-safe.
func (x *BearerToken_Body) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeEmbedded(fieldBearerEACL, x.EaclTable) +
proto.SizeEmbedded(fieldBearerOwner, x.OwnerId) +
proto.SizeEmbedded(fieldBearerLifetime, x.Lifetime) +
proto.SizeEmbedded(fieldBearerIssuer, x.Issuer)
}
return sz
}

// MarshalStable writes the BearerToken_Body in Protocol Buffers V3 format with
// ascending order of fields by number into b. MarshalStable uses exactly
// [BearerToken_Body.MarshaledSize] first bytes of b. MarshalStable is NPE-safe.
func (x *BearerToken_Body) MarshalStable(b []byte) {
if x != nil {
off := proto.MarshalToEmbedded(b, fieldBearerEACL, x.EaclTable)
off += proto.MarshalToEmbedded(b[off:], fieldBearerOwner, x.OwnerId)
off += proto.MarshalToEmbedded(b[off:], fieldBearerLifetime, x.Lifetime)
proto.MarshalToEmbedded(b[off:], fieldBearerIssuer, x.Issuer)
}
}

const (
_ = iota
fieldBearerBody
fieldBearerSignature
)

// MarshaledSize returns size of the BearerToken in Protocol Buffers V3 format
// in bytes. MarshaledSize is NPE-safe.
func (x *BearerToken) MarshaledSize() int {
var sz int
if x != nil {
sz = proto.SizeEmbedded(fieldBearerBody, x.Body) +
proto.SizeEmbedded(fieldBearerSignature, x.Signature)
}
return sz
}

// MarshalStable writes the BearerToken in Protocol Buffers V3 format with
// ascending order of fields by number into b. MarshalStable uses exactly
// [BearerToken.MarshaledSize] first bytes of b. MarshalStable is NPE-safe.
func (x *BearerToken) MarshalStable(b []byte) {
if x != nil {
off := proto.MarshalToEmbedded(b, fieldBearerBody, x.Body)
proto.MarshalToEmbedded(b[off:], fieldBearerSignature, x.Signature)
}
}
3 changes: 3 additions & 0 deletions api/acl/encoding_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package acl_test

// TODO
Loading

0 comments on commit 2185947

Please sign in to comment.