[#170] oid, cid: Add marshal format checks

Also add checking presence of the `oid`, `cid` fields via `set` flag.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2022-04-12 19:23:16 +03:00 committed by LeL
parent f7172adf18
commit 1186f2f703
17 changed files with 432 additions and 118 deletions

View file

@ -1,6 +1,9 @@
package audit
import (
"errors"
"fmt"
"github.com/nspcc-dev/neofs-api-go/v2/audit"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
@ -43,17 +46,54 @@ func (r *Result) Marshal() []byte {
return data
}
var errCIDNotSet = errors.New("container ID is not set")
// Unmarshal decodes Result from its canonical NeoFS binary format (Protocol Buffers
// with direct field order). Returns an error describing a format violation.
//
// See also Marshal.
func (r *Result) Unmarshal(data []byte) error {
err := r.v2.Unmarshal(data)
if err == nil {
r.versionEncoded = true
if err != nil {
return err
}
return err
r.versionEncoded = true
// format checks
var cID cid.ID
cidV2 := r.v2.GetContainerID()
if cidV2 == nil {
return errCIDNotSet
}
err = cID.ReadFromV2(*cidV2)
if err != nil {
return fmt.Errorf("could not convert V2 container ID: %w", err)
}
var (
oID oid.ID
oidV2 refs.ObjectID
)
for _, oidV2 = range r.v2.GetPassSG() {
err = oID.ReadFromV2(oidV2)
if err != nil {
return fmt.Errorf("invalid passed storage group ID: %w", err)
}
}
for _, oidV2 = range r.v2.GetFailSG() {
err = oID.ReadFromV2(oidV2)
if err != nil {
return fmt.Errorf("invalid failed storage group ID: %w", err)
}
}
return nil
}
// Epoch returns NeoFS epoch when the data associated with the Result was audited.
@ -73,20 +113,21 @@ func (r *Result) ForEpoch(epoch uint64) {
}
// Container returns identifier of the container with which the data audit Result
// is associated.
// is associated and a bool that indicates container ID field presence in the Result.
//
// Returns zero ID if container is not specified. Zero Result has zero container.
// Zero Result does not have container ID.
//
// See also ForContainer.
func (r Result) Container() cid.ID {
func (r Result) Container() (cid.ID, bool) {
var cID cid.ID
cidV2 := r.v2.GetContainerID()
if cidV2 != nil {
_ = cID.ReadFromV2(*cidV2)
return cID, true
}
return cID
return cID, false
}
// ForContainer sets identifier of the container with which the data audit Result

View file

@ -66,7 +66,8 @@ func TestResultData(t *testing.T) {
countFailNodes := func(f func([]byte)) int { return countNodes(false, f) }
require.Zero(t, r.Epoch())
require.True(t, r.Container().Empty())
_, set := r.Container()
require.False(t, set)
require.Nil(t, r.AuditorKey())
require.False(t, r.Completed())
require.Zero(t, r.RequestsPoR())
@ -82,7 +83,9 @@ func TestResultData(t *testing.T) {
cnr := cidtest.ID()
r.ForContainer(cnr)
require.Equal(t, cnr, r.Container())
cID, set := r.Container()
require.True(t, set)
require.Equal(t, cnr, cID)
key := []byte{1, 2, 3}
r.SetAuditorKey(key)

View file

@ -1,6 +1,9 @@
package container
import (
"errors"
"fmt"
"github.com/nspcc-dev/neofs-api-go/v2/container"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
@ -39,7 +42,7 @@ func (a *UsedSpaceAnnouncement) SetEpoch(epoch uint64) {
}
// ContainerID of the announcement.
func (a *UsedSpaceAnnouncement) ContainerID() (cID cid.ID) {
func (a *UsedSpaceAnnouncement) ContainerID() (cID cid.ID, isSet bool) {
v2 := (*container.UsedSpaceAnnouncement)(a)
cidV2 := v2.GetContainerID()
@ -48,6 +51,7 @@ func (a *UsedSpaceAnnouncement) ContainerID() (cID cid.ID) {
}
_ = cID.ReadFromV2(*cidV2)
isSet = true
return
}
@ -82,7 +86,28 @@ func (a *UsedSpaceAnnouncement) Marshal() ([]byte, error) {
return a.ToV2().StableMarshal(nil)
}
var errCIDNotSet = errors.New("container ID is not set")
// Unmarshal unmarshals protobuf binary representation of UsedSpaceAnnouncement.
func (a *UsedSpaceAnnouncement) Unmarshal(data []byte) error {
return a.ToV2().Unmarshal(data)
err := a.ToV2().Unmarshal(data)
if err != nil {
return err
}
// format checks
var cID cid.ID
cidV2 := a.ToV2().GetContainerID()
if cidV2 == nil {
return errCIDNotSet
}
err = cID.ReadFromV2(*cidV2)
if err != nil {
return fmt.Errorf("could not convert V2 container ID: %w", err)
}
return nil
}

View file

@ -26,7 +26,9 @@ func TestAnnouncement(t *testing.T) {
require.Equal(t, epoch, a.Epoch())
require.Equal(t, usedSpace, a.UsedSpace())
require.Equal(t, id, a.ContainerID())
cID, set := a.ContainerID()
require.True(t, set)
require.Equal(t, id, cID)
t.Run("test v2", func(t *testing.T) {
const newEpoch, newUsedSpace uint64 = 20, 200
@ -51,7 +53,9 @@ func TestAnnouncement(t *testing.T) {
require.Equal(t, newEpoch, newA.Epoch())
require.Equal(t, newUsedSpace, newA.UsedSpace())
require.Equal(t, cID, newA.ContainerID())
cIDNew, set := newA.ContainerID()
require.True(t, set)
require.Equal(t, cID, cIDNew)
})
}
@ -82,7 +86,8 @@ func TestUsedSpaceAnnouncement_ToV2(t *testing.T) {
// check initial values
require.Zero(t, announcement.Epoch())
require.Zero(t, announcement.UsedSpace())
require.True(t, announcement.ContainerID().Empty())
_, set := announcement.ContainerID()
require.False(t, set)
// convert to v2 message
announcementV2 := announcement.ToV2()

View file

@ -112,9 +112,3 @@ func (id *ID) DecodeString(s string) error {
func (id ID) String() string {
return id.EncodeToString()
}
// Empty returns true if it is called on
// zero container ID.
func (id ID) Empty() bool {
return id == ID{}
}

View file

@ -2,6 +2,8 @@ package eacl
import (
"crypto/sha256"
"errors"
"fmt"
v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
@ -16,20 +18,25 @@ import (
// Table is compatible with v2 acl.EACLTable message.
type Table struct {
version version.Version
cid cid.ID
cid *cid.ID
token *session.Token
sig *signature.Signature
records []Record
}
// CID returns identifier of the container that should use given access control rules.
func (t Table) CID() cid.ID {
return t.cid
func (t Table) CID() (cID cid.ID, isSet bool) {
if t.cid != nil {
cID = *t.cid
isSet = true
}
return
}
// SetCID sets identifier of the container that should use given access control rules.
func (t *Table) SetCID(cid cid.ID) {
t.cid = cid
t.cid = &cid
}
// Version returns version of eACL format.
@ -87,7 +94,7 @@ func (t *Table) ToV2() *v2acl.Table {
v2 := new(v2acl.Table)
var cidV2 refs.ContainerID
if !t.cid.Empty() {
if t.cid != nil {
t.cid.WriteToV2(&cidV2)
v2.SetContainerID(&cidV2)
}
@ -150,8 +157,8 @@ func NewTableFromV2(table *v2acl.Table) *Table {
// set container id
if id := table.GetContainerID(); id != nil {
if t.cid.Empty() {
t.cid = cid.ID{}
if t.cid == nil {
t.cid = new(cid.ID)
}
var h [sha256.Size]byte
@ -176,6 +183,8 @@ func (t *Table) Marshal() ([]byte, error) {
return t.ToV2().StableMarshal(nil)
}
var errCIDNotSet = errors.New("container ID is not set")
// Unmarshal unmarshals protobuf binary representation of Table.
func (t *Table) Unmarshal(data []byte) error {
fV2 := new(v2acl.Table)
@ -183,6 +192,12 @@ func (t *Table) Unmarshal(data []byte) error {
return err
}
// format checks
err := checkFormat(fV2)
if err != nil {
return err
}
*t = *NewTableFromV2(fV2)
return nil
@ -200,6 +215,11 @@ func (t *Table) UnmarshalJSON(data []byte) error {
return err
}
err := checkFormat(tV2)
if err != nil {
return err
}
*t = *NewTableFromV2(tV2)
return nil
@ -207,7 +227,10 @@ func (t *Table) UnmarshalJSON(data []byte) error {
// EqualTables compares Table with each other.
func EqualTables(t1, t2 Table) bool {
if !t1.CID().Equals(t2.CID()) ||
cID1, set1 := t1.CID()
cID2, set2 := t2.CID()
if set1 != set2 || cID1 != cID2 ||
!t1.Version().Equal(t2.Version()) {
return false
}
@ -226,3 +249,19 @@ func EqualTables(t1, t2 Table) bool {
return true
}
func checkFormat(v2 *v2acl.Table) error {
var cID cid.ID
cidV2 := v2.GetContainerID()
if cidV2 == nil {
return errCIDNotSet
}
err := cID.ReadFromV2(*cidV2)
if err != nil {
return fmt.Errorf("could not convert V2 container ID: %w", err)
}
return nil
}

View file

@ -46,7 +46,9 @@ func TestTable(t *testing.T) {
id := cidtest.ID()
table := eacl.CreateTable(id)
require.Equal(t, id, table.CID())
cID, set := table.CID()
require.True(t, set)
require.Equal(t, id, cID)
require.Equal(t, version.Current(), table.Version())
})
}
@ -124,7 +126,8 @@ func TestTable_ToV2(t *testing.T) {
// check initial values
require.Equal(t, version.Current(), table.Version())
require.Nil(t, table.Records())
require.True(t, table.CID().Empty())
_, set := table.CID()
require.False(t, set)
require.Nil(t, table.SessionToken())
require.Nil(t, table.Signature())

View file

@ -2,6 +2,7 @@ package address
import (
"errors"
"fmt"
"strings"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
@ -45,16 +46,16 @@ func (a *Address) ToV2() *refs.Address {
}
// ContainerID returns container identifier.
func (a *Address) ContainerID() (v cid.ID) {
var cID cid.ID
func (a *Address) ContainerID() (v cid.ID, isSet bool) {
v2 := (*refs.Address)(a)
cidV2 := v2.GetContainerID()
if cidV2 != nil {
_ = cID.ReadFromV2(*cidV2)
_ = v.ReadFromV2(*cidV2)
isSet = true
}
return cID
return
}
// SetContainerID sets container identifier.
@ -66,16 +67,16 @@ func (a *Address) SetContainerID(id cid.ID) {
}
// ObjectID returns object identifier.
func (a *Address) ObjectID() (v oid.ID) {
var id oid.ID
func (a *Address) ObjectID() (v oid.ID, isSet bool) {
v2 := (*refs.Address)(a)
oidV2 := v2.GetObjectID()
if oidV2 != nil {
_ = id.ReadFromV2(*oidV2)
_ = v.ReadFromV2(*oidV2)
isSet = true
}
return id
return
}
// SetObjectID sets object identifier.
@ -111,10 +112,17 @@ func (a *Address) Parse(s string) error {
// String returns string representation of Object.Address.
func (a *Address) String() string {
return strings.Join([]string{
a.ContainerID().String(),
a.ObjectID().String(),
}, addressSeparator)
var cidStr, oidStr string
if cID, set := a.ContainerID(); set {
cidStr = cID.String()
}
if oID, set := a.ObjectID(); set {
oidStr = oID.String()
}
return strings.Join([]string{cidStr, oidStr}, addressSeparator)
}
// Marshal marshals Address into a protobuf binary form.
@ -122,9 +130,19 @@ func (a *Address) Marshal() ([]byte, error) {
return (*refs.Address)(a).StableMarshal(nil)
}
var errCIDNotSet = errors.New("container ID is not set")
var errOIDNotSet = errors.New("object ID is not set")
// Unmarshal unmarshals protobuf binary representation of Address.
func (a *Address) Unmarshal(data []byte) error {
return (*refs.Address)(a).Unmarshal(data)
err := (*refs.Address)(a).Unmarshal(data)
if err != nil {
return err
}
v2 := a.ToV2()
return checkFormat(v2)
}
// MarshalJSON encodes Address to protobuf JSON format.
@ -134,5 +152,41 @@ func (a *Address) MarshalJSON() ([]byte, error) {
// UnmarshalJSON decodes Address from protobuf JSON format.
func (a *Address) UnmarshalJSON(data []byte) error {
return (*refs.Address)(a).UnmarshalJSON(data)
v2 := (*refs.Address)(a)
err := v2.UnmarshalJSON(data)
if err != nil {
return err
}
return checkFormat(v2)
}
func checkFormat(v2 *refs.Address) error {
var (
cID cid.ID
oID oid.ID
)
cidV2 := v2.GetContainerID()
if cidV2 == nil {
return errCIDNotSet
}
err := cID.ReadFromV2(*cidV2)
if err != nil {
return fmt.Errorf("could not convert V2 container ID: %w", err)
}
oidV2 := v2.GetObjectID()
if oidV2 == nil {
return errOIDNotSet
}
err = oID.ReadFromV2(*oidV2)
if err != nil {
return fmt.Errorf("could not convert V2 object ID: %w", err)
}
return nil
}

View file

@ -17,7 +17,9 @@ func TestAddress_SetContainerID(t *testing.T) {
a.SetContainerID(id)
require.Equal(t, id, a.ContainerID())
cID, set := a.ContainerID()
require.True(t, set)
require.Equal(t, id, cID)
}
func TestAddress_SetObjectID(t *testing.T) {
@ -27,7 +29,9 @@ func TestAddress_SetObjectID(t *testing.T) {
a.SetObjectID(oid)
require.Equal(t, oid, a.ObjectID())
oID, set := a.ObjectID()
require.True(t, set)
require.Equal(t, oid, oID)
}
func TestAddress_Parse(t *testing.T) {
@ -40,8 +44,12 @@ func TestAddress_Parse(t *testing.T) {
a := NewAddress()
require.NoError(t, a.Parse(s))
require.Equal(t, oid, a.ObjectID())
require.Equal(t, cid, a.ContainerID())
oID, set := a.ObjectID()
require.True(t, set)
require.Equal(t, oid, oID)
cID, set := a.ContainerID()
require.True(t, set)
require.Equal(t, cid, cID)
})
t.Run("should fail for bad address", func(t *testing.T) {
@ -107,8 +115,10 @@ func TestNewAddress(t *testing.T) {
a := NewAddress()
// check initial values
require.True(t, a.ContainerID().Empty())
require.True(t, a.ObjectID().Empty())
_, set := a.ContainerID()
require.False(t, set)
_, set = a.ObjectID()
require.False(t, set)
// convert to v2 message
aV2 := a.ToV2()

View file

@ -88,7 +88,12 @@ func VerifyID(obj *Object) error {
return err
}
if !id.Equals(obj.ID()) {
oID, set := obj.ID()
if !set {
return errOIDNotSet
}
if !id.Equals(oID) {
return errIncorrectID
}
@ -98,7 +103,12 @@ func VerifyID(obj *Object) error {
// CalculateAndSetSignature signs id with provided key and sets that signature to
// the object.
func CalculateAndSetSignature(key ecdsa.PrivateKey, obj *Object) error {
sig, err := obj.ID().CalculateIDSignature(key)
oID, set := obj.ID()
if !set {
return errOIDNotSet
}
sig, err := oID.CalculateIDSignature(key)
if err != nil {
return err
}
@ -110,8 +120,13 @@ func CalculateAndSetSignature(key ecdsa.PrivateKey, obj *Object) error {
// VerifyIDSignature verifies object ID signature.
func (o *Object) VerifyIDSignature() bool {
oID, set := o.ID()
if !set {
return false
}
var idV2 refs.ObjectID
o.ID().WriteToV2(&idV2)
oID.WriteToV2(&idV2)
sig := o.Signature()

View file

@ -130,12 +130,6 @@ func (id ID) CalculateIDSignature(key ecdsa.PrivateKey) (signature.Signature, er
return *sign, err
}
// Empty returns true if it is called on
// zero object ID.
func (id ID) Empty() bool {
return id == ID{}
}
// Marshal marshals ID into a protobuf binary form.
func (id ID) Marshal() ([]byte, error) {
var v2 refs.ObjectID

View file

@ -1,6 +1,9 @@
package object
import (
"errors"
"fmt"
"github.com/nspcc-dev/neofs-api-go/v2/object"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-sdk-go/checksum"
@ -86,15 +89,14 @@ func (o *Object) setSplitFields(setter func(*object.SplitHeader)) {
}
// ID returns object identifier.
func (o *Object) ID() oid.ID {
var v oid.ID
func (o *Object) ID() (v oid.ID, isSet bool) {
v2 := (*object.Object)(o)
if id := v2.GetObjectID(); id != nil {
_ = v.ReadFromV2(*v2.GetObjectID())
isSet = true
}
return v
return
}
// SetID sets object identifier.
@ -161,16 +163,16 @@ func (o *Object) SetPayloadSize(v uint64) {
}
// ContainerID returns identifier of the related container.
func (o *Object) ContainerID() cid.ID {
var cID cid.ID
func (o *Object) ContainerID() (v cid.ID, isSet bool) {
v2 := (*object.Object)(o)
cidV2 := v2.GetHeader().GetContainerID()
if cidV2 != nil {
_ = cID.ReadFromV2(*cidV2)
_ = v.ReadFromV2(*cidV2)
isSet = true
}
return cID
return
}
// SetContainerID sets identifier of the related container.
@ -304,16 +306,16 @@ func (o *Object) SetAttributes(v ...Attribute) {
}
// PreviousID returns identifier of the previous sibling object.
func (o *Object) PreviousID() oid.ID {
var v oid.ID
func (o *Object) PreviousID() (v oid.ID, isSet bool) {
v2 := (*object.Object)(o)
v2Prev := v2.GetHeader().GetSplit().GetPrevious()
if v2Prev != nil {
_ = v.ReadFromV2(*v2Prev)
isSet = true
}
return v
return
}
// SetPreviousID sets identifier of the previous sibling object.
@ -432,16 +434,16 @@ func (o *Object) SetSplitID(id *SplitID) {
}
// ParentID returns identifier of the parent object.
func (o *Object) ParentID() oid.ID {
var v oid.ID
func (o *Object) ParentID() (v oid.ID, isSet bool) {
v2 := (*object.Object)(o)
v2Par := v2.GetHeader().GetSplit().GetParent()
if v2Par != nil {
_ = v.ReadFromV2(*v2Par)
isSet = true
}
return v
return
}
// SetParentID sets identifier of the parent object.
@ -564,7 +566,12 @@ func (o *Object) Marshal() ([]byte, error) {
// Unmarshal unmarshals protobuf binary representation of object.
func (o *Object) Unmarshal(data []byte) error {
return (*object.Object)(o).Unmarshal(data)
err := (*object.Object)(o).Unmarshal(data)
if err != nil {
return err
}
return formatCheck((*object.Object)(o))
}
// MarshalJSON encodes object to protobuf JSON format.
@ -574,5 +581,56 @@ func (o *Object) MarshalJSON() ([]byte, error) {
// UnmarshalJSON decodes object from protobuf JSON format.
func (o *Object) UnmarshalJSON(data []byte) error {
return (*object.Object)(o).UnmarshalJSON(data)
err := (*object.Object)(o).UnmarshalJSON(data)
if err != nil {
return err
}
return formatCheck((*object.Object)(o))
}
var errOIDNotSet = errors.New("object ID is not set")
var errCIDNotSet = errors.New("container ID is not set")
func formatCheck(v2 *object.Object) error {
var (
oID oid.ID
cID cid.ID
)
oidV2 := v2.GetObjectID()
if oidV2 == nil {
return errOIDNotSet
}
err := oID.ReadFromV2(*oidV2)
if err != nil {
return fmt.Errorf("could not convert V2 object ID: %w", err)
}
cidV2 := v2.GetHeader().GetContainerID()
if cidV2 == nil {
return errCIDNotSet
}
err = cID.ReadFromV2(*cidV2)
if err != nil {
return fmt.Errorf("could not convert V2 container ID: %w", err)
}
if prev := v2.GetHeader().GetSplit().GetPrevious(); prev != nil {
err = oID.ReadFromV2(*prev)
if err != nil {
return fmt.Errorf("could not convert previous object ID: %w", err)
}
}
if parent := v2.GetHeader().GetSplit().GetParent(); parent != nil {
err = oID.ReadFromV2(*parent)
if err != nil {
return fmt.Errorf("could not convert parent object ID: %w", err)
}
}
return nil
}

View file

@ -19,6 +19,8 @@ func TestInitCreation(t *testing.T) {
Owner: own,
})
require.Equal(t, cnr, o.ContainerID())
cID, set := o.ContainerID()
require.True(t, set)
require.Equal(t, cnr, cID)
require.Equal(t, &own, o.OwnerID())
}

View file

@ -44,7 +44,9 @@ func TestObject_SetID(t *testing.T) {
obj.SetID(id)
require.Equal(t, id, obj.ID())
oID, set := obj.ID()
require.True(t, set)
require.Equal(t, id, oID)
}
func TestObject_SetSignature(t *testing.T) {
@ -98,7 +100,9 @@ func TestObject_SetContainerID(t *testing.T) {
obj.SetContainerID(cid)
require.Equal(t, cid, obj.ContainerID())
cID, set := obj.ContainerID()
require.True(t, set)
require.Equal(t, cid, cID)
}
func TestObject_SetOwnerID(t *testing.T) {
@ -168,7 +172,10 @@ func TestObject_SetPreviousID(t *testing.T) {
obj.SetPreviousID(prev)
require.Equal(t, prev, obj.PreviousID())
oID, set := obj.PreviousID()
require.True(t, set)
require.Equal(t, prev, oID)
}
func TestObject_SetChildren(t *testing.T) {
@ -270,7 +277,9 @@ func TestObject_SetParentID(t *testing.T) {
id := randID(t)
obj.SetParentID(id)
require.Equal(t, id, obj.ParentID())
oID, set := obj.ParentID()
require.True(t, set)
require.Equal(t, id, oID)
}
func TestObject_ResetRelations(t *testing.T) {
@ -280,7 +289,8 @@ func TestObject_ResetRelations(t *testing.T) {
obj.ResetRelations()
require.True(t, obj.PreviousID().Empty())
_, set := obj.PreviousID()
require.False(t, set)
}
func TestObject_HasParent(t *testing.T) {
@ -298,6 +308,7 @@ func TestObject_HasParent(t *testing.T) {
func TestObjectEncoding(t *testing.T) {
o := New()
o.SetID(randID(t))
o.SetContainerID(cidtest.ID())
t.Run("binary", func(t *testing.T) {
data, err := o.Marshal()

View file

@ -1,6 +1,9 @@
package object
import (
"errors"
"fmt"
"github.com/nspcc-dev/neofs-api-go/v2/object"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
@ -41,16 +44,16 @@ func (s *SplitInfo) SetSplitID(v *SplitID) {
(*object.SplitInfo)(s).SetSplitID(v.ToV2())
}
func (s SplitInfo) LastPart() oid.ID {
var id oid.ID
func (s SplitInfo) LastPart() (v oid.ID, isSet bool) {
v2 := (object.SplitInfo)(s)
lpV2 := v2.GetLastPart()
if lpV2 != nil {
_ = id.ReadFromV2(*lpV2)
_ = v.ReadFromV2(*lpV2)
isSet = true
}
return id
return
}
func (s *SplitInfo) SetLastPart(v oid.ID) {
@ -60,16 +63,16 @@ func (s *SplitInfo) SetLastPart(v oid.ID) {
(*object.SplitInfo)(s).SetLastPart(&idV2)
}
func (s SplitInfo) Link() oid.ID {
var id oid.ID
func (s SplitInfo) Link() (v oid.ID, isSet bool) {
v2 := (object.SplitInfo)(s)
linkV2 := v2.GetLink()
if linkV2 != nil {
_ = id.ReadFromV2(*linkV2)
_ = v.ReadFromV2(*linkV2)
isSet = true
}
return id
return
}
func (s *SplitInfo) SetLink(v oid.ID) {
@ -84,7 +87,12 @@ func (s *SplitInfo) Marshal() ([]byte, error) {
}
func (s *SplitInfo) Unmarshal(data []byte) error {
return (*object.SplitInfo)(s).Unmarshal(data)
err := (*object.SplitInfo)(s).Unmarshal(data)
if err != nil {
return err
}
return formatCheckSI((*object.SplitInfo)(s))
}
// MarshalJSON implements json.Marshaler.
@ -94,5 +102,39 @@ func (s *SplitInfo) MarshalJSON() ([]byte, error) {
// UnmarshalJSON implements json.Unmarshaler.
func (s *SplitInfo) UnmarshalJSON(data []byte) error {
return (*object.SplitInfo)(s).UnmarshalJSON(data)
err := (*object.SplitInfo)(s).UnmarshalJSON(data)
if err != nil {
return err
}
return formatCheckSI((*object.SplitInfo)(s))
}
var errLinkNotSet = errors.New("link object ID is not set")
var errLastPartNotSet = errors.New("last part object ID is not set")
func formatCheckSI(v2 *object.SplitInfo) error {
var oID oid.ID
link := v2.GetLink()
if link == nil {
return errLinkNotSet
}
err := oID.ReadFromV2(*link)
if err != nil {
return fmt.Errorf("could not convert link object ID: %w", err)
}
lastPart := v2.GetLastPart()
if lastPart == nil {
return errLastPartNotSet
}
err = oID.ReadFromV2(*lastPart)
if err != nil {
return fmt.Errorf("could not convert last part object ID: %w", err)
}
return nil
}

View file

@ -21,10 +21,14 @@ func TestSplitInfo(t *testing.T) {
require.Equal(t, splitID, s.SplitID())
s.SetLastPart(lastPart)
require.Equal(t, lastPart, s.LastPart())
lp, set := s.LastPart()
require.True(t, set)
require.Equal(t, lastPart, lp)
s.SetLink(link)
require.Equal(t, link, s.Link())
l, set := s.Link()
require.True(t, set)
require.Equal(t, link, l)
t.Run("to and from v2", func(t *testing.T) {
v2 := s.ToV2()
@ -77,8 +81,10 @@ func TestNewSplitInfo(t *testing.T) {
// check initial values
require.Nil(t, si.SplitID())
require.True(t, si.LastPart().Empty())
require.True(t, si.Link().Empty())
_, set := si.LastPart()
require.False(t, set)
_, set = si.Link()
require.False(t, set)
// convert to v2 message
siV2 := si.ToV2()

View file

@ -192,7 +192,12 @@ func (c *clientWrapper) containerSetEACL(ctx context.Context, prm PrmContainerSe
prm.waitParams.setDefaults()
}
return waitForEACLPresence(ctx, c, prm.table.CID(), &prm.table, &prm.waitParams)
var cIDp *cid.ID
if cID, set := prm.table.CID(); set {
cIDp = &cID
}
return waitForEACLPresence(ctx, c, cIDp, &prm.table, &prm.waitParams)
}
func (c *clientWrapper) endpointInfo(ctx context.Context, _ prmEndpointInfo) (*netmap.NodeInfo, error) {
@ -288,12 +293,12 @@ func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (*oid.I
func (c *clientWrapper) objectDelete(ctx context.Context, prm PrmObjectDelete) error {
var cliPrm sdkClient.PrmObjectDelete
if cnr := prm.addr.ContainerID(); cnr != nil {
cliPrm.FromContainer(*cnr)
if cnr, set := prm.addr.ContainerID(); set {
cliPrm.FromContainer(cnr)
}
if obj := prm.addr.ObjectID(); obj != nil {
cliPrm.ByID(*obj)
if obj, set := prm.addr.ObjectID(); set {
cliPrm.ByID(obj)
}
if prm.stoken != nil {
@ -314,20 +319,20 @@ func (c *clientWrapper) objectDelete(ctx context.Context, prm PrmObjectDelete) e
func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (*ResGetObject, error) {
var cliPrm sdkClient.PrmObjectGet
if cnr := prm.addr.ContainerID(); cnr != nil {
cliPrm.FromContainer(*cnr)
if cnr, set := prm.addr.ContainerID(); set {
cliPrm.FromContainer(cnr)
}
if obj := prm.addr.ObjectID(); obj != nil {
cliPrm.ByID(*obj)
if obj, set := prm.addr.ObjectID(); set {
cliPrm.ByID(obj)
}
if cnr := prm.addr.ContainerID(); cnr != nil {
cliPrm.FromContainer(*cnr)
if cnr, set := prm.addr.ContainerID(); set {
cliPrm.FromContainer(cnr)
}
if obj := prm.addr.ObjectID(); obj != nil {
cliPrm.ByID(*obj)
if obj, set := prm.addr.ObjectID(); set {
cliPrm.ByID(obj)
}
if prm.stoken != nil {
@ -362,12 +367,12 @@ func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (*ResGe
func (c *clientWrapper) objectHead(ctx context.Context, prm PrmObjectHead) (*object.Object, error) {
var cliPrm sdkClient.PrmObjectHead
if cnr := prm.addr.ContainerID(); cnr != nil {
cliPrm.FromContainer(*cnr)
if cnr, set := prm.addr.ContainerID(); set {
cliPrm.FromContainer(cnr)
}
if obj := prm.addr.ObjectID(); obj != nil {
cliPrm.ByID(*obj)
if obj, set := prm.addr.ObjectID(); set {
cliPrm.ByID(obj)
}
if prm.stoken != nil {
@ -401,12 +406,12 @@ func (c *clientWrapper) objectRange(ctx context.Context, prm PrmObjectRange) (*R
cliPrm.SetOffset(prm.off)
cliPrm.SetLength(prm.ln)
if cnr := prm.addr.ContainerID(); cnr != nil {
cliPrm.FromContainer(*cnr)
if cnr, set := prm.addr.ContainerID(); set {
cliPrm.FromContainer(cnr)
}
if obj := prm.addr.ObjectID(); obj != nil {
cliPrm.ByID(*obj)
if obj, set := prm.addr.ObjectID(); set {
cliPrm.ByID(obj)
}
if prm.stoken != nil {
@ -1354,10 +1359,15 @@ func (p *Pool) fillAppropriateKey(prm *prmCommon) {
// PutObject writes an object through a remote server using NeoFS API protocol.
func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (*oid.ID, error) {
var cIDp *cid.ID
if cID, set := prm.hdr.ContainerID(); set {
cIDp = &cID
}
var prmCtx prmContext
prmCtx.useDefaultSession()
prmCtx.useVerb(sessionv2.ObjectVerbPut)
prmCtx.useAddress(newAddressFromCnrID(prm.hdr.ContainerID()))
prmCtx.useAddress(newAddressFromCnrID(cIDp))
p.fillAppropriateKey(&prm.prmCommon)
@ -1786,7 +1796,9 @@ func sessionTokenForOwner(id *owner.ID, cliRes *resCreateSession, exp uint64) *s
func newAddressFromCnrID(cnrID *cid.ID) *address.Address {
addr := address.NewAddress()
addr.SetContainerID(cnrID)
if cnrID != nil {
addr.SetContainerID(*cnrID)
}
return addr
}