[#64] core/object: Implement tombstone content messages
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
6ee908c2db
commit
21bdc82fb5
2 changed files with 206 additions and 0 deletions
163
pkg/core/object/tombstone.go
Normal file
163
pkg/core/object/tombstone.go
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/util/proto"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FIXME: replace this code to neofs-api-go
|
||||||
|
|
||||||
|
const addrListField = 1
|
||||||
|
|
||||||
|
type TombstoneContent TombstoneContentV2
|
||||||
|
|
||||||
|
type TombstoneContentV2 struct {
|
||||||
|
addrList []*refs.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTombstoneContentFromV2(cV2 *TombstoneContentV2) *TombstoneContent {
|
||||||
|
return (*TombstoneContent)(cV2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTombstoneContent() *TombstoneContent {
|
||||||
|
return NewTombstoneContentFromV2(new(TombstoneContentV2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TombstoneContent) MarshalBinary() ([]byte, error) {
|
||||||
|
return c.ToV2().StableMarshal(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TombstoneContent) SetAddressList(v ...*object.Address) {
|
||||||
|
if c != nil {
|
||||||
|
addrV2 := make([]*refs.Address, 0, len(v))
|
||||||
|
|
||||||
|
for i := range v {
|
||||||
|
addrV2 = append(addrV2, v[i].ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
(*TombstoneContentV2)(c).SetAddressList(addrV2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TombstoneContent) GetAddressList() []*object.Address {
|
||||||
|
if c != nil {
|
||||||
|
addrV2 := (*TombstoneContentV2)(c).GetAddressList()
|
||||||
|
addr := make([]*object.Address, 0, len(addrV2))
|
||||||
|
|
||||||
|
for i := range addrV2 {
|
||||||
|
addr = append(addr, object.NewAddressFromV2(addrV2[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TombstoneContent) ToV2() *TombstoneContentV2 {
|
||||||
|
return (*TombstoneContentV2)(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TombstoneContentV2) StableMarshal(buf []byte) ([]byte, error) {
|
||||||
|
if c == nil {
|
||||||
|
return make([]byte, 0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, c.StableSize())
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := 0
|
||||||
|
|
||||||
|
for i := range c.addrList {
|
||||||
|
n, err := proto.NestedStructureMarshal(addrListField, buf[offset:], c.addrList[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += n
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TombstoneContentV2) StableSize() (sz int) {
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range c.addrList {
|
||||||
|
sz += proto.NestedStructureSize(addrListField, c.addrList[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TombstoneContentV2) StableUnmarshal(data []byte) error {
|
||||||
|
c.addrList = c.addrList[:0]
|
||||||
|
|
||||||
|
for len(data) > 0 {
|
||||||
|
expPrefix, _ := proto.NestedStructurePrefix(addrListField)
|
||||||
|
|
||||||
|
prefix, ln := binary.Uvarint(data)
|
||||||
|
if ln <= 0 {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
} else if expPrefix != prefix {
|
||||||
|
return errors.Errorf("wrong prefix %d", prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
data = data[ln:]
|
||||||
|
|
||||||
|
sz, ln := binary.Uvarint(data)
|
||||||
|
if ln <= 0 {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
|
||||||
|
data = data[ln:]
|
||||||
|
|
||||||
|
addr := new(refs.Address)
|
||||||
|
if err := addr.StableUnmarshal(data[:sz]); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.addrList = append(c.addrList, addr)
|
||||||
|
|
||||||
|
data = data[sz:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TombstoneContentV2) SetAddressList(v []*refs.Address) {
|
||||||
|
if c != nil {
|
||||||
|
c.addrList = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TombstoneContentV2) GetAddressList() []*refs.Address {
|
||||||
|
if c != nil {
|
||||||
|
return c.addrList
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TombstoneContentFromBytes(data []byte) (*TombstoneContent, error) {
|
||||||
|
if len(data) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cV2 := new(TombstoneContentV2)
|
||||||
|
if err := cV2.StableUnmarshal(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewTombstoneContentFromV2(cV2), nil
|
||||||
|
}
|
43
pkg/core/object/tombstone_test.go
Normal file
43
pkg/core/object/tombstone_test.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTombstoneContent_MarshalBinary(t *testing.T) {
|
||||||
|
cid1 := container.NewID()
|
||||||
|
cid1.SetSHA256([sha256.Size]byte{1, 2})
|
||||||
|
|
||||||
|
id1 := object.NewID()
|
||||||
|
id1.SetSHA256([sha256.Size]byte{3, 4})
|
||||||
|
|
||||||
|
addr1 := object.NewAddress()
|
||||||
|
addr1.SetObjectID(id1)
|
||||||
|
addr1.SetContainerID(cid1)
|
||||||
|
|
||||||
|
cid2 := container.NewID()
|
||||||
|
cid2.SetSHA256([sha256.Size]byte{5, 6})
|
||||||
|
|
||||||
|
id2 := object.NewID()
|
||||||
|
id2.SetSHA256([sha256.Size]byte{7, 8})
|
||||||
|
|
||||||
|
addr2 := object.NewAddress()
|
||||||
|
addr2.SetObjectID(id2)
|
||||||
|
addr2.SetContainerID(cid2)
|
||||||
|
|
||||||
|
c := NewTombstoneContent()
|
||||||
|
c.SetAddressList(addr1, addr2)
|
||||||
|
|
||||||
|
data, err := c.MarshalBinary()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
c2, err := TombstoneContentFromBytes(data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, c, c2)
|
||||||
|
}
|
Loading…
Reference in a new issue