forked from TrueCloudLab/frostfs-sdk-go
[#170] oid, cid: Refactor and document package functionality
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
parent
24d6c2221f
commit
f7172adf18
49 changed files with 831 additions and 439 deletions
|
@ -75,20 +75,29 @@ func (r *Result) ForEpoch(epoch uint64) {
|
||||||
// Container returns identifier of the container with which the data audit Result
|
// Container returns identifier of the container with which the data audit Result
|
||||||
// is associated.
|
// is associated.
|
||||||
//
|
//
|
||||||
// Returns nil if container is not specified. Zero Result has nil container.
|
// Returns zero ID if container is not specified. Zero Result has zero container.
|
||||||
// Return value MUST NOT be mutated: to do this, first make a copy.
|
|
||||||
//
|
//
|
||||||
// See also ForContainer.
|
// See also ForContainer.
|
||||||
func (r Result) Container() *cid.ID {
|
func (r Result) Container() cid.ID {
|
||||||
return cid.NewFromV2(r.v2.GetContainerID())
|
var cID cid.ID
|
||||||
|
|
||||||
|
cidV2 := r.v2.GetContainerID()
|
||||||
|
if cidV2 != nil {
|
||||||
|
_ = cID.ReadFromV2(*cidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForContainer returns identifier of the container with which the data audit Result
|
return cID
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForContainer sets identifier of the container with which the data audit Result
|
||||||
// is associated.
|
// is associated.
|
||||||
//
|
//
|
||||||
// See also Container.
|
// See also Container.
|
||||||
func (r *Result) ForContainer(cnr cid.ID) {
|
func (r *Result) ForContainer(cnr cid.ID) {
|
||||||
r.v2.SetContainerID(cnr.ToV2())
|
var cidV2 refs.ContainerID
|
||||||
|
cnr.WriteToV2(&cidV2)
|
||||||
|
|
||||||
|
r.v2.SetContainerID(&cidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuditorKey returns public key of the auditing NeoFS Inner Ring node in
|
// AuditorKey returns public key of the auditing NeoFS Inner Ring node in
|
||||||
|
@ -174,8 +183,12 @@ func (r *Result) SetRetriesPoR(v uint32) {
|
||||||
func (r Result) IteratePassedStorageGroups(f func(oid.ID) bool) {
|
func (r Result) IteratePassedStorageGroups(f func(oid.ID) bool) {
|
||||||
r2 := r.v2.GetPassSG()
|
r2 := r.v2.GetPassSG()
|
||||||
|
|
||||||
|
var id oid.ID
|
||||||
|
|
||||||
for i := range r2 {
|
for i := range r2 {
|
||||||
if !f(*oid.NewIDFromV2(&r2[i])) {
|
_ = id.ReadFromV2(r2[i])
|
||||||
|
|
||||||
|
if !f(id) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,7 +199,10 @@ func (r Result) IteratePassedStorageGroups(f func(oid.ID) bool) {
|
||||||
//
|
//
|
||||||
// See also IteratePassedStorageGroups.
|
// See also IteratePassedStorageGroups.
|
||||||
func (r *Result) SubmitPassedStorageGroup(sg oid.ID) {
|
func (r *Result) SubmitPassedStorageGroup(sg oid.ID) {
|
||||||
r.v2.SetPassSG(append(r.v2.GetPassSG(), *sg.ToV2()))
|
var idV2 refs.ObjectID
|
||||||
|
sg.WriteToV2(&idV2)
|
||||||
|
|
||||||
|
r.v2.SetPassSG(append(r.v2.GetPassSG(), idV2))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterateFailedStorageGroups is similar to IteratePassedStorageGroups but for failed groups.
|
// IterateFailedStorageGroups is similar to IteratePassedStorageGroups but for failed groups.
|
||||||
|
@ -194,9 +210,11 @@ func (r *Result) SubmitPassedStorageGroup(sg oid.ID) {
|
||||||
// See also SubmitFailedStorageGroup.
|
// See also SubmitFailedStorageGroup.
|
||||||
func (r Result) IterateFailedStorageGroups(f func(oid.ID) bool) {
|
func (r Result) IterateFailedStorageGroups(f func(oid.ID) bool) {
|
||||||
v := r.v2.GetFailSG()
|
v := r.v2.GetFailSG()
|
||||||
|
var id oid.ID
|
||||||
|
|
||||||
for i := range v {
|
for i := range v {
|
||||||
if !f(*oid.NewIDFromV2(&v[i])) {
|
_ = id.ReadFromV2(v[i])
|
||||||
|
if !f(id) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,7 +224,10 @@ func (r Result) IterateFailedStorageGroups(f func(oid.ID) bool) {
|
||||||
//
|
//
|
||||||
// See also IterateFailedStorageGroups.
|
// See also IterateFailedStorageGroups.
|
||||||
func (r *Result) SubmitFailedStorageGroup(sg oid.ID) {
|
func (r *Result) SubmitFailedStorageGroup(sg oid.ID) {
|
||||||
r.v2.SetFailSG(append(r.v2.GetFailSG(), *sg.ToV2()))
|
var idV2 refs.ObjectID
|
||||||
|
sg.WriteToV2(&idV2)
|
||||||
|
|
||||||
|
r.v2.SetFailSG(append(r.v2.GetFailSG(), idV2))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hits returns number of sampled objects under audit placed
|
// Hits returns number of sampled objects under audit placed
|
||||||
|
|
|
@ -66,7 +66,7 @@ func TestResultData(t *testing.T) {
|
||||||
countFailNodes := func(f func([]byte)) int { return countNodes(false, f) }
|
countFailNodes := func(f func([]byte)) int { return countNodes(false, f) }
|
||||||
|
|
||||||
require.Zero(t, r.Epoch())
|
require.Zero(t, r.Epoch())
|
||||||
require.Nil(t, r.Container())
|
require.True(t, r.Container().Empty())
|
||||||
require.Nil(t, r.AuditorKey())
|
require.Nil(t, r.AuditorKey())
|
||||||
require.False(t, r.Completed())
|
require.False(t, r.Completed())
|
||||||
require.Zero(t, r.RequestsPoR())
|
require.Zero(t, r.RequestsPoR())
|
||||||
|
@ -81,7 +81,7 @@ func TestResultData(t *testing.T) {
|
||||||
require.Equal(t, epoch, r.Epoch())
|
require.Equal(t, epoch, r.Epoch())
|
||||||
|
|
||||||
cnr := cidtest.ID()
|
cnr := cidtest.ID()
|
||||||
r.ForContainer(*cnr)
|
r.ForContainer(cnr)
|
||||||
require.Equal(t, cnr, r.Container())
|
require.Equal(t, cnr, r.Container())
|
||||||
|
|
||||||
key := []byte{1, 2, 3}
|
key := []byte{1, 2, 3}
|
||||||
|
@ -99,32 +99,32 @@ func TestResultData(t *testing.T) {
|
||||||
r.SetRetriesPoR(retries)
|
r.SetRetriesPoR(retries)
|
||||||
require.Equal(t, retries, r.RetriesPoR())
|
require.Equal(t, retries, r.RetriesPoR())
|
||||||
|
|
||||||
passSG1, passSG2 := *oidtest.ID(), *oidtest.ID()
|
passSG1, passSG2 := oidtest.ID(), oidtest.ID()
|
||||||
r.SubmitPassedStorageGroup(passSG1)
|
r.SubmitPassedStorageGroup(passSG1)
|
||||||
r.SubmitPassedStorageGroup(passSG2)
|
r.SubmitPassedStorageGroup(passSG2)
|
||||||
|
|
||||||
called1, called2 := false, false
|
called1, called2 := false, false
|
||||||
|
|
||||||
require.EqualValues(t, 2, countPassSG(func(id oid.ID) {
|
require.EqualValues(t, 2, countPassSG(func(id oid.ID) {
|
||||||
if id.Equal(&passSG1) {
|
if id.Equals(passSG1) {
|
||||||
called1 = true
|
called1 = true
|
||||||
} else if id.Equal(&passSG2) {
|
} else if id.Equals(passSG2) {
|
||||||
called2 = true
|
called2 = true
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
require.True(t, called1)
|
require.True(t, called1)
|
||||||
require.True(t, called2)
|
require.True(t, called2)
|
||||||
|
|
||||||
failSG1, failSG2 := *oidtest.ID(), *oidtest.ID()
|
failSG1, failSG2 := oidtest.ID(), oidtest.ID()
|
||||||
r.SubmitFailedStorageGroup(failSG1)
|
r.SubmitFailedStorageGroup(failSG1)
|
||||||
r.SubmitFailedStorageGroup(failSG2)
|
r.SubmitFailedStorageGroup(failSG2)
|
||||||
|
|
||||||
called1, called2 = false, false
|
called1, called2 = false, false
|
||||||
|
|
||||||
require.EqualValues(t, 2, countFailSG(func(id oid.ID) {
|
require.EqualValues(t, 2, countFailSG(func(id oid.ID) {
|
||||||
if id.Equal(&failSG1) {
|
if id.Equals(failSG1) {
|
||||||
called1 = true
|
called1 = true
|
||||||
} else if id.Equal(&failSG2) {
|
} else if id.Equals(failSG2) {
|
||||||
called2 = true
|
called2 = true
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
func Result() *audit.Result {
|
func Result() *audit.Result {
|
||||||
var x audit.Result
|
var x audit.Result
|
||||||
|
|
||||||
x.ForContainer(*cidtest.ID())
|
x.ForContainer(cidtest.ID())
|
||||||
x.SetAuditorKey([]byte("key"))
|
x.SetAuditorKey([]byte("key"))
|
||||||
x.Complete()
|
x.Complete()
|
||||||
x.ForEpoch(44)
|
x.ForEpoch(44)
|
||||||
|
@ -27,10 +27,10 @@ func Result() *audit.Result {
|
||||||
[]byte("node3"),
|
[]byte("node3"),
|
||||||
[]byte("node4"),
|
[]byte("node4"),
|
||||||
})
|
})
|
||||||
x.SubmitPassedStorageGroup(*oidtest.ID())
|
x.SubmitPassedStorageGroup(oidtest.ID())
|
||||||
x.SubmitPassedStorageGroup(*oidtest.ID())
|
x.SubmitPassedStorageGroup(oidtest.ID())
|
||||||
x.SubmitFailedStorageGroup(*oidtest.ID())
|
x.SubmitFailedStorageGroup(oidtest.ID())
|
||||||
x.SubmitFailedStorageGroup(*oidtest.ID())
|
x.SubmitFailedStorageGroup(oidtest.ID())
|
||||||
|
|
||||||
return &x
|
return &x
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
v2container "github.com/nspcc-dev/neofs-api-go/v2/container"
|
v2container "github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
|
@ -121,7 +122,17 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon
|
||||||
}
|
}
|
||||||
cc.result = func(r responseV2) {
|
cc.result = func(r responseV2) {
|
||||||
resp := r.(*v2container.PutResponse)
|
resp := r.(*v2container.PutResponse)
|
||||||
res.setID(cid.NewFromV2(resp.GetBody().GetContainerID()))
|
var cID *cid.ID
|
||||||
|
|
||||||
|
cidV2 := resp.GetBody().GetContainerID()
|
||||||
|
if cidV2 != nil {
|
||||||
|
var c cid.ID
|
||||||
|
_ = c.ReadFromV2(*cidV2)
|
||||||
|
|
||||||
|
cID = &c
|
||||||
|
}
|
||||||
|
|
||||||
|
res.setID(cID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// process call
|
// process call
|
||||||
|
@ -187,9 +198,12 @@ func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResCon
|
||||||
panic(panicMsgMissingContainer)
|
panic(panicMsgMissingContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cidV2 refs.ContainerID
|
||||||
|
prm.id.WriteToV2(&cidV2)
|
||||||
|
|
||||||
// form request body
|
// form request body
|
||||||
reqBody := new(v2container.GetRequestBody)
|
reqBody := new(v2container.GetRequestBody)
|
||||||
reqBody.SetContainerID(prm.id.ToV2())
|
reqBody.SetContainerID(&cidV2)
|
||||||
|
|
||||||
// form request
|
// form request
|
||||||
var req v2container.GetRequest
|
var req v2container.GetRequest
|
||||||
|
@ -322,7 +336,7 @@ func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResC
|
||||||
ids := make([]cid.ID, len(resp.GetBody().GetContainerIDs()))
|
ids := make([]cid.ID, len(resp.GetBody().GetContainerIDs()))
|
||||||
|
|
||||||
for i, cidV2 := range resp.GetBody().GetContainerIDs() {
|
for i, cidV2 := range resp.GetBody().GetContainerIDs() {
|
||||||
ids[i] = *cid.NewFromV2(&cidV2)
|
_ = ids[i].ReadFromV2(cidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setContainers(ids)
|
res.setContainers(ids)
|
||||||
|
@ -400,9 +414,12 @@ func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*
|
||||||
panic(panicMsgMissingContainer)
|
panic(panicMsgMissingContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cidV2 refs.ContainerID
|
||||||
|
prm.id.WriteToV2(&cidV2)
|
||||||
|
|
||||||
// form request body
|
// form request body
|
||||||
reqBody := new(v2container.DeleteRequestBody)
|
reqBody := new(v2container.DeleteRequestBody)
|
||||||
reqBody.SetContainerID(prm.id.ToV2())
|
reqBody.SetContainerID(&cidV2)
|
||||||
|
|
||||||
signWrapper := delContainerSignWrapper{body: reqBody}
|
signWrapper := delContainerSignWrapper{body: reqBody}
|
||||||
|
|
||||||
|
@ -504,9 +521,12 @@ func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResC
|
||||||
panic(panicMsgMissingContainer)
|
panic(panicMsgMissingContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cidV2 refs.ContainerID
|
||||||
|
prm.id.WriteToV2(&cidV2)
|
||||||
|
|
||||||
// form request body
|
// form request body
|
||||||
reqBody := new(v2container.GetExtendedACLRequestBody)
|
reqBody := new(v2container.GetExtendedACLRequestBody)
|
||||||
reqBody.SetContainerID(prm.id.ToV2())
|
reqBody.SetContainerID(&cidV2)
|
||||||
|
|
||||||
// form request
|
// form request
|
||||||
var req v2container.GetExtendedACLRequest
|
var req v2container.GetExtendedACLRequest
|
||||||
|
|
|
@ -52,13 +52,19 @@ func (x *PrmObjectDelete) WithBearerToken(t bearer.Token) {
|
||||||
// FromContainer specifies NeoFS container of the object.
|
// FromContainer specifies NeoFS container of the object.
|
||||||
// Required parameter.
|
// Required parameter.
|
||||||
func (x *PrmObjectDelete) FromContainer(id cid.ID) {
|
func (x *PrmObjectDelete) FromContainer(id cid.ID) {
|
||||||
x.addr.SetContainerID(id.ToV2())
|
var cidV2 v2refs.ContainerID
|
||||||
|
id.WriteToV2(&cidV2)
|
||||||
|
|
||||||
|
x.addr.SetContainerID(&cidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByID specifies identifier of the requested object.
|
// ByID specifies identifier of the requested object.
|
||||||
// Required parameter.
|
// Required parameter.
|
||||||
func (x *PrmObjectDelete) ByID(id oid.ID) {
|
func (x *PrmObjectDelete) ByID(id oid.ID) {
|
||||||
x.addr.SetObjectID(id.ToV2())
|
var idV2 v2refs.ObjectID
|
||||||
|
id.WriteToV2(&idV2)
|
||||||
|
|
||||||
|
x.addr.SetObjectID(&idV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseKey specifies private key to sign the requests.
|
// UseKey specifies private key to sign the requests.
|
||||||
|
@ -91,7 +97,7 @@ type ResObjectDelete struct {
|
||||||
// Returns false if ID is missing (not read).
|
// Returns false if ID is missing (not read).
|
||||||
func (x ResObjectDelete) ReadTombstoneID(dst *oid.ID) bool {
|
func (x ResObjectDelete) ReadTombstoneID(dst *oid.ID) bool {
|
||||||
if x.idTomb != nil {
|
if x.idTomb != nil {
|
||||||
*dst = *oid.NewIDFromV2(x.idTomb) // need smth better
|
_ = dst.ReadFromV2(*x.idTomb)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,10 +36,10 @@ type prmObjectRead struct {
|
||||||
bearer bearer.Token
|
bearer bearer.Token
|
||||||
|
|
||||||
cnrSet bool
|
cnrSet bool
|
||||||
cnr cid.ID
|
cnrID cid.ID
|
||||||
|
|
||||||
objSet bool
|
objSet bool
|
||||||
obj oid.ID
|
objID oid.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x prmObjectRead) writeToMetaHeader(h *v2session.RequestMetaHeader) {
|
func (x prmObjectRead) writeToMetaHeader(h *v2session.RequestMetaHeader) {
|
||||||
|
@ -94,14 +94,14 @@ func (x *prmObjectRead) WithBearerToken(t bearer.Token) {
|
||||||
// FromContainer specifies NeoFS container of the object.
|
// FromContainer specifies NeoFS container of the object.
|
||||||
// Required parameter.
|
// Required parameter.
|
||||||
func (x *prmObjectRead) FromContainer(id cid.ID) {
|
func (x *prmObjectRead) FromContainer(id cid.ID) {
|
||||||
x.cnr = id
|
x.cnrID = id
|
||||||
x.cnrSet = true
|
x.cnrSet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByID specifies identifier of the requested object.
|
// ByID specifies identifier of the requested object.
|
||||||
// Required parameter.
|
// Required parameter.
|
||||||
func (x *prmObjectRead) ByID(id oid.ID) {
|
func (x *prmObjectRead) ByID(id oid.ID) {
|
||||||
x.obj = id
|
x.objID = id
|
||||||
x.objSet = true
|
x.objSet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,10 +318,17 @@ func (c *Client) ObjectGetInit(ctx context.Context, prm PrmObjectGet) (*ObjectRe
|
||||||
panic("missing object")
|
panic("missing object")
|
||||||
}
|
}
|
||||||
|
|
||||||
var addr v2refs.Address
|
var (
|
||||||
|
addr v2refs.Address
|
||||||
|
oidV2 v2refs.ObjectID
|
||||||
|
cidV2 v2refs.ContainerID
|
||||||
|
)
|
||||||
|
|
||||||
addr.SetContainerID(prm.cnr.ToV2())
|
prm.objID.WriteToV2(&oidV2)
|
||||||
addr.SetObjectID(prm.obj.ToV2())
|
prm.cnrID.WriteToV2(&cidV2)
|
||||||
|
|
||||||
|
addr.SetContainerID(&cidV2)
|
||||||
|
addr.SetObjectID(&oidV2)
|
||||||
|
|
||||||
// form request body
|
// form request body
|
||||||
var body v2object.GetRequestBody
|
var body v2object.GetRequestBody
|
||||||
|
@ -411,7 +418,7 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
|
||||||
objv2.SetSignature(x.hdr.GetSignature())
|
objv2.SetSignature(x.hdr.GetSignature())
|
||||||
|
|
||||||
obj := object.NewFromV2(&objv2)
|
obj := object.NewFromV2(&objv2)
|
||||||
obj.SetID(&x.idObj)
|
obj.SetID(x.idObj)
|
||||||
|
|
||||||
*dst = *obj
|
*dst = *obj
|
||||||
|
|
||||||
|
@ -449,16 +456,23 @@ func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectH
|
||||||
panic("missing object")
|
panic("missing object")
|
||||||
}
|
}
|
||||||
|
|
||||||
var addr v2refs.Address
|
var (
|
||||||
|
addrV2 v2refs.Address
|
||||||
|
oidV2 v2refs.ObjectID
|
||||||
|
cidV2 v2refs.ContainerID
|
||||||
|
)
|
||||||
|
|
||||||
addr.SetContainerID(prm.cnr.ToV2())
|
prm.objID.WriteToV2(&oidV2)
|
||||||
addr.SetObjectID(prm.obj.ToV2())
|
prm.cnrID.WriteToV2(&cidV2)
|
||||||
|
|
||||||
|
addrV2.SetContainerID(&cidV2)
|
||||||
|
addrV2.SetObjectID(&oidV2)
|
||||||
|
|
||||||
// form request body
|
// form request body
|
||||||
var body v2object.HeadRequestBody
|
var body v2object.HeadRequestBody
|
||||||
|
|
||||||
body.SetRaw(prm.raw)
|
body.SetRaw(prm.raw)
|
||||||
body.SetAddress(&addr)
|
body.SetAddress(&addrV2)
|
||||||
|
|
||||||
// form meta header
|
// form meta header
|
||||||
var meta v2session.RequestMetaHeader
|
var meta v2session.RequestMetaHeader
|
||||||
|
@ -478,7 +492,7 @@ func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectH
|
||||||
res ResObjectHead
|
res ResObjectHead
|
||||||
)
|
)
|
||||||
|
|
||||||
res.idObj = prm.obj
|
res.idObj = prm.objID
|
||||||
|
|
||||||
if prm.keySet {
|
if prm.keySet {
|
||||||
c.initCallContextWithoutKey(&cc)
|
c.initCallContextWithoutKey(&cc)
|
||||||
|
@ -715,10 +729,17 @@ func (c *Client) ObjectRangeInit(ctx context.Context, prm PrmObjectRange) (*Obje
|
||||||
panic("zero range length")
|
panic("zero range length")
|
||||||
}
|
}
|
||||||
|
|
||||||
var addr v2refs.Address
|
var (
|
||||||
|
addrV2 v2refs.Address
|
||||||
|
oidV2 v2refs.ObjectID
|
||||||
|
cidV2 v2refs.ContainerID
|
||||||
|
)
|
||||||
|
|
||||||
addr.SetContainerID(prm.cnr.ToV2())
|
prm.objID.WriteToV2(&oidV2)
|
||||||
addr.SetObjectID(prm.obj.ToV2())
|
prm.cnrID.WriteToV2(&cidV2)
|
||||||
|
|
||||||
|
addrV2.SetContainerID(&cidV2)
|
||||||
|
addrV2.SetObjectID(&oidV2)
|
||||||
|
|
||||||
var rng v2object.Range
|
var rng v2object.Range
|
||||||
|
|
||||||
|
@ -729,7 +750,7 @@ func (c *Client) ObjectRangeInit(ctx context.Context, prm PrmObjectRange) (*Obje
|
||||||
var body v2object.GetRangeRequestBody
|
var body v2object.GetRangeRequestBody
|
||||||
|
|
||||||
body.SetRaw(prm.raw)
|
body.SetRaw(prm.raw)
|
||||||
body.SetAddress(&addr)
|
body.SetAddress(&addrV2)
|
||||||
body.SetRange(&rng)
|
body.SetRange(&rng)
|
||||||
|
|
||||||
// form meta header
|
// form meta header
|
||||||
|
|
|
@ -55,13 +55,19 @@ func (x *PrmObjectHash) WithBearerToken(t bearer.Token) {
|
||||||
// FromContainer specifies NeoFS container of the object.
|
// FromContainer specifies NeoFS container of the object.
|
||||||
// Required parameter.
|
// Required parameter.
|
||||||
func (x *PrmObjectHash) FromContainer(id cid.ID) {
|
func (x *PrmObjectHash) FromContainer(id cid.ID) {
|
||||||
x.addr.SetContainerID(id.ToV2())
|
var cidV2 v2refs.ContainerID
|
||||||
|
id.WriteToV2(&cidV2)
|
||||||
|
|
||||||
|
x.addr.SetContainerID(&cidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByID specifies identifier of the requested object.
|
// ByID specifies identifier of the requested object.
|
||||||
// Required parameter.
|
// Required parameter.
|
||||||
func (x *PrmObjectHash) ByID(id oid.ID) {
|
func (x *PrmObjectHash) ByID(id oid.ID) {
|
||||||
x.addr.SetObjectID(id.ToV2())
|
var idV2 v2refs.ObjectID
|
||||||
|
id.WriteToV2(&idV2)
|
||||||
|
|
||||||
|
x.addr.SetObjectID(&idV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRangeList sets list of ranges in (offset, length) pair format.
|
// SetRangeList sets list of ranges in (offset, length) pair format.
|
||||||
|
|
|
@ -37,7 +37,7 @@ func (x *ResObjectPut) ReadStoredObjectID(id *oid.ID) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
*id = *oid.NewIDFromV2(idv2) // need smth better
|
_ = id.ReadFromV2(*idv2)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ type PrmObjectSearch struct {
|
||||||
bearer bearer.Token
|
bearer bearer.Token
|
||||||
|
|
||||||
cnrSet bool
|
cnrSet bool
|
||||||
cnr cid.ID
|
cnrID cid.ID
|
||||||
|
|
||||||
filters object.SearchFilters
|
filters object.SearchFilters
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ func (x *PrmObjectSearch) WithBearerToken(t bearer.Token) {
|
||||||
// InContainer specifies the container in which to look for objects.
|
// InContainer specifies the container in which to look for objects.
|
||||||
// Required parameter.
|
// Required parameter.
|
||||||
func (x *PrmObjectSearch) InContainer(id cid.ID) {
|
func (x *PrmObjectSearch) InContainer(id cid.ID) {
|
||||||
x.cnr = id
|
x.cnrID = id
|
||||||
x.cnrSet = true
|
x.cnrSet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ func (x *ObjectListReader) Read(buf []oid.ID) (int, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < read; i++ {
|
for i := 0; i < read; i++ {
|
||||||
buf[i] = *oid.NewIDFromV2(&x.tail[i]) // need smth better
|
_ = buf[i].ReadFromV2(x.tail[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
x.tail = x.tail[read:]
|
x.tail = x.tail[read:]
|
||||||
|
@ -165,7 +165,7 @@ func (x *ObjectListReader) Read(buf []oid.ID) (int, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i = 0; i < ln; i++ {
|
for i = 0; i < ln; i++ {
|
||||||
buf[read+i] = *oid.NewIDFromV2(&ids[i]) // need smth better
|
_ = buf[read+i].ReadFromV2(ids[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
read += ln
|
read += ln
|
||||||
|
@ -244,10 +244,15 @@ func (c *Client) ObjectSearchInit(ctx context.Context, prm PrmObjectSearch) (*Ob
|
||||||
}
|
}
|
||||||
|
|
||||||
// form request body
|
// form request body
|
||||||
var body v2object.SearchRequestBody
|
var (
|
||||||
|
body v2object.SearchRequestBody
|
||||||
|
cidV2 v2refs.ContainerID
|
||||||
|
)
|
||||||
|
|
||||||
|
prm.cnrID.WriteToV2(&cidV2)
|
||||||
|
|
||||||
body.SetVersion(1)
|
body.SetVersion(1)
|
||||||
body.SetContainerID(prm.cnr.ToV2())
|
body.SetContainerID(&cidV2)
|
||||||
body.SetFilters(prm.filters.ToV2())
|
body.SetFilters(prm.filters.ToV2())
|
||||||
|
|
||||||
// form meta header
|
// form meta header
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
func TestObjectSearch(t *testing.T) {
|
func TestObjectSearch(t *testing.T) {
|
||||||
ids := make([]oid.ID, 20)
|
ids := make([]oid.ID, 20)
|
||||||
for i := range ids {
|
for i := range ids {
|
||||||
ids[i] = *oidtest.ID()
|
ids[i] = oidtest.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, setID := testListReaderResponse(t)
|
resp, setID := testListReaderResponse(t)
|
||||||
|
@ -88,7 +88,7 @@ func TestObjectSearch(t *testing.T) {
|
||||||
func TestObjectIterate(t *testing.T) {
|
func TestObjectIterate(t *testing.T) {
|
||||||
ids := make([]oid.ID, 3)
|
ids := make([]oid.ID, 3)
|
||||||
for i := range ids {
|
for i := range ids {
|
||||||
ids[i] = *oidtest.ID()
|
ids[i] = oidtest.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("iterate all sequence", func(t *testing.T) {
|
t.Run("iterate all sequence", func(t *testing.T) {
|
||||||
|
@ -176,8 +176,11 @@ func testListReaderResponse(t *testing.T) (*ObjectListReader, func(id []oid.ID)
|
||||||
resp.SetBody(new(object.SearchResponseBody))
|
resp.SetBody(new(object.SearchResponseBody))
|
||||||
|
|
||||||
v2id := make([]refs.ObjectID, len(id))
|
v2id := make([]refs.ObjectID, len(id))
|
||||||
|
var oidV2 refs.ObjectID
|
||||||
|
|
||||||
for i := range id {
|
for i := range id {
|
||||||
v2id[i] = *id[i].ToV2()
|
id[i].WriteToV2(&oidV2)
|
||||||
|
v2id[i] = oidV2
|
||||||
}
|
}
|
||||||
resp.GetBody().SetIDList(v2id)
|
resp.GetBody().SetIDList(v2id)
|
||||||
err := signatureV2.SignServiceMessage(&p.PrivateKey, resp)
|
err := signatureV2.SignServiceMessage(&p.PrivateKey, resp)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
"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"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,15 +39,25 @@ func (a *UsedSpaceAnnouncement) SetEpoch(epoch uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerID of the announcement.
|
// ContainerID of the announcement.
|
||||||
func (a *UsedSpaceAnnouncement) ContainerID() *cid.ID {
|
func (a *UsedSpaceAnnouncement) ContainerID() (cID cid.ID) {
|
||||||
return cid.NewFromV2(
|
v2 := (*container.UsedSpaceAnnouncement)(a)
|
||||||
(*container.UsedSpaceAnnouncement)(a).GetContainerID(),
|
|
||||||
)
|
cidV2 := v2.GetContainerID()
|
||||||
|
if cidV2 == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = cID.ReadFromV2(*cidV2)
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetContainerID sets announcement container value.
|
// SetContainerID sets announcement container value.
|
||||||
func (a *UsedSpaceAnnouncement) SetContainerID(cid *cid.ID) {
|
func (a *UsedSpaceAnnouncement) SetContainerID(cnr cid.ID) {
|
||||||
(*container.UsedSpaceAnnouncement)(a).SetContainerID(cid.ToV2())
|
var cidV2 refs.ContainerID
|
||||||
|
cnr.WriteToV2(&cidV2)
|
||||||
|
|
||||||
|
(*container.UsedSpaceAnnouncement)(a).SetContainerID(&cidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UsedSpace in container.
|
// UsedSpace in container.
|
||||||
|
|
|
@ -46,9 +46,12 @@ func TestAnnouncement(t *testing.T) {
|
||||||
|
|
||||||
newA := container.NewAnnouncementFromV2(v2)
|
newA := container.NewAnnouncementFromV2(v2)
|
||||||
|
|
||||||
|
var cID cid.ID
|
||||||
|
_ = cID.ReadFromV2(*newCID)
|
||||||
|
|
||||||
require.Equal(t, newEpoch, newA.Epoch())
|
require.Equal(t, newEpoch, newA.Epoch())
|
||||||
require.Equal(t, newUsedSpace, newA.UsedSpace())
|
require.Equal(t, newUsedSpace, newA.UsedSpace())
|
||||||
require.Equal(t, cid.NewFromV2(newCID), newA.ContainerID())
|
require.Equal(t, cID, newA.ContainerID())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +82,7 @@ func TestUsedSpaceAnnouncement_ToV2(t *testing.T) {
|
||||||
// check initial values
|
// check initial values
|
||||||
require.Zero(t, announcement.Epoch())
|
require.Zero(t, announcement.Epoch())
|
||||||
require.Zero(t, announcement.UsedSpace())
|
require.Zero(t, announcement.UsedSpace())
|
||||||
require.Nil(t, announcement.ContainerID())
|
require.True(t, announcement.ContainerID().Empty())
|
||||||
|
|
||||||
// convert to v2 message
|
// convert to v2 message
|
||||||
announcementV2 := announcement.ToV2()
|
announcementV2 := announcement.ToV2()
|
||||||
|
|
|
@ -87,13 +87,13 @@ func NewContainerFromV2(c *container.Container) *Container {
|
||||||
|
|
||||||
// CalculateID calculates container identifier
|
// CalculateID calculates container identifier
|
||||||
// based on its structure.
|
// based on its structure.
|
||||||
func CalculateID(c *Container) *cid.ID {
|
func CalculateID(c *Container) cid.ID {
|
||||||
data, err := c.ToV2().StableMarshal(nil)
|
data, err := c.ToV2().StableMarshal(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
id := cid.New()
|
var id cid.ID
|
||||||
id.SetSHA256(sha256.Sum256(data))
|
id.SetSHA256(sha256.Sum256(data))
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
|
8
container/id/doc.go
Normal file
8
container/id/doc.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
Package cid provides primitives to work with container identification in NeoFS.
|
||||||
|
|
||||||
|
Using package types in an application is recommended to potentially work with
|
||||||
|
different protocol versions with which these types are compatible.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package cid
|
|
@ -1,90 +1,120 @@
|
||||||
package cid
|
package cid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"errors"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mr-tron/base58"
|
"github.com/mr-tron/base58"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ID represents v2-compatible container identifier.
|
// ID represents NeoFS container identifier.
|
||||||
type ID refs.ContainerID
|
|
||||||
|
|
||||||
// NewFromV2 wraps v2 ContainerID message to ID.
|
|
||||||
//
|
//
|
||||||
// Nil refs.ContainerID converts to nil.
|
// ID is mutually compatible with github.com/nspcc-dev/neofs-api-go/v2/refs.ContainerID
|
||||||
func NewFromV2(idV2 *refs.ContainerID) *ID {
|
// message. See ReadFromV2 / WriteToV2 methods.
|
||||||
return (*ID)(idV2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates and initializes blank ID.
|
|
||||||
//
|
//
|
||||||
// Defaults:
|
// Instances can be created using built-in var declaration.
|
||||||
// - value: nil.
|
|
||||||
func New() *ID {
|
|
||||||
return NewFromV2(new(refs.ContainerID))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetSHA256 sets container identifier value to SHA256 checksum of container body.
|
|
||||||
func (id *ID) SetSHA256(v [sha256.Size]byte) {
|
|
||||||
(*refs.ContainerID)(id).SetValue(v[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToV2 returns the v2 container ID message.
|
|
||||||
//
|
//
|
||||||
// Nil ID converts to nil.
|
// Note that direct typecast is not safe and may result in loss of compatibility:
|
||||||
func (id *ID) ToV2() *refs.ContainerID {
|
// _ = ID([32]byte) // not recommended
|
||||||
return (*refs.ContainerID)(id)
|
type ID [sha256.Size]byte
|
||||||
}
|
|
||||||
|
|
||||||
// Equal returns true if identifiers are identical.
|
// ReadFromV2 reads ID from the refs.ContainerID message.
|
||||||
func (id *ID) Equal(id2 *ID) bool {
|
// Returns an error if the message is malformed according
|
||||||
return bytes.Equal(
|
// to the NeoFS API V2 protocol.
|
||||||
(*refs.ContainerID)(id).GetValue(),
|
|
||||||
(*refs.ContainerID)(id2).GetValue(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse parses string representation of ID.
|
|
||||||
//
|
//
|
||||||
// Returns error if s is not a base58 encoded
|
// See also WriteToV2.
|
||||||
// ID data.
|
func (id *ID) ReadFromV2(m refs.ContainerID) error {
|
||||||
func (id *ID) Parse(s string) error {
|
return id.Decode(m.GetValue())
|
||||||
data, err := base58.Decode(s)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if len(data) != sha256.Size {
|
|
||||||
return errors.New("incorrect format of the string container ID")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(*refs.ContainerID)(id).SetValue(data)
|
// WriteToV2 writes ID to the refs.ContainerID message.
|
||||||
|
// The message must not be nil.
|
||||||
|
//
|
||||||
|
// See also ReadFromV2.
|
||||||
|
func (id ID) WriteToV2(m *refs.ContainerID) {
|
||||||
|
m.SetValue(id[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode encodes ID into 32 bytes of dst. Panics if
|
||||||
|
// dst length is less than 32.
|
||||||
|
//
|
||||||
|
// Zero ID is all zeros.
|
||||||
|
//
|
||||||
|
// See also Decode.
|
||||||
|
func (id ID) Encode(dst []byte) {
|
||||||
|
if l := len(dst); l < sha256.Size {
|
||||||
|
panic(fmt.Sprintf("destination length is less than %d bytes: %d", sha256.Size, l))
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(dst, id[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes src bytes into ID.
|
||||||
|
//
|
||||||
|
// Decode expects that src has 32 bytes length. If the input is malformed,
|
||||||
|
// Decode returns an error describing format violation. In this case ID
|
||||||
|
// remains unchanged.
|
||||||
|
//
|
||||||
|
// Decode doesn't mutate src.
|
||||||
|
//
|
||||||
|
// See also Encode.
|
||||||
|
func (id *ID) Decode(src []byte) error {
|
||||||
|
if len(src) != sha256.Size {
|
||||||
|
return fmt.Errorf("invalid length %d", len(src))
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(id[:], src)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns base58 string representation of ID.
|
// SetSHA256 sets container identifier value to SHA256 checksum of container structure.
|
||||||
func (id *ID) String() string {
|
func (id *ID) SetSHA256(v [sha256.Size]byte) {
|
||||||
return base58.Encode((*refs.ContainerID)(id).GetValue())
|
copy(id[:], v[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal marshals ID into a protobuf binary form.
|
// Equals defines a comparison relation between two ID instances.
|
||||||
func (id *ID) Marshal() ([]byte, error) {
|
//
|
||||||
return (*refs.ContainerID)(id).StableMarshal(nil)
|
// Note that comparison using '==' operator is not recommended since it MAY result
|
||||||
|
// in loss of compatibility.
|
||||||
|
func (id ID) Equals(id2 ID) bool {
|
||||||
|
return id == id2
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal unmarshals protobuf binary representation of ID.
|
// EncodeToString encodes ID into NeoFS API protocol string.
|
||||||
func (id *ID) Unmarshal(data []byte) error {
|
//
|
||||||
return (*refs.ContainerID)(id).Unmarshal(data)
|
// Zero ID is base58 encoding of 32 zeros.
|
||||||
|
//
|
||||||
|
// See also DecodeString.
|
||||||
|
func (id ID) EncodeToString() string {
|
||||||
|
return base58.Encode(id[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON encodes ID to protobuf JSON format.
|
// DecodeString decodes string into ID according to NeoFS API protocol. Returns
|
||||||
func (id *ID) MarshalJSON() ([]byte, error) {
|
// an error if s is malformed.
|
||||||
return (*refs.ContainerID)(id).MarshalJSON()
|
//
|
||||||
|
// See also DecodeString.
|
||||||
|
func (id *ID) DecodeString(s string) error {
|
||||||
|
data, err := base58.Decode(s)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("decode base58: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON decodes ID from protobuf JSON format.
|
return id.Decode(data)
|
||||||
func (id *ID) UnmarshalJSON(data []byte) error {
|
}
|
||||||
return (*refs.ContainerID)(id).UnmarshalJSON(data)
|
|
||||||
|
// String implements fmt.Stringer.
|
||||||
|
//
|
||||||
|
// String is designed to be human-readable, and its format MAY differ between
|
||||||
|
// SDK versions. String MAY return same result as EncodeToString. String MUST NOT
|
||||||
|
// be used to encode ID into NeoFS protocol string.
|
||||||
|
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{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mr-tron/base58"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
||||||
|
@ -16,30 +17,32 @@ func randSHA256Checksum() (cs [sha256.Size]byte) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emptyID = "11111111111111111111111111111111"
|
||||||
|
|
||||||
func TestID_ToV2(t *testing.T) {
|
func TestID_ToV2(t *testing.T) {
|
||||||
t.Run("non-nil", func(t *testing.T) {
|
t.Run("non-zero", func(t *testing.T) {
|
||||||
checksum := randSHA256Checksum()
|
checksum := randSHA256Checksum()
|
||||||
|
|
||||||
id := cidtest.IDWithChecksum(checksum)
|
id := cidtest.IDWithChecksum(checksum)
|
||||||
|
|
||||||
idV2 := id.ToV2()
|
var idV2 refs.ContainerID
|
||||||
|
id.WriteToV2(&idV2)
|
||||||
|
|
||||||
require.Equal(t, id, cid.NewFromV2(idV2))
|
var newID cid.ID
|
||||||
|
require.NoError(t, newID.ReadFromV2(idV2))
|
||||||
|
|
||||||
|
require.Equal(t, id, newID)
|
||||||
require.Equal(t, checksum[:], idV2.GetValue())
|
require.Equal(t, checksum[:], idV2.GetValue())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("nil", func(t *testing.T) {
|
t.Run("zero", func(t *testing.T) {
|
||||||
var x *cid.ID
|
var (
|
||||||
|
x cid.ID
|
||||||
|
v2 refs.ContainerID
|
||||||
|
)
|
||||||
|
|
||||||
require.Nil(t, x.ToV2())
|
x.WriteToV2(&v2)
|
||||||
})
|
require.Equal(t, emptyID, base58.Encode(v2.GetValue()))
|
||||||
|
|
||||||
t.Run("default values", func(t *testing.T) {
|
|
||||||
id := cid.New()
|
|
||||||
|
|
||||||
// convert to v2 message
|
|
||||||
cidV2 := id.ToV2()
|
|
||||||
require.Nil(t, cidV2.GetValue())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,57 +52,57 @@ func TestID_Equal(t *testing.T) {
|
||||||
id1 := cidtest.IDWithChecksum(cs)
|
id1 := cidtest.IDWithChecksum(cs)
|
||||||
id2 := cidtest.IDWithChecksum(cs)
|
id2 := cidtest.IDWithChecksum(cs)
|
||||||
|
|
||||||
require.True(t, id1.Equal(id2))
|
require.True(t, id1.Equals(id2))
|
||||||
|
|
||||||
id3 := cidtest.ID()
|
id3 := cidtest.ID()
|
||||||
|
|
||||||
require.False(t, id1.Equal(id3))
|
require.False(t, id1.Equals(id3))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestID_String(t *testing.T) {
|
func TestID_String(t *testing.T) {
|
||||||
t.Run("Parse/String", func(t *testing.T) {
|
t.Run("DecodeString/EncodeToString", func(t *testing.T) {
|
||||||
id := cidtest.ID()
|
id := cidtest.ID()
|
||||||
id2 := cid.New()
|
var id2 cid.ID
|
||||||
|
|
||||||
require.NoError(t, id2.Parse(id.String()))
|
require.NoError(t, id2.DecodeString(id.String()))
|
||||||
require.Equal(t, id, id2)
|
require.Equal(t, id, id2)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("nil", func(t *testing.T) {
|
t.Run("zero", func(t *testing.T) {
|
||||||
id := cid.New()
|
var id cid.ID
|
||||||
|
|
||||||
require.Empty(t, id.String())
|
require.Equal(t, emptyID, id.EncodeToString())
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContainerIDEncoding(t *testing.T) {
|
|
||||||
id := cidtest.ID()
|
|
||||||
|
|
||||||
t.Run("binary", func(t *testing.T) {
|
|
||||||
data, err := id.Marshal()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
id2 := cid.New()
|
|
||||||
require.NoError(t, id2.Unmarshal(data))
|
|
||||||
|
|
||||||
require.Equal(t, id, id2)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("json", func(t *testing.T) {
|
|
||||||
data, err := id.MarshalJSON()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
a2 := cid.New()
|
|
||||||
require.NoError(t, a2.UnmarshalJSON(data))
|
|
||||||
|
|
||||||
require.Equal(t, id, a2)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewFromV2(t *testing.T) {
|
func TestNewFromV2(t *testing.T) {
|
||||||
t.Run("from nil", func(t *testing.T) {
|
t.Run("from zero", func(t *testing.T) {
|
||||||
var x *refs.ContainerID
|
var (
|
||||||
|
x cid.ID
|
||||||
|
v2 refs.ContainerID
|
||||||
|
)
|
||||||
|
|
||||||
require.Nil(t, cid.NewFromV2(x))
|
require.Error(t, x.ReadFromV2(v2))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestID_Encode(t *testing.T) {
|
||||||
|
var id cid.ID
|
||||||
|
|
||||||
|
t.Run("panic", func(t *testing.T) {
|
||||||
|
dst := make([]byte, sha256.Size-1)
|
||||||
|
|
||||||
|
require.Panics(t, func() {
|
||||||
|
id.Encode(dst)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("correct", func(t *testing.T) {
|
||||||
|
dst := make([]byte, sha256.Size)
|
||||||
|
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
id.Encode(dst)
|
||||||
|
})
|
||||||
|
require.Equal(t, emptyID, id.EncodeToString())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
13
container/id/test/doc.go
Normal file
13
container/id/test/doc.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
Package cidtest provides functions for convenient testing of cid package API.
|
||||||
|
|
||||||
|
Note that importing the package into source files is highly discouraged.
|
||||||
|
|
||||||
|
Random instance generation functions can be useful when testing expects any value, e.g.:
|
||||||
|
import cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
||||||
|
|
||||||
|
cid := cidtest.ID()
|
||||||
|
// test the value
|
||||||
|
|
||||||
|
*/
|
||||||
|
package cidtest
|
|
@ -8,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ID returns random cid.ID.
|
// ID returns random cid.ID.
|
||||||
func ID() *cid.ID {
|
func ID() cid.ID {
|
||||||
checksum := [sha256.Size]byte{}
|
checksum := [sha256.Size]byte{}
|
||||||
|
|
||||||
rand.Read(checksum[:])
|
rand.Read(checksum[:])
|
||||||
|
@ -18,8 +18,8 @@ func ID() *cid.ID {
|
||||||
|
|
||||||
// IDWithChecksum returns cid.ID initialized
|
// IDWithChecksum returns cid.ID initialized
|
||||||
// with specified checksum.
|
// with specified checksum.
|
||||||
func IDWithChecksum(cs [sha256.Size]byte) *cid.ID {
|
func IDWithChecksum(cs [sha256.Size]byte) cid.ID {
|
||||||
id := cid.New()
|
var id cid.ID
|
||||||
id.SetSHA256(cs)
|
id.SetSHA256(cs)
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
|
|
@ -112,12 +112,12 @@ func (r *Record) AddObjectVersionFilter(m Match, v *version.Version) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddObjectIDFilter adds filter by object ID.
|
// AddObjectIDFilter adds filter by object ID.
|
||||||
func (r *Record) AddObjectIDFilter(m Match, id *oid.ID) {
|
func (r *Record) AddObjectIDFilter(m Match, id oid.ID) {
|
||||||
r.addObjectReservedFilter(m, fKeyObjID, id)
|
r.addObjectReservedFilter(m, fKeyObjID, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddObjectContainerIDFilter adds filter by object container ID.
|
// AddObjectContainerIDFilter adds filter by object container ID.
|
||||||
func (r *Record) AddObjectContainerIDFilter(m Match, id *cid.ID) {
|
func (r *Record) AddObjectContainerIDFilter(m Match, id cid.ID) {
|
||||||
r.addObjectReservedFilter(m, fKeyObjContainerID, id)
|
r.addObjectReservedFilter(m, fKeyObjContainerID, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,19 +16,19 @@ import (
|
||||||
// Table is compatible with v2 acl.EACLTable message.
|
// Table is compatible with v2 acl.EACLTable message.
|
||||||
type Table struct {
|
type Table struct {
|
||||||
version version.Version
|
version version.Version
|
||||||
cid *cid.ID
|
cid cid.ID
|
||||||
token *session.Token
|
token *session.Token
|
||||||
sig *signature.Signature
|
sig *signature.Signature
|
||||||
records []Record
|
records []Record
|
||||||
}
|
}
|
||||||
|
|
||||||
// CID returns identifier of the container that should use given access control rules.
|
// CID returns identifier of the container that should use given access control rules.
|
||||||
func (t Table) CID() *cid.ID {
|
func (t Table) CID() cid.ID {
|
||||||
return t.cid
|
return t.cid
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCID sets identifier of the container that should use given access control rules.
|
// SetCID sets identifier of the container that should use given access control rules.
|
||||||
func (t *Table) SetCID(cid *cid.ID) {
|
func (t *Table) SetCID(cid cid.ID) {
|
||||||
t.cid = cid
|
t.cid = cid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +85,11 @@ func (t *Table) ToV2() *v2acl.Table {
|
||||||
}
|
}
|
||||||
|
|
||||||
v2 := new(v2acl.Table)
|
v2 := new(v2acl.Table)
|
||||||
|
var cidV2 refs.ContainerID
|
||||||
|
|
||||||
if t.cid != nil {
|
if !t.cid.Empty() {
|
||||||
v2.SetContainerID(t.cid.ToV2())
|
t.cid.WriteToV2(&cidV2)
|
||||||
|
v2.SetContainerID(&cidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.records != nil {
|
if t.records != nil {
|
||||||
|
@ -124,7 +126,7 @@ func NewTable() *Table {
|
||||||
// CreateTable creates, initializes with parameters and returns Table instance.
|
// CreateTable creates, initializes with parameters and returns Table instance.
|
||||||
func CreateTable(cid cid.ID) *Table {
|
func CreateTable(cid cid.ID) *Table {
|
||||||
t := NewTable()
|
t := NewTable()
|
||||||
t.SetCID(&cid)
|
t.SetCID(cid)
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
@ -148,8 +150,8 @@ func NewTableFromV2(table *v2acl.Table) *Table {
|
||||||
|
|
||||||
// set container id
|
// set container id
|
||||||
if id := table.GetContainerID(); id != nil {
|
if id := table.GetContainerID(); id != nil {
|
||||||
if t.cid == nil {
|
if t.cid.Empty() {
|
||||||
t.cid = new(cid.ID)
|
t.cid = cid.ID{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var h [sha256.Size]byte
|
var h [sha256.Size]byte
|
||||||
|
@ -205,7 +207,7 @@ func (t *Table) UnmarshalJSON(data []byte) error {
|
||||||
|
|
||||||
// EqualTables compares Table with each other.
|
// EqualTables compares Table with each other.
|
||||||
func EqualTables(t1, t2 Table) bool {
|
func EqualTables(t1, t2 Table) bool {
|
||||||
if !t1.CID().Equal(t2.CID()) ||
|
if !t1.CID().Equals(t2.CID()) ||
|
||||||
!t1.Version().Equal(t2.Version()) {
|
!t1.Version().Equal(t2.Version()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ func TestTable(t *testing.T) {
|
||||||
t.Run("create table", func(t *testing.T) {
|
t.Run("create table", func(t *testing.T) {
|
||||||
id := cidtest.ID()
|
id := cidtest.ID()
|
||||||
|
|
||||||
table := eacl.CreateTable(*id)
|
table := eacl.CreateTable(id)
|
||||||
require.Equal(t, id, table.CID())
|
require.Equal(t, id, table.CID())
|
||||||
require.Equal(t, version.Current(), table.Version())
|
require.Equal(t, version.Current(), table.Version())
|
||||||
})
|
})
|
||||||
|
@ -124,7 +124,7 @@ func TestTable_ToV2(t *testing.T) {
|
||||||
// check initial values
|
// check initial values
|
||||||
require.Equal(t, version.Current(), table.Version())
|
require.Equal(t, version.Current(), table.Version())
|
||||||
require.Nil(t, table.Records())
|
require.Nil(t, table.Records())
|
||||||
require.Nil(t, table.CID())
|
require.True(t, table.CID().Empty())
|
||||||
require.Nil(t, table.SessionToken())
|
require.Nil(t, table.SessionToken())
|
||||||
require.Nil(t, table.Signature())
|
require.Nil(t, table.Signature())
|
||||||
|
|
||||||
|
|
14
ns/dns.go
14
ns/dns.go
|
@ -16,20 +16,20 @@ type DNS struct{}
|
||||||
// Otherwise, returns an error.
|
// Otherwise, returns an error.
|
||||||
//
|
//
|
||||||
// See also net.LookupTXT.
|
// See also net.LookupTXT.
|
||||||
func (x *DNS) ResolveContainerName(name string) (*cid.ID, error) {
|
func (x *DNS) ResolveContainerName(name string) (id cid.ID, err error) {
|
||||||
records, err := net.LookupTXT(name)
|
records, err := net.LookupTXT(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var id cid.ID
|
|
||||||
|
|
||||||
for i := range records {
|
for i := range records {
|
||||||
err = id.Parse(records[i])
|
err = id.DecodeString(records[i])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return &id, nil
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errNotFound
|
err = errNotFound
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
20
ns/nns.go
20
ns/nns.go
|
@ -114,7 +114,7 @@ func (n *NNS) Dial(address string) error {
|
||||||
// ResolveContainerName MUST NOT be called before successful Dial.
|
// ResolveContainerName MUST NOT be called before successful Dial.
|
||||||
//
|
//
|
||||||
// See also https://docs.neo.org/docs/en-us/reference/nns.html.
|
// See also https://docs.neo.org/docs/en-us/reference/nns.html.
|
||||||
func (n *NNS) ResolveContainerName(name string) (*cid.ID, error) {
|
func (n *NNS) ResolveContainerName(name string) (cid.ID, error) {
|
||||||
res, err := n.neoClient.call(n.nnsContract, "resolve", []smartcontract.Parameter{
|
res, err := n.neoClient.call(n.nnsContract, "resolve", []smartcontract.Parameter{
|
||||||
{
|
{
|
||||||
Type: smartcontract.StringType,
|
Type: smartcontract.StringType,
|
||||||
|
@ -126,25 +126,25 @@ func (n *NNS) ResolveContainerName(name string) (*cid.ID, error) {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invoke NNS contract: %w", err)
|
return cid.ID{}, fmt.Errorf("invoke NNS contract: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if res.State != vm.HaltState.String() {
|
if res.State != vm.HaltState.String() {
|
||||||
return nil, fmt.Errorf("NNS contract fault exception: %s", res.FaultException)
|
return cid.ID{}, fmt.Errorf("NNS contract fault exception: %s", res.FaultException)
|
||||||
} else if len(res.Stack) == 0 {
|
} else if len(res.Stack) == 0 {
|
||||||
return nil, errors.New("empty stack in invocation result")
|
return cid.ID{}, errors.New("empty stack in invocation result")
|
||||||
}
|
}
|
||||||
|
|
||||||
itemArr, err := res.Stack[len(res.Stack)-1].Convert(stackitem.ArrayT) // top stack element is last in the array
|
itemArr, err := res.Stack[len(res.Stack)-1].Convert(stackitem.ArrayT) // top stack element is last in the array
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("convert stack item to %s", stackitem.ArrayT)
|
return cid.ID{}, fmt.Errorf("convert stack item to %s", stackitem.ArrayT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := itemArr.(stackitem.Null); !ok {
|
if _, ok := itemArr.(stackitem.Null); !ok {
|
||||||
arr, ok := itemArr.Value().([]stackitem.Item)
|
arr, ok := itemArr.Value().([]stackitem.Item)
|
||||||
if !ok {
|
if !ok {
|
||||||
// unexpected for types from stackitem package
|
// unexpected for types from stackitem package
|
||||||
return nil, errors.New("invalid cast to stack item slice")
|
return cid.ID{}, errors.New("invalid cast to stack item slice")
|
||||||
}
|
}
|
||||||
|
|
||||||
var id cid.ID
|
var id cid.ID
|
||||||
|
@ -152,15 +152,15 @@ func (n *NNS) ResolveContainerName(name string) (*cid.ID, error) {
|
||||||
for i := range arr {
|
for i := range arr {
|
||||||
bs, err := arr[i].TryBytes()
|
bs, err := arr[i].TryBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("convert array item to byte slice: %w", err)
|
return cid.ID{}, fmt.Errorf("convert array item to byte slice: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = id.Parse(string(bs))
|
err = id.DecodeString(string(bs))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return &id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errNotFound
|
return cid.ID{}, errNotFound
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,41 +45,61 @@ func (a *Address) ToV2() *refs.Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerID returns container identifier.
|
// ContainerID returns container identifier.
|
||||||
func (a *Address) ContainerID() *cid.ID {
|
func (a *Address) ContainerID() (v cid.ID) {
|
||||||
return cid.NewFromV2(
|
var cID cid.ID
|
||||||
(*refs.Address)(a).GetContainerID())
|
v2 := (*refs.Address)(a)
|
||||||
|
|
||||||
|
cidV2 := v2.GetContainerID()
|
||||||
|
if cidV2 != nil {
|
||||||
|
_ = cID.ReadFromV2(*cidV2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cID
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetContainerID sets container identifier.
|
// SetContainerID sets container identifier.
|
||||||
func (a *Address) SetContainerID(id *cid.ID) {
|
func (a *Address) SetContainerID(id cid.ID) {
|
||||||
(*refs.Address)(a).SetContainerID(id.ToV2())
|
var cidV2 refs.ContainerID
|
||||||
|
id.WriteToV2(&cidV2)
|
||||||
|
|
||||||
|
(*refs.Address)(a).SetContainerID(&cidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectID returns object identifier.
|
// ObjectID returns object identifier.
|
||||||
func (a *Address) ObjectID() *oid.ID {
|
func (a *Address) ObjectID() (v oid.ID) {
|
||||||
return oid.NewIDFromV2(
|
var id oid.ID
|
||||||
(*refs.Address)(a).GetObjectID())
|
v2 := (*refs.Address)(a)
|
||||||
|
|
||||||
|
oidV2 := v2.GetObjectID()
|
||||||
|
if oidV2 != nil {
|
||||||
|
_ = id.ReadFromV2(*oidV2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetObjectID sets object identifier.
|
// SetObjectID sets object identifier.
|
||||||
func (a *Address) SetObjectID(id *oid.ID) {
|
func (a *Address) SetObjectID(id oid.ID) {
|
||||||
(*refs.Address)(a).SetObjectID(id.ToV2())
|
var oidV2 refs.ObjectID
|
||||||
|
id.WriteToV2(&oidV2)
|
||||||
|
|
||||||
|
(*refs.Address)(a).SetObjectID(&oidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse converts base58 string representation into Address.
|
// Parse converts base58 string representation into Address.
|
||||||
func (a *Address) Parse(s string) error {
|
func (a *Address) Parse(s string) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
oid = oid.NewID()
|
oid oid.ID
|
||||||
id = cid.New()
|
id cid.ID
|
||||||
parts = strings.Split(s, addressSeparator)
|
parts = strings.Split(s, addressSeparator)
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(parts) != addressParts {
|
if len(parts) != addressParts {
|
||||||
return errInvalidAddressString
|
return errInvalidAddressString
|
||||||
} else if err = id.Parse(parts[0]); err != nil {
|
} else if err = id.DecodeString(parts[0]); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err = oid.Parse(parts[1]); err != nil {
|
} else if err = oid.DecodeString(parts[1]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,8 +107,8 @@ func TestNewAddress(t *testing.T) {
|
||||||
a := NewAddress()
|
a := NewAddress()
|
||||||
|
|
||||||
// check initial values
|
// check initial values
|
||||||
require.Nil(t, a.ContainerID())
|
require.True(t, a.ContainerID().Empty())
|
||||||
require.Nil(t, a.ObjectID())
|
require.True(t, a.ObjectID().Empty())
|
||||||
|
|
||||||
// convert to v2 message
|
// convert to v2 message
|
||||||
aV2 := a.ToV2()
|
aV2 := a.ToV2()
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
signatureV2 "github.com/nspcc-dev/neofs-api-go/v2/signature"
|
signatureV2 "github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/checksum"
|
"github.com/nspcc-dev/neofs-sdk-go/checksum"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/signature"
|
|
||||||
sigutil "github.com/nspcc-dev/neofs-sdk-go/util/signature"
|
sigutil "github.com/nspcc-dev/neofs-sdk-go/util/signature"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,13 +55,13 @@ func VerifyPayloadChecksum(obj *Object) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalculateID calculates identifier for the object.
|
// CalculateID calculates identifier for the object.
|
||||||
func CalculateID(obj *Object) (*oid.ID, error) {
|
func CalculateID(obj *Object) (oid.ID, error) {
|
||||||
data, err := obj.ToV2().GetHeader().StableMarshal(nil)
|
data, err := obj.ToV2().GetHeader().StableMarshal(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return oid.ID{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id := oid.NewID()
|
var id oid.ID
|
||||||
id.SetSHA256(sha256.Sum256(data))
|
id.SetSHA256(sha256.Sum256(data))
|
||||||
|
|
||||||
return id, nil
|
return id, nil
|
||||||
|
@ -88,43 +88,45 @@ func VerifyID(obj *Object) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !id.Equal(obj.ID()) {
|
if !id.Equals(obj.ID()) {
|
||||||
return errIncorrectID
|
return errIncorrectID
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CalculateIDSignature(key *ecdsa.PrivateKey, id *oid.ID) (*signature.Signature, error) {
|
// CalculateAndSetSignature signs id with provided key and sets that signature to
|
||||||
return sigutil.SignData(
|
// the object.
|
||||||
key,
|
func CalculateAndSetSignature(key ecdsa.PrivateKey, obj *Object) error {
|
||||||
signatureV2.StableMarshalerWrapper{
|
sig, err := obj.ID().CalculateIDSignature(key)
|
||||||
SM: id.ToV2(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func CalculateAndSetSignature(key *ecdsa.PrivateKey, obj *Object) error {
|
|
||||||
sig, err := CalculateIDSignature(key, obj.ID())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.SetSignature(sig)
|
obj.SetSignature(&sig)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyIDSignature(obj *Object) error {
|
// VerifyIDSignature verifies object ID signature.
|
||||||
return sigutil.VerifyData(
|
func (o *Object) VerifyIDSignature() bool {
|
||||||
|
var idV2 refs.ObjectID
|
||||||
|
o.ID().WriteToV2(&idV2)
|
||||||
|
|
||||||
|
sig := o.Signature()
|
||||||
|
|
||||||
|
err := sigutil.VerifyData(
|
||||||
signatureV2.StableMarshalerWrapper{
|
signatureV2.StableMarshalerWrapper{
|
||||||
SM: obj.ID().ToV2(),
|
SM: &idV2,
|
||||||
},
|
},
|
||||||
obj.Signature(),
|
sig,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetIDWithSignature sets object identifier and signature.
|
// SetIDWithSignature sets object identifier and signature.
|
||||||
func SetIDWithSignature(key *ecdsa.PrivateKey, obj *Object) error {
|
func SetIDWithSignature(key ecdsa.PrivateKey, obj *Object) error {
|
||||||
if err := CalculateAndSetID(obj); err != nil {
|
if err := CalculateAndSetID(obj); err != nil {
|
||||||
return fmt.Errorf("could not set identifier: %w", err)
|
return fmt.Errorf("could not set identifier: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -137,7 +139,7 @@ func SetIDWithSignature(key *ecdsa.PrivateKey, obj *Object) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVerificationFields calculates and sets all verification fields of the object.
|
// SetVerificationFields calculates and sets all verification fields of the object.
|
||||||
func SetVerificationFields(key *ecdsa.PrivateKey, obj *Object) error {
|
func SetVerificationFields(key ecdsa.PrivateKey, obj *Object) error {
|
||||||
CalculateAndSetPayloadChecksum(obj)
|
CalculateAndSetPayloadChecksum(obj)
|
||||||
|
|
||||||
return SetIDWithSignature(key, obj)
|
return SetIDWithSignature(key, obj)
|
||||||
|
@ -156,10 +158,12 @@ func CheckVerificationFields(obj *Object) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errInvalidSignature = errors.New("invalid signature")
|
||||||
|
|
||||||
// CheckHeaderVerificationFields checks all verification fields except payload.
|
// CheckHeaderVerificationFields checks all verification fields except payload.
|
||||||
func CheckHeaderVerificationFields(obj *Object) error {
|
func CheckHeaderVerificationFields(obj *Object) error {
|
||||||
if err := VerifyIDSignature(obj); err != nil {
|
if !obj.VerifyIDSignature() {
|
||||||
return fmt.Errorf("invalid signature: %w", err)
|
return errInvalidSignature
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := VerifyID(obj); err != nil {
|
if err := VerifyID(obj); err != nil {
|
||||||
|
|
|
@ -19,7 +19,7 @@ func TestVerificationFields(t *testing.T) {
|
||||||
|
|
||||||
p, err := keys.NewPrivateKey()
|
p, err := keys.NewPrivateKey()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, SetVerificationFields(&p.PrivateKey, obj))
|
require.NoError(t, SetVerificationFields(p.PrivateKey, obj))
|
||||||
|
|
||||||
require.NoError(t, CheckVerificationFields(obj))
|
require.NoError(t, CheckVerificationFields(obj))
|
||||||
|
|
||||||
|
@ -45,10 +45,10 @@ func TestVerificationFields(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
corrupt: func() {
|
corrupt: func() {
|
||||||
obj.ID().ToV2().GetValue()[0]++
|
obj.ToV2().GetObjectID().GetValue()[0]++
|
||||||
},
|
},
|
||||||
restore: func() {
|
restore: func() {
|
||||||
obj.ID().ToV2().GetValue()[0]--
|
obj.ToV2().GetObjectID().GetValue()[0]--
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
8
object/id/doc.go
Normal file
8
object/id/doc.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
Package oid provides primitives to work with object identification in NeoFS.
|
||||||
|
|
||||||
|
Using package types in an application is recommended to potentially work with
|
||||||
|
different protocol versions with which these types are compatible.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package oid
|
193
object/id/id.go
193
object/id/id.go
|
@ -1,92 +1,177 @@
|
||||||
package oid
|
package oid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"crypto/ecdsa"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mr-tron/base58"
|
"github.com/mr-tron/base58"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
|
signatureV2 "github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/signature"
|
||||||
|
sigutil "github.com/nspcc-dev/neofs-sdk-go/util/signature"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ID represents v2-compatible object identifier.
|
// ID represents NeoFS object identifier in a container.
|
||||||
type ID refs.ObjectID
|
|
||||||
|
|
||||||
var errInvalidIDString = errors.New("incorrect format of the string object ID")
|
|
||||||
|
|
||||||
// NewIDFromV2 wraps v2 ObjectID message to ID.
|
|
||||||
//
|
//
|
||||||
// Nil refs.ObjectID converts to nil.
|
// ID is mutually compatible with github.com/nspcc-dev/neofs-api-go/v2/refs.ObjectID
|
||||||
func NewIDFromV2(idV2 *refs.ObjectID) *ID {
|
// message. See ReadFromV2 / WriteToV2 methods.
|
||||||
return (*ID)(idV2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewID creates and initializes blank ID.
|
|
||||||
//
|
//
|
||||||
// Works similar as NewIDFromV2(new(ObjectID)).
|
// Instances can be created using built-in var declaration.
|
||||||
//
|
//
|
||||||
// Defaults:
|
// Note that direct typecast is not safe and may result in loss of compatibility:
|
||||||
// - value: nil.
|
// _ = ObjectID([32]byte{}) // not recommended
|
||||||
func NewID() *ID {
|
type ID [sha256.Size]byte
|
||||||
return NewIDFromV2(new(refs.ObjectID))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetSHA256 sets object identifier value to SHA256 checksum.
|
// ReadFromV2 reads ID from the refs.ObjectID message. Returns an error if
|
||||||
func (id *ID) SetSHA256(v [sha256.Size]byte) {
|
// the message is malformed according to the NeoFS API V2 protocol.
|
||||||
(*refs.ObjectID)(id).SetValue(v[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equal returns true if identifiers are identical.
|
|
||||||
func (id *ID) Equal(id2 *ID) bool {
|
|
||||||
return bytes.Equal(
|
|
||||||
(*refs.ObjectID)(id).GetValue(),
|
|
||||||
(*refs.ObjectID)(id2).GetValue(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToV2 converts ID to v2 ObjectID message.
|
|
||||||
//
|
//
|
||||||
// Nil ID converts to nil.
|
// See also WriteToV2.
|
||||||
func (id *ID) ToV2() *refs.ObjectID {
|
func (id *ID) ReadFromV2(m refs.ObjectID) error {
|
||||||
return (*refs.ObjectID)(id)
|
return id.Decode(m.GetValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse converts base58 string representation into ID.
|
// WriteToV2 writes ID to the refs.ObjectID message.
|
||||||
func (id *ID) Parse(s string) error {
|
// The message must not be nil.
|
||||||
data, err := base58.Decode(s)
|
//
|
||||||
if err != nil {
|
// See also ReadFromV2.
|
||||||
return fmt.Errorf("could not parse object.ID from string: %w", err)
|
func (id ID) WriteToV2(m *refs.ObjectID) {
|
||||||
} else if len(data) != sha256.Size {
|
m.SetValue(id[:])
|
||||||
return errInvalidIDString
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(*refs.ObjectID)(id).SetValue(data)
|
// Encode encodes ID into 32 bytes of dst. Panics if
|
||||||
|
// dst length is less than 32.
|
||||||
|
//
|
||||||
|
// Zero ID is all zeros.
|
||||||
|
//
|
||||||
|
// See also Decode.
|
||||||
|
func (id ID) Encode(dst []byte) {
|
||||||
|
if l := len(dst); l < sha256.Size {
|
||||||
|
panic(fmt.Sprintf("destination length is less than %d bytes: %d", sha256.Size, l))
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(dst, id[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes src bytes into ID.
|
||||||
|
//
|
||||||
|
// Decode expects that src has 32 bytes length. If the input is malformed,
|
||||||
|
// Decode returns an error describing format violation. In this case ID
|
||||||
|
// remains unchanged.
|
||||||
|
//
|
||||||
|
// Decode doesn't mutate src.
|
||||||
|
//
|
||||||
|
// See also Encode.
|
||||||
|
func (id *ID) Decode(src []byte) error {
|
||||||
|
if len(src) != 32 {
|
||||||
|
return fmt.Errorf("invalid length %d", len(src))
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(id[:], src)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns base58 string representation of ID.
|
// SetSHA256 sets object identifier value to SHA256 checksum.
|
||||||
func (id *ID) String() string {
|
func (id *ID) SetSHA256(v [sha256.Size]byte) {
|
||||||
return base58.Encode((*refs.ObjectID)(id).GetValue())
|
copy(id[:], v[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equals defines a comparison relation between two ID instances.
|
||||||
|
//
|
||||||
|
// Note that comparison using '==' operator is not recommended since it MAY result
|
||||||
|
// in loss of compatibility.
|
||||||
|
func (id ID) Equals(id2 ID) bool {
|
||||||
|
return id == id2
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeToString encodes ID into NeoFS API protocol string.
|
||||||
|
//
|
||||||
|
// Zero ID is base58 encoding of 32 zeros.
|
||||||
|
//
|
||||||
|
// See also DecodeString.
|
||||||
|
func (id ID) EncodeToString() string {
|
||||||
|
return base58.Encode(id[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeString decodes string into ID according to NeoFS API protocol. Returns
|
||||||
|
// an error if s is malformed.
|
||||||
|
//
|
||||||
|
// See also DecodeString.
|
||||||
|
func (id *ID) DecodeString(s string) error {
|
||||||
|
data, err := base58.Decode(s)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("decode base58: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return id.Decode(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements fmt.Stringer.
|
||||||
|
//
|
||||||
|
// String is designed to be human-readable, and its format MAY differ between
|
||||||
|
// SDK versions. String MAY return same result as EncodeToString. String MUST NOT
|
||||||
|
// be used to encode ID into NeoFS protocol string.
|
||||||
|
func (id ID) String() string {
|
||||||
|
return id.EncodeToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalculateIDSignature signs object id with provided key.
|
||||||
|
func (id ID) CalculateIDSignature(key ecdsa.PrivateKey) (signature.Signature, error) {
|
||||||
|
var idV2 refs.ObjectID
|
||||||
|
id.WriteToV2(&idV2)
|
||||||
|
|
||||||
|
sign, err := sigutil.SignData(&key,
|
||||||
|
signatureV2.StableMarshalerWrapper{
|
||||||
|
SM: &idV2,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
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.
|
// Marshal marshals ID into a protobuf binary form.
|
||||||
func (id *ID) Marshal() ([]byte, error) {
|
func (id ID) Marshal() ([]byte, error) {
|
||||||
return (*refs.ObjectID)(id).StableMarshal(nil)
|
var v2 refs.ObjectID
|
||||||
|
v2.SetValue(id[:])
|
||||||
|
|
||||||
|
return v2.StableMarshal(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal unmarshals protobuf binary representation of ID.
|
// Unmarshal unmarshals protobuf binary representation of ID.
|
||||||
func (id *ID) Unmarshal(data []byte) error {
|
func (id *ID) Unmarshal(data []byte) error {
|
||||||
return (*refs.ObjectID)(id).Unmarshal(data)
|
var v2 refs.ObjectID
|
||||||
|
if err := v2.Unmarshal(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(id[:], v2.GetValue())
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON encodes ID to protobuf JSON format.
|
// MarshalJSON encodes ID to protobuf JSON format.
|
||||||
func (id *ID) MarshalJSON() ([]byte, error) {
|
func (id ID) MarshalJSON() ([]byte, error) {
|
||||||
return (*refs.ObjectID)(id).MarshalJSON()
|
var v2 refs.ObjectID
|
||||||
|
v2.SetValue(id[:])
|
||||||
|
|
||||||
|
return v2.MarshalJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON decodes ID from protobuf JSON format.
|
// UnmarshalJSON decodes ID from protobuf JSON format.
|
||||||
func (id *ID) UnmarshalJSON(data []byte) error {
|
func (id *ID) UnmarshalJSON(data []byte) error {
|
||||||
return (*refs.ObjectID)(id).UnmarshalJSON(data)
|
var v2 refs.ObjectID
|
||||||
|
if err := v2.UnmarshalJSON(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(id[:], v2.GetValue())
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,10 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func randID(t *testing.T) *ID {
|
const emptyID = "11111111111111111111111111111111"
|
||||||
id := NewID()
|
|
||||||
|
func randID(t *testing.T) ID {
|
||||||
|
var id ID
|
||||||
id.SetSHA256(randSHA256Checksum(t))
|
id.SetSHA256(randSHA256Checksum(t))
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
@ -26,7 +28,7 @@ func randSHA256Checksum(t *testing.T) (cs [sha256.Size]byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIDV2(t *testing.T) {
|
func TestIDV2(t *testing.T) {
|
||||||
id := NewID()
|
var id ID
|
||||||
|
|
||||||
checksum := [sha256.Size]byte{}
|
checksum := [sha256.Size]byte{}
|
||||||
|
|
||||||
|
@ -35,7 +37,8 @@ func TestIDV2(t *testing.T) {
|
||||||
|
|
||||||
id.SetSHA256(checksum)
|
id.SetSHA256(checksum)
|
||||||
|
|
||||||
idV2 := id.ToV2()
|
var idV2 refs.ObjectID
|
||||||
|
id.WriteToV2(&idV2)
|
||||||
|
|
||||||
require.Equal(t, checksum[:], idV2.GetValue())
|
require.Equal(t, checksum[:], idV2.GetValue())
|
||||||
}
|
}
|
||||||
|
@ -43,17 +46,17 @@ func TestIDV2(t *testing.T) {
|
||||||
func TestID_Equal(t *testing.T) {
|
func TestID_Equal(t *testing.T) {
|
||||||
cs := randSHA256Checksum(t)
|
cs := randSHA256Checksum(t)
|
||||||
|
|
||||||
id1 := NewID()
|
var id1 ID
|
||||||
id1.SetSHA256(cs)
|
id1.SetSHA256(cs)
|
||||||
|
|
||||||
id2 := NewID()
|
var id2 ID
|
||||||
id2.SetSHA256(cs)
|
id2.SetSHA256(cs)
|
||||||
|
|
||||||
id3 := NewID()
|
var id3 ID
|
||||||
id3.SetSHA256(randSHA256Checksum(t))
|
id3.SetSHA256(randSHA256Checksum(t))
|
||||||
|
|
||||||
require.True(t, id1.Equal(id2))
|
require.True(t, id1.Equals(id2))
|
||||||
require.False(t, id1.Equal(id3))
|
require.False(t, id1.Equals(id3))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestID_Parse(t *testing.T) {
|
func TestID_Parse(t *testing.T) {
|
||||||
|
@ -62,10 +65,14 @@ func TestID_Parse(t *testing.T) {
|
||||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||||
cs := randSHA256Checksum(t)
|
cs := randSHA256Checksum(t)
|
||||||
str := base58.Encode(cs[:])
|
str := base58.Encode(cs[:])
|
||||||
oid := NewID()
|
var oid ID
|
||||||
|
|
||||||
require.NoError(t, oid.Parse(str))
|
require.NoError(t, oid.DecodeString(str))
|
||||||
require.Equal(t, cs[:], oid.ToV2().GetValue())
|
|
||||||
|
var oidV2 refs.ObjectID
|
||||||
|
oid.WriteToV2(&oidV2)
|
||||||
|
|
||||||
|
require.Equal(t, cs[:], oidV2.GetValue())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -76,18 +83,18 @@ func TestID_Parse(t *testing.T) {
|
||||||
t.Run(strconv.Itoa(j), func(t *testing.T) {
|
t.Run(strconv.Itoa(j), func(t *testing.T) {
|
||||||
cs := []byte{1, 2, 3, 4, 5, byte(j)}
|
cs := []byte{1, 2, 3, 4, 5, byte(j)}
|
||||||
str := base58.Encode(cs)
|
str := base58.Encode(cs)
|
||||||
oid := NewID()
|
var oid ID
|
||||||
|
|
||||||
require.Error(t, oid.Parse(str))
|
require.Error(t, oid.DecodeString(str))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestID_String(t *testing.T) {
|
func TestID_String(t *testing.T) {
|
||||||
t.Run("nil", func(t *testing.T) {
|
t.Run("zero", func(t *testing.T) {
|
||||||
id := NewID()
|
var id ID
|
||||||
require.Empty(t, id.String())
|
require.Equal(t, emptyID, id.EncodeToString())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should be equal", func(t *testing.T) {
|
t.Run("should be equal", func(t *testing.T) {
|
||||||
|
@ -95,9 +102,9 @@ func TestID_String(t *testing.T) {
|
||||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||||
cs := randSHA256Checksum(t)
|
cs := randSHA256Checksum(t)
|
||||||
str := base58.Encode(cs[:])
|
str := base58.Encode(cs[:])
|
||||||
oid := NewID()
|
var oid ID
|
||||||
|
|
||||||
require.NoError(t, oid.Parse(str))
|
require.NoError(t, oid.DecodeString(str))
|
||||||
require.Equal(t, str, oid.String())
|
require.Equal(t, str, oid.String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -111,7 +118,7 @@ func TestObjectIDEncoding(t *testing.T) {
|
||||||
data, err := id.Marshal()
|
data, err := id.Marshal()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
id2 := NewID()
|
var id2 ID
|
||||||
require.NoError(t, id2.Unmarshal(data))
|
require.NoError(t, id2.Unmarshal(data))
|
||||||
|
|
||||||
require.Equal(t, id, id2)
|
require.Equal(t, id, id2)
|
||||||
|
@ -121,36 +128,55 @@ func TestObjectIDEncoding(t *testing.T) {
|
||||||
data, err := id.MarshalJSON()
|
data, err := id.MarshalJSON()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
a2 := NewID()
|
var id2 ID
|
||||||
require.NoError(t, a2.UnmarshalJSON(data))
|
require.NoError(t, id2.UnmarshalJSON(data))
|
||||||
|
|
||||||
require.Equal(t, id, a2)
|
require.Equal(t, id, id2)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewIDFromV2(t *testing.T) {
|
func TestNewIDFromV2(t *testing.T) {
|
||||||
t.Run("from nil", func(t *testing.T) {
|
t.Run("from zero", func(t *testing.T) {
|
||||||
var x *refs.ObjectID
|
var (
|
||||||
|
x ID
|
||||||
|
v2 refs.ObjectID
|
||||||
|
)
|
||||||
|
|
||||||
require.Nil(t, NewIDFromV2(x))
|
require.Error(t, x.ReadFromV2(v2))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestID_ToV2(t *testing.T) {
|
func TestID_ToV2(t *testing.T) {
|
||||||
t.Run("nil", func(t *testing.T) {
|
t.Run("zero to v2", func(t *testing.T) {
|
||||||
var x *ID
|
var (
|
||||||
|
x ID
|
||||||
|
v2 refs.ObjectID
|
||||||
|
)
|
||||||
|
|
||||||
require.Nil(t, x.ToV2())
|
x.WriteToV2(&v2)
|
||||||
|
|
||||||
|
require.Equal(t, sha256.Size, len(v2.GetValue()))
|
||||||
|
require.Equal(t, emptyID, base58.Encode(v2.GetValue()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewID(t *testing.T) {
|
func TestID_Encode(t *testing.T) {
|
||||||
t.Run("default values", func(t *testing.T) {
|
var id ID
|
||||||
id := NewID()
|
|
||||||
|
|
||||||
// convert to v2 message
|
t.Run("panic", func(t *testing.T) {
|
||||||
idV2 := id.ToV2()
|
dst := make([]byte, sha256.Size-1)
|
||||||
|
|
||||||
require.Nil(t, idV2.GetValue())
|
require.Panics(t, func() {
|
||||||
|
id.Encode(dst)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("correct", func(t *testing.T) {
|
||||||
|
dst := make([]byte, sha256.Size)
|
||||||
|
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
id.Encode(dst)
|
||||||
|
})
|
||||||
|
require.Equal(t, emptyID, id.EncodeToString())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
13
object/id/test/doc.go
Normal file
13
object/id/test/doc.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
Package oidtest provides functions for convenient testing of oid package API.
|
||||||
|
|
||||||
|
Note that importing the package into source files is highly discouraged.
|
||||||
|
|
||||||
|
Random instance generation functions can be useful when testing expects any value, e.g.:
|
||||||
|
import oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
|
||||||
|
|
||||||
|
dec := oidtest.ID()
|
||||||
|
// test the value
|
||||||
|
|
||||||
|
*/
|
||||||
|
package oidtest
|
|
@ -1,4 +1,4 @@
|
||||||
package test
|
package oidtest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
@ -8,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ID returns random object.ID.
|
// ID returns random object.ID.
|
||||||
func ID() *oid.ID {
|
func ID() oid.ID {
|
||||||
checksum := [sha256.Size]byte{}
|
checksum := [sha256.Size]byte{}
|
||||||
|
|
||||||
rand.Read(checksum[:])
|
rand.Read(checksum[:])
|
||||||
|
@ -18,8 +18,8 @@ func ID() *oid.ID {
|
||||||
|
|
||||||
// idWithChecksum returns object.ID initialized
|
// idWithChecksum returns object.ID initialized
|
||||||
// with specified checksum.
|
// with specified checksum.
|
||||||
func idWithChecksum(cs [sha256.Size]byte) *oid.ID {
|
func idWithChecksum(cs [sha256.Size]byte) oid.ID {
|
||||||
id := oid.NewID()
|
var id oid.ID
|
||||||
id.SetSHA256(cs)
|
id.SetSHA256(cs)
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
|
|
@ -41,8 +41,8 @@ func (x Lock) NumberOfMembers() int {
|
||||||
func (x Lock) ReadMembers(buf []oid.ID) {
|
func (x Lock) ReadMembers(buf []oid.ID) {
|
||||||
var i int
|
var i int
|
||||||
|
|
||||||
(*v2object.Lock)(&x).IterateMembers(func(id refs.ObjectID) {
|
(*v2object.Lock)(&x).IterateMembers(func(idV2 refs.ObjectID) {
|
||||||
buf[i] = *oid.NewIDFromV2(&id) // need smth better
|
_ = buf[i].ReadFromV2(idV2)
|
||||||
i++
|
i++
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ func (x *Lock) WriteMembers(ids []oid.ID) {
|
||||||
members = make([]refs.ObjectID, len(ids))
|
members = make([]refs.ObjectID, len(ids))
|
||||||
|
|
||||||
for i := range ids {
|
for i := range ids {
|
||||||
members[i] = *ids[i].ToV2() // need smth better
|
ids[i].WriteToV2(&members[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
116
object/object.go
116
object/object.go
|
@ -34,7 +34,7 @@ type RequiredFields struct {
|
||||||
// InitCreation initializes the object instance with minimum set of required fields.
|
// InitCreation initializes the object instance with minimum set of required fields.
|
||||||
// Object is expected (but not required) to be blank. Object must not be nil.
|
// Object is expected (but not required) to be blank. Object must not be nil.
|
||||||
func InitCreation(dst *Object, rf RequiredFields) {
|
func InitCreation(dst *Object, rf RequiredFields) {
|
||||||
dst.SetContainerID(&rf.Container)
|
dst.SetContainerID(rf.Container)
|
||||||
dst.SetOwnerID(&rf.Owner)
|
dst.SetOwnerID(&rf.Owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,17 +86,24 @@ func (o *Object) setSplitFields(setter func(*object.SplitHeader)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns object identifier.
|
// ID returns object identifier.
|
||||||
func (o *Object) ID() *oid.ID {
|
func (o *Object) ID() oid.ID {
|
||||||
return oid.NewIDFromV2(
|
var v oid.ID
|
||||||
(*object.Object)(o).
|
|
||||||
GetObjectID(),
|
v2 := (*object.Object)(o)
|
||||||
)
|
if id := v2.GetObjectID(); id != nil {
|
||||||
|
_ = v.ReadFromV2(*v2.GetObjectID())
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetID sets object identifier.
|
// SetID sets object identifier.
|
||||||
func (o *Object) SetID(v *oid.ID) {
|
func (o *Object) SetID(v oid.ID) {
|
||||||
|
var v2 refs.ObjectID
|
||||||
|
v.WriteToV2(&v2)
|
||||||
|
|
||||||
(*object.Object)(o).
|
(*object.Object)(o).
|
||||||
SetObjectID(v.ToV2())
|
SetObjectID(&v2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signature returns signature of the object identifier.
|
// Signature returns signature of the object identifier.
|
||||||
|
@ -154,18 +161,25 @@ func (o *Object) SetPayloadSize(v uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerID returns identifier of the related container.
|
// ContainerID returns identifier of the related container.
|
||||||
func (o *Object) ContainerID() *cid.ID {
|
func (o *Object) ContainerID() cid.ID {
|
||||||
return cid.NewFromV2(
|
var cID cid.ID
|
||||||
(*object.Object)(o).
|
v2 := (*object.Object)(o)
|
||||||
GetHeader().
|
|
||||||
GetContainerID(),
|
cidV2 := v2.GetHeader().GetContainerID()
|
||||||
)
|
if cidV2 != nil {
|
||||||
|
_ = cID.ReadFromV2(*cidV2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cID
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetContainerID sets identifier of the related container.
|
// SetContainerID sets identifier of the related container.
|
||||||
func (o *Object) SetContainerID(v *cid.ID) {
|
func (o *Object) SetContainerID(v cid.ID) {
|
||||||
|
var cidV2 refs.ContainerID
|
||||||
|
v.WriteToV2(&cidV2)
|
||||||
|
|
||||||
o.setHeaderField(func(h *object.Header) {
|
o.setHeaderField(func(h *object.Header) {
|
||||||
h.SetContainerID(v.ToV2())
|
h.SetContainerID(&cidV2)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,33 +304,41 @@ func (o *Object) SetAttributes(v ...Attribute) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreviousID returns identifier of the previous sibling object.
|
// PreviousID returns identifier of the previous sibling object.
|
||||||
func (o *Object) PreviousID() *oid.ID {
|
func (o *Object) PreviousID() oid.ID {
|
||||||
return oid.NewIDFromV2(
|
var v oid.ID
|
||||||
(*object.Object)(o).
|
v2 := (*object.Object)(o)
|
||||||
GetHeader().
|
|
||||||
GetSplit().
|
v2Prev := v2.GetHeader().GetSplit().GetPrevious()
|
||||||
GetPrevious(),
|
if v2Prev != nil {
|
||||||
)
|
_ = v.ReadFromV2(*v2Prev)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPreviousID sets identifier of the previous sibling object.
|
// SetPreviousID sets identifier of the previous sibling object.
|
||||||
func (o *Object) SetPreviousID(v *oid.ID) {
|
func (o *Object) SetPreviousID(v oid.ID) {
|
||||||
|
var v2 refs.ObjectID
|
||||||
|
v.WriteToV2(&v2)
|
||||||
|
|
||||||
o.setSplitFields(func(split *object.SplitHeader) {
|
o.setSplitFields(func(split *object.SplitHeader) {
|
||||||
split.SetPrevious(v.ToV2())
|
split.SetPrevious(&v2)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Children return list of the identifiers of the child objects.
|
// Children return list of the identifiers of the child objects.
|
||||||
func (o *Object) Children() []oid.ID {
|
func (o *Object) Children() []oid.ID {
|
||||||
ids := (*object.Object)(o).
|
v2 := (*object.Object)(o)
|
||||||
GetHeader().
|
ids := v2.GetHeader().GetSplit().GetChildren()
|
||||||
GetSplit().
|
|
||||||
GetChildren()
|
|
||||||
|
|
||||||
res := make([]oid.ID, len(ids))
|
var (
|
||||||
|
id oid.ID
|
||||||
|
res = make([]oid.ID, len(ids))
|
||||||
|
)
|
||||||
|
|
||||||
for i := range ids {
|
for i := range ids {
|
||||||
res[i] = *oid.NewIDFromV2(&ids[i])
|
_ = id.ReadFromV2(ids[i])
|
||||||
|
res[i] = id
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
@ -324,10 +346,14 @@ func (o *Object) Children() []oid.ID {
|
||||||
|
|
||||||
// SetChildren sets list of the identifiers of the child objects.
|
// SetChildren sets list of the identifiers of the child objects.
|
||||||
func (o *Object) SetChildren(v ...oid.ID) {
|
func (o *Object) SetChildren(v ...oid.ID) {
|
||||||
ids := make([]refs.ObjectID, len(v))
|
var (
|
||||||
|
v2 refs.ObjectID
|
||||||
|
ids = make([]refs.ObjectID, len(v))
|
||||||
|
)
|
||||||
|
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = *v[i].ToV2()
|
v[i].WriteToV2(&v2)
|
||||||
|
ids[i] = v2
|
||||||
}
|
}
|
||||||
|
|
||||||
o.setSplitFields(func(split *object.SplitHeader) {
|
o.setSplitFields(func(split *object.SplitHeader) {
|
||||||
|
@ -406,19 +432,25 @@ func (o *Object) SetSplitID(id *SplitID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParentID returns identifier of the parent object.
|
// ParentID returns identifier of the parent object.
|
||||||
func (o *Object) ParentID() *oid.ID {
|
func (o *Object) ParentID() oid.ID {
|
||||||
return oid.NewIDFromV2(
|
var v oid.ID
|
||||||
(*object.Object)(o).
|
v2 := (*object.Object)(o)
|
||||||
GetHeader().
|
|
||||||
GetSplit().
|
v2Par := v2.GetHeader().GetSplit().GetParent()
|
||||||
GetParent(),
|
if v2Par != nil {
|
||||||
)
|
_ = v.ReadFromV2(*v2Par)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetParentID sets identifier of the parent object.
|
// SetParentID sets identifier of the parent object.
|
||||||
func (o *Object) SetParentID(v *oid.ID) {
|
func (o *Object) SetParentID(v oid.ID) {
|
||||||
|
var v2 refs.ObjectID
|
||||||
|
v.WriteToV2(&v2)
|
||||||
|
|
||||||
o.setSplitFields(func(split *object.SplitHeader) {
|
o.setSplitFields(func(split *object.SplitHeader) {
|
||||||
split.SetParent(v.ToV2())
|
split.SetParent(&v2)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
func TestInitCreation(t *testing.T) {
|
func TestInitCreation(t *testing.T) {
|
||||||
var o object.Object
|
var o object.Object
|
||||||
cnr := *cidtest.ID()
|
cnr := cidtest.ID()
|
||||||
own := *ownertest.ID()
|
own := *ownertest.ID()
|
||||||
|
|
||||||
object.InitCreation(&o, object.RequiredFields{
|
object.InitCreation(&o, object.RequiredFields{
|
||||||
|
@ -19,6 +19,6 @@ func TestInitCreation(t *testing.T) {
|
||||||
Owner: own,
|
Owner: own,
|
||||||
})
|
})
|
||||||
|
|
||||||
require.Equal(t, &cnr, o.ContainerID())
|
require.Equal(t, cnr, o.ContainerID())
|
||||||
require.Equal(t, &own, o.OwnerID())
|
require.Equal(t, &own, o.OwnerID())
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func randID(t *testing.T) *oid.ID {
|
func randID(t *testing.T) oid.ID {
|
||||||
id := oid.NewID()
|
var id oid.ID
|
||||||
id.SetSHA256(randSHA256Checksum(t))
|
id.SetSHA256(randSHA256Checksum(t))
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
@ -177,9 +177,9 @@ func TestObject_SetChildren(t *testing.T) {
|
||||||
id1 := randID(t)
|
id1 := randID(t)
|
||||||
id2 := randID(t)
|
id2 := randID(t)
|
||||||
|
|
||||||
obj.SetChildren(*id1, *id2)
|
obj.SetChildren(id1, id2)
|
||||||
|
|
||||||
require.Equal(t, []oid.ID{*id1, *id2}, obj.Children())
|
require.Equal(t, []oid.ID{id1, id2}, obj.Children())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestObject_SetSplitID(t *testing.T) {
|
func TestObject_SetSplitID(t *testing.T) {
|
||||||
|
@ -280,7 +280,7 @@ func TestObject_ResetRelations(t *testing.T) {
|
||||||
|
|
||||||
obj.ResetRelations()
|
obj.ResetRelations()
|
||||||
|
|
||||||
require.Nil(t, obj.PreviousID())
|
require.True(t, obj.PreviousID().Empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestObject_HasParent(t *testing.T) {
|
func TestObject_HasParent(t *testing.T) {
|
||||||
|
|
|
@ -220,7 +220,7 @@ func (f *SearchFilters) AddObjectVersionFilter(op SearchMatchType, v *version.Ve
|
||||||
f.addReservedFilter(op, fKeyVersion, v)
|
f.addReservedFilter(op, fKeyVersion, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *SearchFilters) AddObjectContainerIDFilter(m SearchMatchType, id *cid.ID) {
|
func (f *SearchFilters) AddObjectContainerIDFilter(m SearchMatchType, id cid.ID) {
|
||||||
f.addReservedFilter(m, fKeyContainerID, id)
|
f.addReservedFilter(m, fKeyContainerID, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,12 +261,12 @@ func (f *SearchFilters) AddPhyFilter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddParentIDFilter adds filter by parent identifier.
|
// AddParentIDFilter adds filter by parent identifier.
|
||||||
func (f *SearchFilters) AddParentIDFilter(m SearchMatchType, id *oid.ID) {
|
func (f *SearchFilters) AddParentIDFilter(m SearchMatchType, id oid.ID) {
|
||||||
f.addReservedFilter(m, fKeyParent, id)
|
f.addReservedFilter(m, fKeyParent, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddObjectIDFilter adds filter by object identifier.
|
// AddObjectIDFilter adds filter by object identifier.
|
||||||
func (f *SearchFilters) AddObjectIDFilter(m SearchMatchType, id *oid.ID) {
|
func (f *SearchFilters) AddObjectIDFilter(m SearchMatchType, id oid.ID) {
|
||||||
f.addReservedFilter(m, fKeyObjectID, id)
|
f.addReservedFilter(m, fKeyObjectID, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,12 +100,12 @@ func TestSearchFilters_AddPhyFilter(t *testing.T) {
|
||||||
require.Equal(t, "", f.Value())
|
require.Equal(t, "", f.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
func testOID() *oid.ID {
|
func testOID() oid.ID {
|
||||||
cs := [sha256.Size]byte{}
|
cs := [sha256.Size]byte{}
|
||||||
|
|
||||||
rand.Read(cs[:])
|
rand.Read(cs[:])
|
||||||
|
|
||||||
id := oid.NewID()
|
var id oid.ID
|
||||||
id.SetSHA256(cs)
|
id.SetSHA256(cs)
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
|
|
@ -2,6 +2,7 @@ package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
"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"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,22 +41,42 @@ func (s *SplitInfo) SetSplitID(v *SplitID) {
|
||||||
(*object.SplitInfo)(s).SetSplitID(v.ToV2())
|
(*object.SplitInfo)(s).SetSplitID(v.ToV2())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SplitInfo) LastPart() *oid.ID {
|
func (s SplitInfo) LastPart() oid.ID {
|
||||||
return oid.NewIDFromV2(
|
var id oid.ID
|
||||||
(*object.SplitInfo)(s).GetLastPart())
|
v2 := (object.SplitInfo)(s)
|
||||||
|
|
||||||
|
lpV2 := v2.GetLastPart()
|
||||||
|
if lpV2 != nil {
|
||||||
|
_ = id.ReadFromV2(*lpV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SplitInfo) SetLastPart(v *oid.ID) {
|
return id
|
||||||
(*object.SplitInfo)(s).SetLastPart(v.ToV2())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SplitInfo) Link() *oid.ID {
|
func (s *SplitInfo) SetLastPart(v oid.ID) {
|
||||||
return oid.NewIDFromV2(
|
var idV2 refs.ObjectID
|
||||||
(*object.SplitInfo)(s).GetLink())
|
v.WriteToV2(&idV2)
|
||||||
|
|
||||||
|
(*object.SplitInfo)(s).SetLastPart(&idV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SplitInfo) SetLink(v *oid.ID) {
|
func (s SplitInfo) Link() oid.ID {
|
||||||
(*object.SplitInfo)(s).SetLink(v.ToV2())
|
var id oid.ID
|
||||||
|
v2 := (object.SplitInfo)(s)
|
||||||
|
|
||||||
|
linkV2 := v2.GetLink()
|
||||||
|
if linkV2 != nil {
|
||||||
|
_ = id.ReadFromV2(*linkV2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SplitInfo) SetLink(v oid.ID) {
|
||||||
|
var idV2 refs.ObjectID
|
||||||
|
v.WriteToV2(&idV2)
|
||||||
|
|
||||||
|
(*object.SplitInfo)(s).SetLink(&idV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SplitInfo) Marshal() ([]byte, error) {
|
func (s *SplitInfo) Marshal() ([]byte, error) {
|
||||||
|
|
|
@ -45,11 +45,11 @@ func TestSplitInfo(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateID() *oid.ID {
|
func generateID() oid.ID {
|
||||||
var buf [32]byte
|
var buf [32]byte
|
||||||
_, _ = rand.Read(buf[:])
|
_, _ = rand.Read(buf[:])
|
||||||
|
|
||||||
id := oid.NewID()
|
var id oid.ID
|
||||||
id.SetSHA256(buf)
|
id.SetSHA256(buf)
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
@ -77,8 +77,8 @@ func TestNewSplitInfo(t *testing.T) {
|
||||||
|
|
||||||
// check initial values
|
// check initial values
|
||||||
require.Nil(t, si.SplitID())
|
require.Nil(t, si.SplitID())
|
||||||
require.Nil(t, si.LastPart())
|
require.True(t, si.LastPart().Empty())
|
||||||
require.Nil(t, si.Link())
|
require.True(t, si.Link().Empty())
|
||||||
|
|
||||||
// convert to v2 message
|
// convert to v2 message
|
||||||
siV2 := si.ToV2()
|
siV2 := si.ToV2()
|
||||||
|
|
|
@ -57,7 +57,7 @@ func generate(withParent bool) *object.Object {
|
||||||
x.SetCreationEpoch(222)
|
x.SetCreationEpoch(222)
|
||||||
x.SetPreviousID(oidtest.ID())
|
x.SetPreviousID(oidtest.ID())
|
||||||
x.SetParentID(oidtest.ID())
|
x.SetParentID(oidtest.ID())
|
||||||
x.SetChildren(*oidtest.ID(), *oidtest.ID())
|
x.SetChildren(oidtest.ID(), oidtest.ID())
|
||||||
x.SetAttributes(*Attribute(), *Attribute())
|
x.SetAttributes(*Attribute(), *Attribute())
|
||||||
x.SetSplitID(SplitID())
|
x.SetSplitID(SplitID())
|
||||||
x.SetPayloadChecksum(checksumtest.Checksum())
|
x.SetPayloadChecksum(checksumtest.Checksum())
|
||||||
|
@ -88,7 +88,7 @@ func Tombstone() *object.Tombstone {
|
||||||
|
|
||||||
x.SetSplitID(SplitID())
|
x.SetSplitID(SplitID())
|
||||||
x.SetExpirationEpoch(13)
|
x.SetExpirationEpoch(13)
|
||||||
x.SetMembers([]oid.ID{*oidtest.ID(), *oidtest.ID()})
|
x.SetMembers([]oid.ID{oidtest.ID(), oidtest.ID()})
|
||||||
|
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ func SearchFilters() object.SearchFilters {
|
||||||
// Lock returns random object.Lock.
|
// Lock returns random object.Lock.
|
||||||
func Lock() *object.Lock {
|
func Lock() *object.Lock {
|
||||||
var l object.Lock
|
var l object.Lock
|
||||||
l.WriteMembers([]oid.ID{*oidtest.ID(), *oidtest.ID()})
|
l.WriteMembers([]oid.ID{oidtest.ID(), oidtest.ID()})
|
||||||
|
|
||||||
return &l
|
return &l
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,17 +56,21 @@ func (t *Tombstone) SetSplitID(v *SplitID) {
|
||||||
|
|
||||||
// Members returns list of objects to be deleted.
|
// Members returns list of objects to be deleted.
|
||||||
func (t *Tombstone) Members() []oid.ID {
|
func (t *Tombstone) Members() []oid.ID {
|
||||||
msV2 := (*tombstone.Tombstone)(t).
|
v2 := (*tombstone.Tombstone)(t)
|
||||||
GetMembers()
|
msV2 := v2.GetMembers()
|
||||||
|
|
||||||
if msV2 == nil {
|
if msV2 == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ms := make([]oid.ID, len(msV2))
|
var (
|
||||||
|
ms = make([]oid.ID, len(msV2))
|
||||||
|
id oid.ID
|
||||||
|
)
|
||||||
|
|
||||||
for i := range msV2 {
|
for i := range msV2 {
|
||||||
ms[i] = *oid.NewIDFromV2(&msV2[i])
|
_ = id.ReadFromV2(msV2[i])
|
||||||
|
ms[i] = id
|
||||||
}
|
}
|
||||||
|
|
||||||
return ms
|
return ms
|
||||||
|
@ -86,8 +90,11 @@ func (t *Tombstone) SetMembers(v []oid.ID) {
|
||||||
ms = make([]refs.ObjectID, 0, ln)
|
ms = make([]refs.ObjectID, 0, ln)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var idV2 refs.ObjectID
|
||||||
|
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ms = append(ms, *v[i].ToV2())
|
v[i].WriteToV2(&idV2)
|
||||||
|
ms = append(ms, idV2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,9 @@ func generateIDList(sz int) []oid.ID {
|
||||||
cs := [sha256.Size]byte{}
|
cs := [sha256.Size]byte{}
|
||||||
|
|
||||||
for i := 0; i < sz; i++ {
|
for i := 0; i < sz; i++ {
|
||||||
res[i] = *oid.NewID()
|
var oID oid.ID
|
||||||
|
|
||||||
|
res[i] = oID
|
||||||
rand.Read(cs[:])
|
rand.Read(cs[:])
|
||||||
res[i].SetSHA256(cs)
|
res[i].SetSHA256(cs)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package session
|
package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
)
|
)
|
||||||
|
@ -43,8 +44,17 @@ func (x *ContainerContext) ToV2() *session.ContainerSessionContext {
|
||||||
func (x *ContainerContext) ApplyTo(id *cid.ID) {
|
func (x *ContainerContext) ApplyTo(id *cid.ID) {
|
||||||
v2 := (*session.ContainerSessionContext)(x)
|
v2 := (*session.ContainerSessionContext)(x)
|
||||||
|
|
||||||
|
var cidV2 *refs.ContainerID
|
||||||
|
|
||||||
|
if id != nil {
|
||||||
|
var c refs.ContainerID
|
||||||
|
id.WriteToV2(&c)
|
||||||
|
|
||||||
|
cidV2 = &c
|
||||||
|
}
|
||||||
|
|
||||||
v2.SetWildcard(id == nil)
|
v2.SetWildcard(id == nil)
|
||||||
v2.SetContainerID(id.ToV2())
|
v2.SetContainerID(cidV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyToAllContainers is a helper function that conveniently
|
// ApplyToAllContainers is a helper function that conveniently
|
||||||
|
@ -65,7 +75,15 @@ func (x *ContainerContext) Container() *cid.ID {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return cid.NewFromV2(v2.ContainerID())
|
cidV2 := v2.ContainerID()
|
||||||
|
if cidV2 == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var cID cid.ID
|
||||||
|
_ = cID.ReadFromV2(*cidV2)
|
||||||
|
|
||||||
|
return &cID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ContainerContext) forVerb(v session.ContainerSessionVerb) {
|
func (x *ContainerContext) forVerb(v session.ContainerSessionVerb) {
|
||||||
|
|
|
@ -39,9 +39,9 @@ func TestContainerContext_ApplyTo(t *testing.T) {
|
||||||
id := cidtest.ID()
|
id := cidtest.ID()
|
||||||
|
|
||||||
t.Run("method", func(t *testing.T) {
|
t.Run("method", func(t *testing.T) {
|
||||||
c.ApplyTo(id)
|
c.ApplyTo(&id)
|
||||||
|
|
||||||
require.Equal(t, id, c.Container())
|
require.Equal(t, id, *c.Container())
|
||||||
|
|
||||||
c.ApplyTo(nil)
|
c.ApplyTo(nil)
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ func TestContainerContext_ApplyTo(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("helper functions", func(t *testing.T) {
|
t.Run("helper functions", func(t *testing.T) {
|
||||||
c.ApplyTo(id)
|
c.ApplyTo(&id)
|
||||||
|
|
||||||
session.ApplyToAllContainers(c)
|
session.ApplyToAllContainers(c)
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ func ContainerContext() *session.ContainerContext {
|
||||||
|
|
||||||
setters[rand.Uint32()%uint32(len(setters))]()
|
setters[rand.Uint32()%uint32(len(setters))]()
|
||||||
|
|
||||||
c.ApplyTo(cidtest.ID())
|
cID := cidtest.ID()
|
||||||
|
c.ApplyTo(&cID)
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ func (sg *StorageGroup) Members() []oid.ID {
|
||||||
m := make([]oid.ID, len(mV2))
|
m := make([]oid.ID, len(mV2))
|
||||||
|
|
||||||
for i := range mV2 {
|
for i := range mV2 {
|
||||||
m[i] = *oid.NewIDFromV2(&mV2[i])
|
_ = m[i].ReadFromV2(mV2[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
@ -115,8 +115,11 @@ func (sg *StorageGroup) SetMembers(members []oid.ID) {
|
||||||
mV2 = make([]refs.ObjectID, ln)
|
mV2 = make([]refs.ObjectID, ln)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var oidV2 refs.ObjectID
|
||||||
|
|
||||||
for i := 0; i < ln; i++ {
|
for i := 0; i < ln; i++ {
|
||||||
mV2[i] = *members[i].ToV2()
|
members[i].WriteToV2(&oidV2)
|
||||||
|
mV2[i] = oidV2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ func TestStorageGroup(t *testing.T) {
|
||||||
sg.SetExpirationEpoch(exp)
|
sg.SetExpirationEpoch(exp)
|
||||||
require.Equal(t, exp, sg.ExpirationEpoch())
|
require.Equal(t, exp, sg.ExpirationEpoch())
|
||||||
|
|
||||||
members := []oid.ID{*oidtest.ID(), *oidtest.ID()}
|
members := []oid.ID{oidtest.ID(), oidtest.ID()}
|
||||||
sg.SetMembers(members)
|
sg.SetMembers(members)
|
||||||
require.Equal(t, members, sg.Members())
|
require.Equal(t, members, sg.Members())
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ func StorageGroup() *storagegroup.StorageGroup {
|
||||||
x.SetExpirationEpoch(66)
|
x.SetExpirationEpoch(66)
|
||||||
x.SetValidationDataSize(322)
|
x.SetValidationDataSize(322)
|
||||||
x.SetValidationDataHash(checksumtest.Checksum())
|
x.SetValidationDataHash(checksumtest.Checksum())
|
||||||
x.SetMembers([]oid.ID{*oidtest.ID(), *oidtest.ID()})
|
x.SetMembers([]oid.ID{oidtest.ID(), oidtest.ID()})
|
||||||
|
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue