forked from TrueCloudLab/frostfs-sdk-go
[#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:
parent
f7172adf18
commit
1186f2f703
17 changed files with 432 additions and 118 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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{}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
58
pool/pool.go
58
pool/pool.go
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue