forked from TrueCloudLab/frostfs-api-go
[#140] sdk/object: Refactor object types
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
e40995b5d4
commit
6ce70d4a18
4 changed files with 574 additions and 236 deletions
|
@ -1,21 +1,10 @@
|
||||||
package object
|
package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/sha256"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/util/signature"
|
|
||||||
"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"
|
|
||||||
signatureV2 "github.com/nspcc-dev/neofs-api-go/v2/signature"
|
|
||||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Object represents NeoFS object that provides
|
// Object represents v2-compatible NeoFS object that provides
|
||||||
// a convenient interface for working in isolation
|
// a convenient interface for working in isolation
|
||||||
// from the internal structure of an object.
|
// from the internal structure of an object.
|
||||||
//
|
//
|
||||||
|
@ -23,198 +12,28 @@ import (
|
||||||
// mode as a reflection of the immutability of objects
|
// mode as a reflection of the immutability of objects
|
||||||
// in the system.
|
// in the system.
|
||||||
type Object struct {
|
type Object struct {
|
||||||
rwObject
|
*rwObject
|
||||||
}
|
}
|
||||||
|
|
||||||
type rwObject struct {
|
// NewFromV2 wraps v2 Object message to Object.
|
||||||
fin bool
|
func NewFromV2(oV2 *object.Object) *Object {
|
||||||
|
|
||||||
id *ID
|
|
||||||
|
|
||||||
key, sig []byte
|
|
||||||
|
|
||||||
cid *container.ID
|
|
||||||
|
|
||||||
ownerID *owner.ID
|
|
||||||
|
|
||||||
payloadChecksum *refs.Checksum
|
|
||||||
|
|
||||||
payload []byte
|
|
||||||
|
|
||||||
// TODO: add other fields
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify checks if object structure is correct.
|
|
||||||
func (o *Object) Verify() error {
|
|
||||||
if o == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
hdr := o.v2Header()
|
|
||||||
|
|
||||||
data, err := hdr.StableMarshal(nil)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "could not marshal header")
|
|
||||||
}
|
|
||||||
|
|
||||||
hdrChecksum := sha256.Sum256(data)
|
|
||||||
|
|
||||||
if !bytes.Equal(hdrChecksum[:], o.id.ToV2().GetValue()) {
|
|
||||||
return errors.New("invalid object identifier")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := signature.VerifyDataWithSource(
|
|
||||||
signatureV2.StableMarshalerWrapper{
|
|
||||||
SM: o.id.ToV2(),
|
|
||||||
},
|
|
||||||
func() (key, sig []byte) {
|
|
||||||
return o.key, o.sig
|
|
||||||
},
|
|
||||||
); err != nil {
|
|
||||||
return errors.Wrap(err, "invalid object ID signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPayload returns object payload bytes.
|
|
||||||
func (o *Object) GetPayload() []byte {
|
|
||||||
if o != nil {
|
|
||||||
return o.payload
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CutPayload copies object fields w/o payload.
|
|
||||||
func (o *Object) CutPayload() *Object {
|
|
||||||
if o != nil {
|
|
||||||
return &Object{
|
return &Object{
|
||||||
rwObject: rwObject{
|
rwObject: (*rwObject)(oV2),
|
||||||
fin: o.fin,
|
|
||||||
id: o.id,
|
|
||||||
key: o.key,
|
|
||||||
sig: o.sig,
|
|
||||||
cid: o.cid,
|
|
||||||
ownerID: o.ownerID,
|
|
||||||
payloadChecksum: o.payloadChecksum,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *rwObject) v2Header() *object.Header {
|
// New creates and initializes blank Object.
|
||||||
hV2 := new(object.Header)
|
|
||||||
hV2.SetContainerID(o.cid.ToV2())
|
|
||||||
hV2.SetOwnerID(o.ownerID.ToV2())
|
|
||||||
hV2.SetPayloadHash(o.payloadChecksum)
|
|
||||||
// TODO: set other fields
|
|
||||||
|
|
||||||
return hV2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *rwObject) complete(key *ecdsa.PrivateKey) (*object.Header, error) {
|
|
||||||
hdr := o.v2Header()
|
|
||||||
|
|
||||||
hdrData, err := hdr.StableMarshal(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "could not marshal header")
|
|
||||||
}
|
|
||||||
|
|
||||||
o.id = new(ID)
|
|
||||||
o.id.SetSHA256(sha256.Sum256(hdrData))
|
|
||||||
|
|
||||||
if err := signature.SignDataWithHandler(
|
|
||||||
key,
|
|
||||||
signatureV2.StableMarshalerWrapper{
|
|
||||||
SM: o.id.ToV2(),
|
|
||||||
},
|
|
||||||
func(key []byte, sig []byte) {
|
|
||||||
o.key, o.sig = key, sig
|
|
||||||
},
|
|
||||||
); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "could sign object identifier")
|
|
||||||
}
|
|
||||||
|
|
||||||
o.fin = true
|
|
||||||
|
|
||||||
return hdr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToV2 calculates object identifier, signs structure and converts
|
|
||||||
// it to v2 Object message.
|
|
||||||
func (o *rwObject) ToV2(key *ecdsa.PrivateKey) (*object.Object, error) {
|
|
||||||
if o == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
hdr *object.Header
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
if !o.fin {
|
|
||||||
if key == nil {
|
|
||||||
return nil, errors.Wrap(crypto.ErrEmptyPrivateKey, "could complete the object")
|
|
||||||
}
|
|
||||||
|
|
||||||
if hdr, err = o.complete(key); err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "could not complete the object")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hdr = o.v2Header()
|
|
||||||
}
|
|
||||||
|
|
||||||
obj := new(object.Object)
|
|
||||||
obj.SetObjectID(o.id.ToV2())
|
|
||||||
obj.SetHeader(hdr)
|
|
||||||
obj.SetPayload(o.payload)
|
|
||||||
|
|
||||||
sig := new(refs.Signature)
|
|
||||||
sig.SetKey(o.key)
|
|
||||||
sig.SetSign(o.sig)
|
|
||||||
obj.SetSignature(sig)
|
|
||||||
|
|
||||||
return obj, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromV2 converts v2 Object message to Object instance.
|
|
||||||
//
|
//
|
||||||
// Returns any error encountered which prevented the
|
// Works similar as NewFromV2(new(Object)).
|
||||||
// recovery of object data from the message.
|
func New() *Object {
|
||||||
func FromV2(oV2 *object.Object) (*Object, error) {
|
return NewFromV2(initObjectRecursive())
|
||||||
if oV2 == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
hdr := oV2.GetHeader()
|
|
||||||
|
|
||||||
// TODO: convert other fields
|
|
||||||
|
|
||||||
sig := oV2.GetSignature()
|
|
||||||
|
|
||||||
return &Object{
|
|
||||||
rwObject: rwObject{
|
|
||||||
fin: true,
|
|
||||||
id: NewIDFromV2(oV2.GetObjectID()),
|
|
||||||
key: sig.GetKey(),
|
|
||||||
sig: sig.GetSign(),
|
|
||||||
cid: container.NewIDFromV2(hdr.GetContainerID()),
|
|
||||||
ownerID: owner.NewIDFromV2(hdr.GetOwnerID()),
|
|
||||||
payloadChecksum: hdr.GetPayloadHash(),
|
|
||||||
payload: oV2.GetPayload(),
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromBytes restores Object from a binary representation.
|
// ToV2 converts Object to v2 Object message.
|
||||||
func FromBytes(data []byte) (*Object, error) {
|
func (o *Object) ToV2() *object.Object {
|
||||||
oV2 := new(object.Object)
|
if o != nil {
|
||||||
if err := oV2.StableUnmarshal(data); err != nil {
|
return (*object.Object)(o.rwObject)
|
||||||
return nil, errors.Wrap(err, "could not unmarshal object")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FromV2(oV2)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,35 @@
|
||||||
package object
|
package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"github.com/nspcc-dev/neofs-api-go/pkg"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RawObject represents NeoFS object that provides
|
// RawObject represents v2-compatible NeoFS object that provides
|
||||||
// a convenient interface to fill in the fields of
|
// a convenient interface to fill in the fields of
|
||||||
// an object in isolation from its internal structure.
|
// an object in isolation from its internal structure.
|
||||||
type RawObject struct {
|
type RawObject struct {
|
||||||
rwObject
|
*rwObject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *RawObject) set(setter func()) {
|
// NewRawFromV2 wraps v2 Object message to RawObject.
|
||||||
o.fin = false
|
func NewRawFromV2(oV2 *object.Object) *RawObject {
|
||||||
setter()
|
return &RawObject{
|
||||||
}
|
rwObject: (*rwObject)(oV2),
|
||||||
|
|
||||||
// SetContainerID sets object's container identifier.
|
|
||||||
func (o *RawObject) SetContainerID(v *container.ID) {
|
|
||||||
if o != nil {
|
|
||||||
o.set(func() {
|
|
||||||
o.cid = v
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOwnerID sets identifier of the object's owner.
|
// NewRaw creates and initializes blank RawObject.
|
||||||
func (o *RawObject) SetOwnerID(v *owner.ID) {
|
//
|
||||||
if o != nil {
|
// Works similar as NewRawFromV2(new(Object)).
|
||||||
o.set(func() {
|
func NewRaw() *RawObject {
|
||||||
o.ownerID = v
|
return NewRawFromV2(initObjectRecursive())
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release returns read-only Object instance.
|
// Object returns read-only object instance.
|
||||||
func (o *RawObject) Release() *Object {
|
func (o *RawObject) Object() *Object {
|
||||||
if o != nil {
|
if o != nil {
|
||||||
return &Object{
|
return &Object{
|
||||||
rwObject: o.rwObject,
|
rwObject: o.rwObject,
|
||||||
|
@ -49,16 +39,72 @@ func (o *RawObject) Release() *Object {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPayloadChecksumSHA256 sets payload checksum as a SHA256 checksum.
|
// SetID sets object identifier.
|
||||||
func (o *RawObject) SetPayloadChecksumSHA256(v [sha256.Size]byte) {
|
func (o *RawObject) SetID(v *ID) {
|
||||||
if o != nil {
|
o.setID(v)
|
||||||
o.set(func() {
|
}
|
||||||
if o.payloadChecksum == nil {
|
|
||||||
o.payloadChecksum = new(refs.Checksum)
|
// SetSignature sets signature of the object identifier.
|
||||||
}
|
func (o *RawObject) SetSignature(v *pkg.Signature) {
|
||||||
|
o.setSignature(v)
|
||||||
o.payloadChecksum.SetType(refs.SHA256)
|
}
|
||||||
o.payloadChecksum.SetSum(v[:])
|
|
||||||
})
|
// SetPayload sets payload bytes.
|
||||||
}
|
func (o *RawObject) SetPayload(v []byte) {
|
||||||
|
o.setPayload(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetVersion sets version of the object.
|
||||||
|
func (o *RawObject) SetVersion(v *pkg.Version) {
|
||||||
|
o.setVersion(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPayloadSize sets payload length of the object.
|
||||||
|
func (o *RawObject) SetPayloadSize(v uint64) {
|
||||||
|
o.setPayloadSize(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetContainerID sets identifier of the related container.
|
||||||
|
func (o *RawObject) SetContainerID(v *container.ID) {
|
||||||
|
o.setContainerID(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOwnerID sets identifier of the object owner.
|
||||||
|
func (o *RawObject) SetOwnerID(v *owner.ID) {
|
||||||
|
o.setOwnerID(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCreationEpoch sets epoch number in which object was created.
|
||||||
|
func (o *RawObject) SetCreationEpoch(v uint64) {
|
||||||
|
o.setCreationEpoch(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPayloadChecksum sets checksum of the object payload.
|
||||||
|
func (o *RawObject) SetPayloadChecksum(v *pkg.Checksum) {
|
||||||
|
o.setPayloadChecksum(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPayloadHomomorphicHash sets homomorphic hash of the object payload.
|
||||||
|
func (o *RawObject) SetPayloadHomomorphicHash(v *pkg.Checksum) {
|
||||||
|
o.setPayloadHomomorphicHash(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAttributes sets object attributes.
|
||||||
|
func (o *RawObject) SetAttributes(v ...*Attribute) {
|
||||||
|
o.setAttributes(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPreviousID sets identifier of the previous sibling object.
|
||||||
|
func (o *RawObject) SetPreviousID(v *ID) {
|
||||||
|
o.setPreviousID(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetChildren sets list of the identifiers of the child objects.
|
||||||
|
func (o *RawObject) SetChildren(v ...*ID) {
|
||||||
|
o.setChildren(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetParent sets parent object w/o payload.
|
||||||
|
func (o *RawObject) SetParent(v *Object) {
|
||||||
|
o.setParent(v)
|
||||||
}
|
}
|
||||||
|
|
204
pkg/object/raw_test.go
Normal file
204
pkg/object/raw_test.go
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func randID(t *testing.T) *ID {
|
||||||
|
id := NewID()
|
||||||
|
id.SetSHA256(randSHA256Checksum(t))
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
func randSHA256Checksum(t *testing.T) (cs [sha256.Size]byte) {
|
||||||
|
_, err := rand.Read(cs[:])
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func randTZChecksum(t *testing.T) (cs [64]byte) {
|
||||||
|
_, err := rand.Read(cs[:])
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetID(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
id := randID(t)
|
||||||
|
|
||||||
|
obj.SetID(id)
|
||||||
|
|
||||||
|
require.Equal(t, id, obj.GetID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetSignature(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
sig := pkg.NewSignature()
|
||||||
|
sig.SetKey([]byte{1, 2, 3})
|
||||||
|
sig.SetSign([]byte{4, 5, 6})
|
||||||
|
|
||||||
|
obj.SetSignature(sig)
|
||||||
|
|
||||||
|
require.Equal(t, sig, obj.GetSignature())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetPayload(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
payload := make([]byte, 10)
|
||||||
|
_, _ = rand.Read(payload)
|
||||||
|
|
||||||
|
obj.SetPayload(payload)
|
||||||
|
|
||||||
|
require.Equal(t, payload, obj.GetPayload())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetVersion(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
ver := pkg.NewVersion()
|
||||||
|
ver.SetMajor(1)
|
||||||
|
ver.SetMinor(2)
|
||||||
|
|
||||||
|
obj.SetVersion(ver)
|
||||||
|
|
||||||
|
require.Equal(t, ver, obj.GetVersion())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetPayloadSize(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
sz := uint64(133)
|
||||||
|
obj.SetPayloadSize(sz)
|
||||||
|
|
||||||
|
require.Equal(t, sz, obj.GetPayloadSize())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetContainerID(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
checksum := randSHA256Checksum(t)
|
||||||
|
|
||||||
|
cid := container.NewID()
|
||||||
|
cid.SetSHA256(checksum)
|
||||||
|
|
||||||
|
obj.SetContainerID(cid)
|
||||||
|
|
||||||
|
require.Equal(t, cid, obj.GetContainerID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetOwnerID(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
w := new(owner.NEO3Wallet)
|
||||||
|
_, _ = rand.Read(w.Bytes())
|
||||||
|
|
||||||
|
ownerID := owner.NewID()
|
||||||
|
ownerID.SetNeo3Wallet(w)
|
||||||
|
|
||||||
|
obj.SetOwnerID(ownerID)
|
||||||
|
|
||||||
|
require.Equal(t, ownerID, obj.GetOwnerID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetCreationEpoch(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
creat := uint64(228)
|
||||||
|
obj.setCreationEpoch(creat)
|
||||||
|
|
||||||
|
require.Equal(t, creat, obj.GetCreationEpoch())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetPayloadChecksum(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
cs := pkg.NewChecksum()
|
||||||
|
cs.SetSHA256(randSHA256Checksum(t))
|
||||||
|
|
||||||
|
obj.SetPayloadChecksum(cs)
|
||||||
|
|
||||||
|
require.Equal(t, cs, obj.GetPayloadChecksum())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetPayloadHomomorphicHash(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
cs := pkg.NewChecksum()
|
||||||
|
cs.SetTillichZemor(randTZChecksum(t))
|
||||||
|
|
||||||
|
obj.SetPayloadHomomorphicHash(cs)
|
||||||
|
|
||||||
|
require.Equal(t, cs, obj.GetPayloadHomomorphicHash())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetAttributes(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
a1 := NewAttribute()
|
||||||
|
a1.SetKey("key1")
|
||||||
|
a1.SetValue("val1")
|
||||||
|
|
||||||
|
a2 := NewAttribute()
|
||||||
|
a2.SetKey("key2")
|
||||||
|
a2.SetValue("val2")
|
||||||
|
|
||||||
|
obj.SetAttributes(a1, a2)
|
||||||
|
|
||||||
|
require.Equal(t, []*Attribute{a1, a2}, obj.GetAttributes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetPreviousID(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
prev := randID(t)
|
||||||
|
|
||||||
|
obj.SetPreviousID(prev)
|
||||||
|
|
||||||
|
require.Equal(t, prev, obj.GetPreviousID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetChildren(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
id1 := randID(t)
|
||||||
|
id2 := randID(t)
|
||||||
|
|
||||||
|
obj.SetChildren(id1, id2)
|
||||||
|
|
||||||
|
require.Equal(t, []*ID{id1, id2}, obj.GetChildren())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_SetParent(t *testing.T) {
|
||||||
|
obj := NewRaw()
|
||||||
|
|
||||||
|
par := NewRaw()
|
||||||
|
par.SetID(randID(t))
|
||||||
|
parObj := par.Object()
|
||||||
|
|
||||||
|
obj.SetParent(parObj)
|
||||||
|
|
||||||
|
require.Equal(t, parObj, obj.GetParent())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawObject_ToV2(t *testing.T) {
|
||||||
|
objV2 := new(object.Object)
|
||||||
|
objV2.SetPayload([]byte{1, 2, 3})
|
||||||
|
|
||||||
|
obj := NewRawFromV2(objV2)
|
||||||
|
|
||||||
|
require.Equal(t, objV2, obj.ToV2())
|
||||||
|
}
|
269
pkg/object/rw.go
Normal file
269
pkg/object/rw.go
Normal file
|
@ -0,0 +1,269 @@
|
||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// wrapper over v2 Object that provides
|
||||||
|
// public getter and private setters.
|
||||||
|
type rwObject object.Object
|
||||||
|
|
||||||
|
func initObjectRecursive() *object.Object {
|
||||||
|
obj := new(object.Object)
|
||||||
|
|
||||||
|
hdr := new(object.Header)
|
||||||
|
|
||||||
|
hdr.SetSplit(new(object.SplitHeader))
|
||||||
|
|
||||||
|
obj.SetHeader(hdr)
|
||||||
|
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add session token methods
|
||||||
|
|
||||||
|
// ToV2 converts Object to v2 Object message.
|
||||||
|
func (o *rwObject) ToV2() *object.Object {
|
||||||
|
return (*object.Object)(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetID returns object identifier.
|
||||||
|
func (o *rwObject) GetID() *ID {
|
||||||
|
return NewIDFromV2(
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetObjectID(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setID(v *ID) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
SetObjectID(v.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSignature returns signature of the object identifier.
|
||||||
|
func (o *rwObject) GetSignature() *pkg.Signature {
|
||||||
|
return pkg.NewSignatureFromV2(
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetSignature(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setSignature(v *pkg.Signature) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
SetSignature(v.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPayload returns payload bytes.
|
||||||
|
func (o *rwObject) GetPayload() []byte {
|
||||||
|
return (*object.Object)(o).
|
||||||
|
GetPayload()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setPayload(v []byte) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
SetPayload(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVersion returns version of the object.
|
||||||
|
func (o *rwObject) GetVersion() *pkg.Version {
|
||||||
|
return pkg.NewVersionFromV2(
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetVersion(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setVersion(v *pkg.Version) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
SetVersion(v.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPayloadSize returns payload length of the object.
|
||||||
|
func (o *rwObject) GetPayloadSize() uint64 {
|
||||||
|
return (*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetPayloadLength()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setPayloadSize(v uint64) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
SetPayloadLength(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContainerID returns identifier of the related container.
|
||||||
|
func (o *rwObject) GetContainerID() *container.ID {
|
||||||
|
return container.NewIDFromV2(
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetContainerID(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setContainerID(v *container.ID) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
SetContainerID(v.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOwnerID returns identifier of the object owner.
|
||||||
|
func (o *rwObject) GetOwnerID() *owner.ID {
|
||||||
|
return owner.NewIDFromV2(
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetOwnerID(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setOwnerID(v *owner.ID) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
SetOwnerID(v.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCreationEpoch returns epoch number in which object was created.
|
||||||
|
func (o *rwObject) GetCreationEpoch() uint64 {
|
||||||
|
return (*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetCreationEpoch()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setCreationEpoch(v uint64) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
SetCreationEpoch(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPayloadChecksum returns checksum of the object payload.
|
||||||
|
func (o *rwObject) GetPayloadChecksum() *pkg.Checksum {
|
||||||
|
return pkg.NewChecksumFromV2(
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetPayloadHash(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setPayloadChecksum(v *pkg.Checksum) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
SetPayloadHash(v.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPayloadHomomorphicHash returns homomorphic hash of the object payload.
|
||||||
|
func (o *rwObject) GetPayloadHomomorphicHash() *pkg.Checksum {
|
||||||
|
return pkg.NewChecksumFromV2(
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetHomomorphicHash(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setPayloadHomomorphicHash(v *pkg.Checksum) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
SetHomomorphicHash(v.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAttributes returns object attributes.
|
||||||
|
func (o *rwObject) GetAttributes() []*Attribute {
|
||||||
|
attrs := (*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetAttributes()
|
||||||
|
|
||||||
|
res := make([]*Attribute, 0, len(attrs))
|
||||||
|
|
||||||
|
for i := range attrs {
|
||||||
|
res = append(res, NewAttributeFromV2(attrs[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setAttributes(v ...*Attribute) {
|
||||||
|
h := (*object.Object)(o).
|
||||||
|
GetHeader()
|
||||||
|
|
||||||
|
attrs := make([]*object.Attribute, 0, len(v))
|
||||||
|
|
||||||
|
for i := range v {
|
||||||
|
attrs = append(attrs, v[i].ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
h.SetAttributes(attrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPreviousID returns identifier of the previous sibling object.
|
||||||
|
func (o *rwObject) GetPreviousID() *ID {
|
||||||
|
return NewIDFromV2(
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetSplit().
|
||||||
|
GetPrevious(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setPreviousID(v *ID) {
|
||||||
|
(*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetSplit().
|
||||||
|
SetPrevious(v.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChildren return list of the identifiers of the child objects.
|
||||||
|
func (o *rwObject) GetChildren() []*ID {
|
||||||
|
ids := (*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetSplit().
|
||||||
|
GetChildren()
|
||||||
|
|
||||||
|
res := make([]*ID, 0, len(ids))
|
||||||
|
|
||||||
|
for i := range ids {
|
||||||
|
res = append(res, NewIDFromV2(ids[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setChildren(v ...*ID) {
|
||||||
|
h := (*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetSplit()
|
||||||
|
|
||||||
|
ids := make([]*refs.ObjectID, 0, len(v))
|
||||||
|
|
||||||
|
for i := range v {
|
||||||
|
ids = append(ids, v[i].ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
h.SetChildren(ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetParent returns parent object w/o payload.
|
||||||
|
func (o *rwObject) GetParent() *Object {
|
||||||
|
h := (*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetSplit()
|
||||||
|
|
||||||
|
oV2 := new(object.Object)
|
||||||
|
oV2.SetObjectID(h.GetParent())
|
||||||
|
oV2.SetSignature(h.GetParentSignature())
|
||||||
|
oV2.SetHeader(h.GetParentHeader())
|
||||||
|
|
||||||
|
return NewFromV2(oV2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *rwObject) setParent(v *Object) {
|
||||||
|
h := (*object.Object)(o).
|
||||||
|
GetHeader().
|
||||||
|
GetSplit()
|
||||||
|
|
||||||
|
h.SetParent((*object.Object)(v.rwObject).GetObjectID())
|
||||||
|
h.SetParentSignature((*object.Object)(v.rwObject).GetSignature())
|
||||||
|
h.SetParentHeader((*object.Object)(v.rwObject).GetHeader())
|
||||||
|
}
|
Loading…
Reference in a new issue