forked from TrueCloudLab/frostfs-api-go
Merge pull request #97 from nspcc-dev/ImplementingProtoClone
Implementing proto.Clone
This commit is contained in:
commit
8cb9ac0528
11 changed files with 129 additions and 10 deletions
|
@ -3,6 +3,7 @@ package container
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/nspcc-dev/neofs-api-go/internal"
|
"github.com/nspcc-dev/neofs-api-go/internal"
|
||||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||||
|
@ -63,6 +64,13 @@ func (m *Container) ID() (CID, error) {
|
||||||
return refs.CIDForBytes(data), nil
|
return refs.CIDForBytes(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge used by proto.Clone
|
||||||
|
func (m *Container) Merge(src proto.Message) {
|
||||||
|
if tmp, ok := src.(*Container); ok {
|
||||||
|
*m = *tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Empty checks that container is empty.
|
// Empty checks that container is empty.
|
||||||
func (m *Container) Empty() bool {
|
func (m *Container) Empty() bool {
|
||||||
return m.Capacity == 0 || bytes.Equal(m.Salt.Bytes(), emptySalt) || bytes.Equal(m.OwnerID.Bytes(), emptyOwner)
|
return m.Capacity == 0 || bytes.Equal(m.Salt.Bytes(), emptySalt) || bytes.Equal(m.OwnerID.Bytes(), emptyOwner)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package hash
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/mr-tron/base58"
|
"github.com/mr-tron/base58"
|
||||||
"github.com/nspcc-dev/neofs-api-go/internal"
|
"github.com/nspcc-dev/neofs-api-go/internal"
|
||||||
"github.com/nspcc-dev/tzhash/tz"
|
"github.com/nspcc-dev/tzhash/tz"
|
||||||
|
@ -78,6 +79,13 @@ func (h Hash) Validate(hashes []Hash) bool {
|
||||||
return err == nil && ok
|
return err == nil && ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge used by proto.Clone
|
||||||
|
func (h *Hash) Merge(src proto.Message) {
|
||||||
|
if tmp, ok := src.(*Hash); ok {
|
||||||
|
*h = *tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Sum returns Tillich-Zémor checksum of data.
|
// Sum returns Tillich-Zémor checksum of data.
|
||||||
func Sum(data []byte) Hash { return tz.Sum(data) }
|
func Sum(data []byte) Hash { return tz.Sum(data) }
|
||||||
|
|
||||||
|
|
|
@ -13,4 +13,7 @@ type Custom interface {
|
||||||
MarshalTo(data []byte) (int, error)
|
MarshalTo(data []byte) (int, error)
|
||||||
Unmarshal(data []byte) error
|
Unmarshal(data []byte) error
|
||||||
proto.Message
|
proto.Message
|
||||||
|
|
||||||
|
// Should contains for proto.Clone
|
||||||
|
proto.Merger
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,6 +163,13 @@ func (m *Object) SetHeader(h *Header) {
|
||||||
m.AddHeader(h)
|
m.AddHeader(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge used by proto.Clone
|
||||||
|
func (m *Object) Merge(src proto.Message) {
|
||||||
|
if tmp, ok := src.(*Object); ok {
|
||||||
|
tmp.CopyTo(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (m Header) typeOf(t isHeader_Value) (ok bool) {
|
func (m Header) typeOf(t isHeader_Value) (ok bool) {
|
||||||
switch t.(type) {
|
switch t.(type) {
|
||||||
case *Header_Link:
|
case *Header_Link:
|
||||||
|
@ -233,8 +240,15 @@ func (m *Object) Copy() (obj *Object) {
|
||||||
// This function creates copies on every available data slice.
|
// This function creates copies on every available data slice.
|
||||||
func (m *Object) CopyTo(o *Object) {
|
func (m *Object) CopyTo(o *Object) {
|
||||||
o.SystemHeader = m.SystemHeader
|
o.SystemHeader = m.SystemHeader
|
||||||
|
|
||||||
|
if m.Headers != nil {
|
||||||
o.Headers = make([]Header, len(m.Headers))
|
o.Headers = make([]Header, len(m.Headers))
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Payload != nil {
|
||||||
o.Payload = make([]byte, len(m.Payload))
|
o.Payload = make([]byte, len(m.Payload))
|
||||||
|
copy(o.Payload, m.Payload)
|
||||||
|
}
|
||||||
|
|
||||||
for i := range m.Headers {
|
for i := range m.Headers {
|
||||||
switch v := m.Headers[i].Value.(type) {
|
switch v := m.Headers[i].Value.(type) {
|
||||||
|
@ -246,23 +260,23 @@ func (m *Object) CopyTo(o *Object) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
case *Header_HomoHash:
|
case *Header_HomoHash:
|
||||||
|
hash := proto.Clone(&v.HomoHash).(*Hash)
|
||||||
o.Headers[i] = Header{
|
o.Headers[i] = Header{
|
||||||
Value: &Header_HomoHash{
|
Value: &Header_HomoHash{
|
||||||
HomoHash: v.HomoHash,
|
HomoHash: *hash,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
case *Header_Token:
|
case *Header_Token:
|
||||||
|
token := *v.Token
|
||||||
o.Headers[i] = Header{
|
o.Headers[i] = Header{
|
||||||
Value: &Header_Token{
|
Value: &Header_Token{
|
||||||
Token: v.Token,
|
Token: &token,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
o.Headers[i] = *proto.Clone(&m.Headers[i]).(*Header)
|
o.Headers[i] = *proto.Clone(&m.Headers[i]).(*Header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(o.Payload, m.Payload)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address returns object's address.
|
// Address returns object's address.
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||||
"github.com/nspcc-dev/neofs-api-go/service"
|
"github.com/nspcc-dev/neofs-api-go/service"
|
||||||
"github.com/nspcc-dev/neofs-api-go/storagegroup"
|
"github.com/nspcc-dev/neofs-api-go/storagegroup"
|
||||||
|
@ -192,11 +193,23 @@ func TestObject_Copy(t *testing.T) {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
{ // Copying
|
||||||
cp := obj.Copy()
|
cp := obj.Copy()
|
||||||
|
|
||||||
_, h := cp.LastHeader(HeaderType(TokenHdr))
|
_, h := cp.LastHeader(HeaderType(TokenHdr))
|
||||||
require.NotNil(t, h)
|
require.NotNil(t, h)
|
||||||
require.Equal(t, token, h.GetValue().(*Header_Token).Token)
|
require.Equal(t, token, h.GetValue().(*Header_Token).Token)
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Cloning
|
||||||
|
cl := proto.Clone(obj).(*Object)
|
||||||
|
require.Equal(t, obj, cl)
|
||||||
|
|
||||||
|
_, h := cl.LastHeader(HeaderType(TokenHdr))
|
||||||
|
h.GetToken().SetID(service.TokenID{3, 2, 1})
|
||||||
|
|
||||||
|
require.NotEqual(t, token, h.GetToken())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/nspcc-dev/neofs-api-go/internal"
|
"github.com/nspcc-dev/neofs-api-go/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -66,3 +67,14 @@ func (m Address) Hash() ([]byte, error) {
|
||||||
h := sha256.Sum256(append(m.ObjectID.Bytes(), m.CID.Bytes()...))
|
h := sha256.Sum256(append(m.ObjectID.Bytes(), m.CID.Bytes()...))
|
||||||
return h[:], nil
|
return h[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge used by proto.Clone
|
||||||
|
func (m *Address) Merge(src proto.Message) {
|
||||||
|
if addr, ok := src.(*Address); ok {
|
||||||
|
cid := proto.Clone(&addr.CID).(*CID)
|
||||||
|
oid := proto.Clone(&addr.ObjectID).(*ObjectID)
|
||||||
|
|
||||||
|
m.CID = *cid
|
||||||
|
m.ObjectID = *oid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/mr-tron/base58"
|
"github.com/mr-tron/base58"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
@ -94,3 +95,10 @@ func (c CID) Verify(data []byte) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge used by proto.Clone
|
||||||
|
func (c *CID) Merge(src proto.Message) {
|
||||||
|
if cid, ok := src.(*CID); ok {
|
||||||
|
*c = *cid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/mr-tron/base58"
|
"github.com/mr-tron/base58"
|
||||||
"github.com/nspcc-dev/neofs-api-go/chain"
|
"github.com/nspcc-dev/neofs-api-go/chain"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -63,3 +64,10 @@ func (o *OwnerID) Unmarshal(data []byte) error {
|
||||||
copy((*o)[:], data)
|
copy((*o)[:], data)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge used by proto.Clone
|
||||||
|
func (o *OwnerID) Merge(src proto.Message) {
|
||||||
|
if uid, ok := src.(*OwnerID); ok {
|
||||||
|
*o = *uid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,19 @@ func TestSGID(t *testing.T) {
|
||||||
require.NoError(t, sgid2.Unmarshal(data))
|
require.NoError(t, sgid2.Unmarshal(data))
|
||||||
require.Equal(t, sgid1, sgid2)
|
require.Equal(t, sgid1, sgid2)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("check that proto.Clone works like expected", func(t *testing.T) {
|
||||||
|
var (
|
||||||
|
sgid1 UUID
|
||||||
|
sgid2 *UUID
|
||||||
|
)
|
||||||
|
|
||||||
|
sgid1, err := NewSGID()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
sgid2 = proto.Clone(&sgid1).(*SGID)
|
||||||
|
require.Equal(t, sgid1, *sgid2)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUUID(t *testing.T) {
|
func TestUUID(t *testing.T) {
|
||||||
|
@ -80,6 +93,18 @@ func TestOwnerID(t *testing.T) {
|
||||||
require.NoError(t, u2.Unmarshal(data))
|
require.NoError(t, u2.Unmarshal(data))
|
||||||
require.Equal(t, u1, u2)
|
require.Equal(t, u1, u2)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("check that proto.Clone works like expected", func(t *testing.T) {
|
||||||
|
var u2 *OwnerID
|
||||||
|
|
||||||
|
key := test.DecodeKey(0)
|
||||||
|
|
||||||
|
u1, err := NewOwnerID(&key.PublicKey)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
u2 = proto.Clone(&u1).(*OwnerID)
|
||||||
|
require.Equal(t, u1, *u2)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddress(t *testing.T) {
|
func TestAddress(t *testing.T) {
|
||||||
|
@ -109,4 +134,8 @@ func TestAddress(t *testing.T) {
|
||||||
actual, err := ParseAddress(expect)
|
actual, err := ParseAddress(expect)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, expect, actual.String())
|
require.Equal(t, expect, actual.String())
|
||||||
|
|
||||||
|
addr := proto.Clone(actual).(*Address)
|
||||||
|
require.Equal(t, actual, addr)
|
||||||
|
require.Equal(t, expect, addr.String())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
@ -74,3 +75,10 @@ func (u *UUID) Parse(id string) error {
|
||||||
copy((*u)[:], tmp[:])
|
copy((*u)[:], tmp[:])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge used by proto.Clone
|
||||||
|
func (u *UUID) Merge(src proto.Message) {
|
||||||
|
if tmp, ok := src.(*UUID); ok {
|
||||||
|
*u = *tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/nspcc-dev/neofs-api-go/internal"
|
"github.com/nspcc-dev/neofs-api-go/internal"
|
||||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||||
)
|
)
|
||||||
|
@ -109,6 +110,13 @@ func (t testCustomField) MarshalTo(data []byte) (int, error) { return 0, nil }
|
||||||
// Marshal skip, it's for test usage only.
|
// Marshal skip, it's for test usage only.
|
||||||
func (t testCustomField) Marshal() ([]byte, error) { return nil, nil }
|
func (t testCustomField) Marshal() ([]byte, error) { return nil, nil }
|
||||||
|
|
||||||
|
// Merge used by proto.Clone
|
||||||
|
func (t *testCustomField) Merge(src proto.Message) {
|
||||||
|
if tmp, ok := src.(*testCustomField); ok {
|
||||||
|
*t = *tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetBearerToken wraps Bearer field and return BearerToken interface.
|
// GetBearerToken wraps Bearer field and return BearerToken interface.
|
||||||
//
|
//
|
||||||
// If Bearer field value is nil, nil returns.
|
// If Bearer field value is nil, nil returns.
|
||||||
|
|
Loading…
Reference in a new issue