Implementing proto.Clone

This commit is contained in:
Evgeniy Kulikov 2020-07-03 09:12:02 +03:00
parent 2456521240
commit d45548c43b
No known key found for this signature in database
GPG key ID: BF6AEE0A2A699BF2
11 changed files with 129 additions and 10 deletions

View file

@ -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)

View file

@ -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) }

View file

@ -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
} }

View file

@ -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.

View file

@ -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())
}
}) })
} }

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -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())
} }

View file

@ -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
}
}

View file

@ -3,6 +3,7 @@ package service
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"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"
) )
@ -104,6 +105,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.