Compare commits

..

1 commit

Author SHA1 Message Date
799def09a7 Verif 2023-07-18 16:00:11 +03:00
47 changed files with 441 additions and 161 deletions

View file

@ -1,21 +0,0 @@
name: DCO action
on: [pull_request]
jobs:
dco:
name: DCO
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: '1.21'
- name: Run commit format checker
uses: https://git.frostfs.info/TrueCloudLab/dco-go@v2
with:
from: 'origin/${{ github.event.pull_request.base.ref }}'

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
acl/grpc/types.pb.go generated

Binary file not shown.

BIN
audit/grpc/types.pb.go generated

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

2
go.mod
View file

@ -1,6 +1,6 @@
module git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 module git.frostfs.info/TrueCloudLab/frostfs-api-go/v2
go 1.20 go 1.19
require ( require (
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0

15
internal/random/rand.go Normal file
View file

@ -0,0 +1,15 @@
package random
import (
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
// Uint32 returns random uint32 value [0, max).
func Uint32(max uint32) uint32 {
return rand.Uint32() % max
}

BIN
lock/grpc/types.pb.go generated

Binary file not shown.

View file

@ -198,7 +198,6 @@ func (p *PlacementPolicy) ToGRPCMessage() grpc.Message {
m.SetSelectors(SelectorsToGRPC(p.selectors)) m.SetSelectors(SelectorsToGRPC(p.selectors))
m.SetReplicas(ReplicasToGRPC(p.replicas)) m.SetReplicas(ReplicasToGRPC(p.replicas))
m.SetContainerBackupFactor(p.backupFactor) m.SetContainerBackupFactor(p.backupFactor)
m.SetUnique(p.unique)
} }
return m return m
@ -229,8 +228,6 @@ func (p *PlacementPolicy) FromGRPCMessage(m grpc.Message) error {
p.backupFactor = v.GetContainerBackupFactor() p.backupFactor = v.GetContainerBackupFactor()
p.unique = v.GetUnique()
return nil return nil
} }

Binary file not shown.

Binary file not shown.

View file

@ -20,11 +20,6 @@ func (m *PlacementPolicy) SetFilters(v []*Filter) {
m.Filters = v m.Filters = v
} }
// SetUnique of placement policy.
func (m *PlacementPolicy) SetUnique(unique bool) {
m.Unique = unique
}
// SetName of placement filter. // SetName of placement filter.
func (m *Filter) SetName(v string) { func (m *Filter) SetName(v string) {
m.Name = v m.Name = v

BIN
netmap/grpc/types.pb.go generated

Binary file not shown.

View file

@ -65,10 +65,6 @@ func (f *Filter) StableMarshal(buf []byte) []byte {
} }
func (f *Filter) StableSize() (size int) { func (f *Filter) StableSize() (size int) {
if f == nil {
return 0
}
size += protoutil.StringSize(nameFilterField, f.name) size += protoutil.StringSize(nameFilterField, f.name)
size += protoutil.StringSize(keyFilterField, f.key) size += protoutil.StringSize(keyFilterField, f.key)
size += protoutil.EnumSize(opFilterField, int32(f.op)) size += protoutil.EnumSize(opFilterField, int32(f.op))
@ -105,10 +101,6 @@ func (s *Selector) StableMarshal(buf []byte) []byte {
} }
func (s *Selector) StableSize() (size int) { func (s *Selector) StableSize() (size int) {
if s == nil {
return 0
}
size += protoutil.StringSize(nameSelectorField, s.name) size += protoutil.StringSize(nameSelectorField, s.name)
size += protoutil.UInt32Size(countSelectorField, s.count) size += protoutil.UInt32Size(countSelectorField, s.count)
size += protoutil.EnumSize(countSelectorField, int32(s.clause)) size += protoutil.EnumSize(countSelectorField, int32(s.clause))
@ -140,10 +132,6 @@ func (r *Replica) StableMarshal(buf []byte) []byte {
} }
func (r *Replica) StableSize() (size int) { func (r *Replica) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.UInt32Size(countReplicaField, r.count) size += protoutil.UInt32Size(countReplicaField, r.count)
size += protoutil.StringSize(selectorReplicaField, r.selector) size += protoutil.StringSize(selectorReplicaField, r.selector)
@ -185,10 +173,6 @@ func (p *PlacementPolicy) StableMarshal(buf []byte) []byte {
} }
func (p *PlacementPolicy) StableSize() (size int) { func (p *PlacementPolicy) StableSize() (size int) {
if p == nil {
return 0
}
for i := range p.replicas { for i := range p.replicas {
size += protoutil.NestedStructureSize(replicasPolicyField, &p.replicas[i]) size += protoutil.NestedStructureSize(replicasPolicyField, &p.replicas[i])
} }

View file

@ -102,7 +102,6 @@ func GeneratePlacementPolicy(empty bool) *netmap.PlacementPolicy {
m.SetFilters(GenerateFilters(false)) m.SetFilters(GenerateFilters(false))
m.SetSelectors(GenerateSelectors(false)) m.SetSelectors(GenerateSelectors(false))
m.SetReplicas(GenerateReplicas(false)) m.SetReplicas(GenerateReplicas(false))
m.SetUnique(true)
} }
return m return m

Binary file not shown.

Binary file not shown.

BIN
object/grpc/types.pb.go generated

Binary file not shown.

View file

@ -1,9 +1,7 @@
package objecttest package objecttest
import ( import (
"math/rand" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/internal/random"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test" refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test"
@ -188,7 +186,7 @@ func GenerateGetResponseBody(empty bool) *object.GetResponseBody {
m := new(object.GetResponseBody) m := new(object.GetResponseBody)
if !empty { if !empty {
switch randomInt(3) { switch random.Uint32(3) {
case 0: case 0:
m.SetObjectPart(GenerateGetObjectPartInit(false)) m.SetObjectPart(GenerateGetObjectPartInit(false))
case 1: case 1:
@ -242,7 +240,7 @@ func GeneratePutRequestBody(empty bool) *object.PutRequestBody {
m := new(object.PutRequestBody) m := new(object.PutRequestBody)
if !empty { if !empty {
switch randomInt(2) { switch random.Uint32(2) {
case 0: case 0:
m.SetObjectPart(GeneratePutObjectPartInit(false)) m.SetObjectPart(GeneratePutObjectPartInit(false))
case 1: case 1:
@ -364,7 +362,7 @@ func GenerateHeadResponseBody(empty bool) *object.HeadResponseBody {
m := new(object.HeadResponseBody) m := new(object.HeadResponseBody)
if !empty { if !empty {
switch randomInt(3) { switch random.Uint32(3) {
case 0: case 0:
m.SetHeaderPart(GenerateHeaderWithSignature(false)) m.SetHeaderPart(GenerateHeaderWithSignature(false))
case 1: case 1:
@ -526,7 +524,7 @@ func GenerateGetRangeResponseBody(empty bool) *object.GetRangeResponseBody {
m := new(object.GetRangeResponseBody) m := new(object.GetRangeResponseBody)
if !empty { if !empty {
switch randomInt(2) { switch random.Uint32(2) {
case 0: case 0:
m.SetRangePart(GenerateGetRangePartChunk(false)) m.SetRangePart(GenerateGetRangePartChunk(false))
case 1: case 1:
@ -644,7 +642,3 @@ func GeneratePutSingleResponse(empty bool) *object.PutSingleResponse {
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
return m return m
} }
func randomInt(n int) int {
return rand.New(rand.NewSource(time.Now().UnixNano())).Intn(n)
}

View file

@ -324,7 +324,7 @@ type PutSingleResponse struct {
const ( const (
TypeRegular Type = iota TypeRegular Type = iota
TypeTombstone TypeTombstone
_ TypeStorageGroup
TypeLock TypeLock
) )

BIN
refs/grpc/types.pb.go generated

Binary file not shown.

View file

@ -6,7 +6,6 @@ import (
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc" refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto"
"google.golang.org/protobuf/encoding/protowire"
) )
const ( const (
@ -117,7 +116,7 @@ func (o *ObjectID) StableSize() int {
// ObjectIDNestedListMarshal writes protobuf repeated ObjectID field // ObjectIDNestedListMarshal writes protobuf repeated ObjectID field
// with fNum number to buf. // with fNum number to buf.
func ObjectIDNestedListMarshal(fNum int64, buf []byte, ids []ObjectID) (off int) { func ObjectIDNestedListMarshal(fNum int64, buf []byte, ids []ObjectID) (off int) {
prefix := protowire.EncodeTag(protowire.Number(fNum), protowire.BytesType) prefix, _ := proto.NestedStructurePrefix(fNum)
for i := range ids { for i := range ids {
off += binary.PutUvarint(buf[off:], prefix) off += binary.PutUvarint(buf[off:], prefix)

View file

@ -17,7 +17,6 @@ type jsonMessage interface {
type binaryMessage interface { type binaryMessage interface {
StableMarshal([]byte) []byte StableMarshal([]byte) []byte
StableSize() int
Unmarshal([]byte) error Unmarshal([]byte) error
} }
@ -54,11 +53,6 @@ func TestRPCMessage(t *testing.T, msgGens ...func(empty bool) message.Message) {
} }
if bm, ok := msg.(binaryMessage); ok { if bm, ok := msg.(binaryMessage); ok {
t.Run(fmt.Sprintf("%T.StableSize() does no allocations", bm), func(t *testing.T) {
require.Zero(t, testing.AllocsPerRun(1000, func() {
_ = bm.StableSize()
}))
})
t.Run(fmt.Sprintf("Binary_%T", msg), func(t *testing.T) { t.Run(fmt.Sprintf("Binary_%T", msg), func(t *testing.T) {
data := bm.StableMarshal(nil) data := bm.StableMarshal(nil)

Binary file not shown.

Binary file not shown.

BIN
session/grpc/types.pb.go generated

Binary file not shown.

View file

@ -211,7 +211,7 @@ func (c *ObjectSessionContext) StableMarshal(buf []byte) []byte {
} }
offset := proto.EnumMarshal(objectCtxVerbField, buf, int32(c.verb)) offset := proto.EnumMarshal(objectCtxVerbField, buf, int32(c.verb))
proto.NestedStructureMarshal(objectCtxTargetField, buf[offset:], objectSessionContextTarget{ proto.NestedStructureMarshal(objectCtxTargetField, buf[offset:], &objectSessionContextTarget{
cnr: c.cnr, cnr: c.cnr,
objs: c.objs, objs: c.objs,
}) })
@ -225,7 +225,7 @@ func (c *ObjectSessionContext) StableSize() (size int) {
} }
size += proto.EnumSize(objectCtxVerbField, int32(c.verb)) size += proto.EnumSize(objectCtxVerbField, int32(c.verb))
size += proto.NestedStructureSize(objectCtxTargetField, objectSessionContextTarget{ size += proto.NestedStructureSize(objectCtxTargetField, &objectSessionContextTarget{
cnr: c.cnr, cnr: c.cnr,
objs: c.objs, objs: c.objs,
}) })

View file

@ -1,10 +1,8 @@
package sessiontest package sessiontest
import ( import (
"math/rand"
"time"
acltest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/test" acltest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/test"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/internal/random"
refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test" refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
statustest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/test" statustest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/test"
@ -169,7 +167,7 @@ func GenerateSessionTokenBody(empty bool) *session.TokenBody {
m.SetOwnerID(refstest.GenerateOwnerID(false)) m.SetOwnerID(refstest.GenerateOwnerID(false))
m.SetLifetime(GenerateTokenLifetime(false)) m.SetLifetime(GenerateTokenLifetime(false))
switch randomInt(2) { switch random.Uint32(2) {
case 0: case 0:
m.SetContext(GenerateObjectSessionContext(false)) m.SetContext(GenerateObjectSessionContext(false))
case 1: case 1:
@ -238,7 +236,3 @@ func GenerateXHeaders(empty bool) []session.XHeader {
return xs return xs
} }
func randomInt(n int) int {
return rand.New(rand.NewSource(time.Now().UnixNano())).Intn(n)
}

View file

@ -50,6 +50,10 @@ func signServiceRequest(key *ecdsa.PrivateKey, v serviceRequest) error {
if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil { if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil {
return err return err
} }
if err := verifyServiceMessagePart(body, result.GetBodySignature); err != nil {
return fmt.Errorf("DEBUG POINT: could not verify body: %w", err)
}
result.SetOrigin(header) result.SetOrigin(header)
v.SetVerificationHeader(result) v.SetVerificationHeader(result)
return nil return nil

BIN
status/grpc/types.pb.go generated

Binary file not shown.

View file

@ -30,10 +30,6 @@ func (x *Detail) StableMarshal(buf []byte) []byte {
} }
func (x *Detail) StableSize() (size int) { func (x *Detail) StableSize() (size int) {
if x == nil {
return 0
}
size += protoutil.UInt32Size(detailIDFNum, x.id) size += protoutil.UInt32Size(detailIDFNum, x.id)
size += protoutil.BytesSize(detailValueFNum, x.val) size += protoutil.BytesSize(detailValueFNum, x.val)
@ -73,10 +69,6 @@ func (x *Status) StableMarshal(buf []byte) []byte {
} }
func (x *Status) StableSize() (size int) { func (x *Status) StableSize() (size int) {
if x == nil {
return 0
}
size += protoutil.UInt32Size(statusCodeFNum, CodeToGRPC(x.code)) size += protoutil.UInt32Size(statusCodeFNum, CodeToGRPC(x.code))
size += protoutil.StringSize(statusMsgFNum, x.msg) size += protoutil.StringSize(statusMsgFNum, x.msg)

59
storagegroup/convert.go Normal file
View file

@ -0,0 +1,59 @@
package storagegroup
import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
sg "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup/grpc"
)
func (s *StorageGroup) ToGRPCMessage() grpc.Message {
m := new(sg.StorageGroup)
if s != nil {
m = new(sg.StorageGroup)
m.SetMembers(refs.ObjectIDListToGRPCMessage(s.members))
//nolint:staticcheck
m.SetExpirationEpoch(s.exp)
m.SetValidationDataSize(s.size)
m.SetValidationHash(s.hash.ToGRPCMessage().(*refsGRPC.Checksum))
}
return m
}
func (s *StorageGroup) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*sg.StorageGroup)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
hash := v.GetValidationHash()
if hash == nil {
s.hash = nil
} else {
if s.hash == nil {
s.hash = new(refs.Checksum)
}
err = s.hash.FromGRPCMessage(hash)
if err != nil {
return err
}
}
s.members, err = refs.ObjectIDListFromGRPCMessage(v.GetMembers())
if err != nil {
return err
}
//nolint:staticcheck
s.exp = v.GetExpirationEpoch()
s.size = v.GetValidationDataSize()
return nil
}

View file

@ -0,0 +1,27 @@
package storagegroup
import (
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
)
// SetValidationDataSize sets the total size of the payloads of the storage group.
func (m *StorageGroup) SetValidationDataSize(v uint64) {
m.ValidationDataSize = v
}
// SetValidationHash sets total homomorphic hash of the storage group payloads.
func (m *StorageGroup) SetValidationHash(v *refs.Checksum) {
m.ValidationHash = v
}
// SetExpirationEpoch sets number of the last epoch of the storage group lifetime.
//
// Deprecated: do not use, `expiration_epoch` field is deprecated in protocol.
func (m *StorageGroup) SetExpirationEpoch(v uint64) {
m.ExpirationEpoch = v
}
// SetMembers sets list of the identifiers of the storage group members.
func (m *StorageGroup) SetMembers(v []*refs.ObjectID) {
m.Members = v
}

BIN
storagegroup/grpc/types.pb.go generated Normal file

Binary file not shown.

14
storagegroup/json.go Normal file
View file

@ -0,0 +1,14 @@
package storagegroup
import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
storagegroup "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup/grpc"
)
func (s *StorageGroup) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(s)
}
func (s *StorageGroup) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(s, data, new(storagegroup.StorageGroup))
}

54
storagegroup/marshal.go Normal file
View file

@ -0,0 +1,54 @@
package storagegroup
import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
storagegroup "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto"
)
const (
sizeField = 1
hashField = 2
expirationField = 3
objectIDsField = 4
)
// StableMarshal marshals unified storage group structure in a protobuf
// compatible way without field order shuffle.
func (s *StorageGroup) StableMarshal(buf []byte) []byte {
if s == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, s.StableSize())
}
var offset int
offset += proto.UInt64Marshal(sizeField, buf[offset:], s.size)
offset += proto.NestedStructureMarshal(hashField, buf[offset:], s.hash)
offset += proto.UInt64Marshal(expirationField, buf[offset:], s.exp)
refs.ObjectIDNestedListMarshal(objectIDsField, buf[offset:], s.members)
return buf
}
// StableSize of storage group structure marshalled by StableMarshal function.
func (s *StorageGroup) StableSize() (size int) {
if s == nil {
return 0
}
size += proto.UInt64Size(sizeField, s.size)
size += proto.NestedStructureSize(hashField, s.hash)
size += proto.UInt64Size(expirationField, s.exp)
size += refs.ObjectIDNestedListSize(objectIDsField, s.members)
return size
}
func (s *StorageGroup) Unmarshal(data []byte) error {
return message.Unmarshal(s, data, new(storagegroup.StorageGroup))
}

View file

@ -0,0 +1,15 @@
package storagegroup_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
messagetest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message/test"
storagegrouptest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup/test"
)
func TestMessageConvert(t *testing.T) {
messagetest.TestRPCMessage(t,
func(empty bool) message.Message { return storagegrouptest.GenerateStorageGroup(empty) },
)
}

View file

@ -0,0 +1,21 @@
package storagegrouptest
import (
refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup"
)
func GenerateStorageGroup(empty bool) *storagegroup.StorageGroup {
m := new(storagegroup.StorageGroup)
if !empty {
m.SetValidationDataSize(44)
//nolint:staticcheck
m.SetExpirationEpoch(55)
m.SetMembers(refstest.GenerateObjectIDs(false))
}
m.SetValidationHash(refstest.GenerateChecksum(empty))
return m
}

79
storagegroup/types.go Normal file
View file

@ -0,0 +1,79 @@
package storagegroup
import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
)
// StorageGroup is a unified structure of StorageGroup
// message from proto definition.
type StorageGroup struct {
size uint64
hash *refs.Checksum
exp uint64
members []refs.ObjectID
}
// GetValidationDataSize of unified storage group structure.
func (s *StorageGroup) GetValidationDataSize() uint64 {
if s != nil {
return s.size
}
return 0
}
// SetValidationDataSize into unified storage group structure.
func (s *StorageGroup) SetValidationDataSize(v uint64) {
s.size = v
}
// GetValidationHash of unified storage group structure.
func (s *StorageGroup) GetValidationHash() *refs.Checksum {
if s != nil {
return s.hash
}
return nil
}
// SetValidationHash into unified storage group structure.
func (s *StorageGroup) SetValidationHash(v *refs.Checksum) {
s.hash = v
}
// GetExpirationEpoch of unified storage group structure.
//
// Deprecated: Do not use.
func (s *StorageGroup) GetExpirationEpoch() uint64 {
if s != nil {
return s.exp
}
return 0
}
// SetExpirationEpoch into unified storage group structure.
//
// Deprecated: Do not use.
func (s *StorageGroup) SetExpirationEpoch(v uint64) {
s.exp = v
}
// GetMembers of unified storage group structure. Members are objects of
// storage group.
func (s *StorageGroup) GetMembers() []refs.ObjectID {
if s != nil {
return s.members
}
return nil
}
// SetMembers into unified storage group structure. Members are objects of
// storage group.
func (s *StorageGroup) SetMembers(v []refs.ObjectID) {
s.members = v
}

Binary file not shown.

View file

@ -10,8 +10,7 @@ import (
"encoding/binary" "encoding/binary"
"math" "math"
"math/bits" "math/bits"
"reflect"
"google.golang.org/protobuf/encoding/protowire"
) )
type ( type (
@ -22,22 +21,14 @@ type (
) )
func BytesMarshal(field int, buf, v []byte) int { func BytesMarshal(field int, buf, v []byte) int {
return bytesMarshal(field, buf, v)
}
func BytesSize(field int, v []byte) int {
return bytesSize(field, v)
}
func bytesMarshal[T ~[]byte | ~string](field int, buf []byte, v T) int {
if len(v) == 0 { if len(v) == 0 {
return 0 return 0
} }
return bytesMarshalNoCheck(field, buf, v) return bytesMarshal(field, buf, v)
} }
func bytesMarshalNoCheck[T ~[]byte | ~string](field int, buf []byte, v T) int { func bytesMarshal(field int, buf, v []byte) int {
prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) prefix := field<<3 | 0x2
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
@ -48,23 +39,26 @@ func bytesMarshalNoCheck[T ~[]byte | ~string](field int, buf []byte, v T) int {
return i return i
} }
func bytesSize[T ~[]byte | ~string](field int, v T) int { func BytesSize(field int, v []byte) int {
if len(v) == 0 { ln := len(v)
if ln == 0 {
return 0 return 0
} }
return bytesSizeNoCheck(field, v) return bytesSize(field, v)
} }
func bytesSizeNoCheck[T ~[]byte | ~string](field int, v T) int { func bytesSize(field int, v []byte) int {
return protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(len(v))) prefix := field<<3 | 0x2
return VarUIntSize(uint64(prefix)) + VarUIntSize(uint64(len(v))) + len(v)
} }
func StringMarshal(field int, buf []byte, v string) int { func StringMarshal(field int, buf []byte, v string) int {
return bytesMarshal(field, buf, v) return BytesMarshal(field, buf, []byte(v))
} }
func StringSize(field int, v string) int { func StringSize(field int, v string) int {
return bytesSize(field, v) return BytesSize(field, []byte(v))
} }
func BoolMarshal(field int, buf []byte, v bool) int { func BoolMarshal(field int, buf []byte, v bool) int {
@ -72,13 +66,12 @@ func BoolMarshal(field int, buf []byte, v bool) int {
return 0 return 0
} }
prefix := protowire.EncodeTag(protowire.Number(field), protowire.VarintType) prefix := field << 3
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
i := binary.PutUvarint(buf, uint64(prefix)) i := binary.PutUvarint(buf, uint64(prefix))
const boolTrueValue = 0x1 buf[i] = 0x1
buf[i] = boolTrueValue
return i + 1 return i + 1
} }
@ -87,8 +80,10 @@ func BoolSize(field int, v bool) int {
if !v { if !v {
return 0 return 0
} }
const boolLength = 1
return protowire.SizeGroup(protowire.Number(field), boolLength) prefix := field << 3
return VarUIntSize(uint64(prefix)) + 1 // bool is always 1 byte long
} }
func UInt64Marshal(field int, buf []byte, v uint64) int { func UInt64Marshal(field int, buf []byte, v uint64) int {
@ -96,7 +91,7 @@ func UInt64Marshal(field int, buf []byte, v uint64) int {
return 0 return 0
} }
prefix := protowire.EncodeTag(protowire.Number(field), protowire.VarintType) prefix := field << 3
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
@ -110,7 +105,10 @@ func UInt64Size(field int, v uint64) int {
if v == 0 { if v == 0 {
return 0 return 0
} }
return protowire.SizeGroup(protowire.Number(field), protowire.SizeVarint(v))
prefix := field << 3
return VarUIntSize(uint64(prefix)) + VarUIntSize(v)
} }
func Int64Marshal(field int, buf []byte, v int64) int { func Int64Marshal(field int, buf []byte, v int64) int {
@ -149,7 +147,7 @@ func RepeatedBytesMarshal(field int, buf []byte, v [][]byte) int {
var offset int var offset int
for i := range v { for i := range v {
offset += bytesMarshalNoCheck(field, buf[offset:], v[i]) offset += bytesMarshal(field, buf[offset:], v[i])
} }
return offset return offset
@ -157,7 +155,7 @@ func RepeatedBytesMarshal(field int, buf []byte, v [][]byte) int {
func RepeatedBytesSize(field int, v [][]byte) (size int) { func RepeatedBytesSize(field int, v [][]byte) (size int) {
for i := range v { for i := range v {
size += bytesSizeNoCheck(field, v[i]) size += bytesSize(field, v[i])
} }
return size return size
@ -167,7 +165,7 @@ func RepeatedStringMarshal(field int, buf []byte, v []string) int {
var offset int var offset int
for i := range v { for i := range v {
offset += bytesMarshalNoCheck(field, buf[offset:], v[i]) offset += bytesMarshal(field, buf[offset:], []byte(v[i]))
} }
return offset return offset
@ -175,73 +173,123 @@ func RepeatedStringMarshal(field int, buf []byte, v []string) int {
func RepeatedStringSize(field int, v []string) (size int) { func RepeatedStringSize(field int, v []string) (size int) {
for i := range v { for i := range v {
size += bytesSizeNoCheck(field, v[i]) size += bytesSize(field, []byte(v[i]))
} }
return size return size
} }
func repeatedUIntSize[T ~uint64 | ~int64 | ~uint32 | ~int32](field int, v []T) (size, arraySize int) { func RepeatedUInt64Marshal(field int, buf []byte, v []uint64) int {
if len(v) == 0 {
return 0, 0
}
for i := range v {
arraySize += protowire.SizeVarint(uint64(v[i]))
}
size = protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(arraySize))
return
}
func repeatedUIntMarshal[T ~uint64 | ~int64 | ~uint32 | ~int32](field int, buf []byte, v []T) int {
if len(v) == 0 { if len(v) == 0 {
return 0 return 0
} }
prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) prefix := field<<3 | 0x02
offset := binary.PutUvarint(buf, uint64(prefix)) offset := binary.PutUvarint(buf, uint64(prefix))
_, arrSize := repeatedUIntSize(field, v) _, arrSize := RepeatedUInt64Size(field, v)
offset += binary.PutUvarint(buf[offset:], uint64(arrSize)) offset += binary.PutUvarint(buf[offset:], uint64(arrSize))
for i := range v { for i := range v {
offset += binary.PutUvarint(buf[offset:], uint64(v[i])) offset += binary.PutUvarint(buf[offset:], v[i])
} }
return offset return offset
} }
func RepeatedUInt64Marshal(field int, buf []byte, v []uint64) int { func RepeatedUInt64Size(field int, v []uint64) (size, arraySize int) {
return repeatedUIntMarshal(field, buf, v) if len(v) == 0 {
return 0, 0
} }
func RepeatedUInt64Size(field int, v []uint64) (size, arraySize int) { for i := range v {
return repeatedUIntSize(field, v) size += VarUIntSize(v[i])
}
arraySize = size
size += VarUIntSize(uint64(size))
prefix := field<<3 | 0x2
size += VarUIntSize(uint64(prefix))
return size, arraySize
} }
func RepeatedInt64Marshal(field int, buf []byte, v []int64) int { func RepeatedInt64Marshal(field int, buf []byte, v []int64) int {
return repeatedUIntMarshal(field, buf, v) if len(v) == 0 {
return 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Marshal(field, buf, convert)
} }
func RepeatedInt64Size(field int, v []int64) (size, arraySize int) { func RepeatedInt64Size(field int, v []int64) (size, arraySize int) {
return repeatedUIntSize(field, v) if len(v) == 0 {
return 0, 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Size(field, convert)
} }
func RepeatedUInt32Marshal(field int, buf []byte, v []uint32) int { func RepeatedUInt32Marshal(field int, buf []byte, v []uint32) int {
return repeatedUIntMarshal(field, buf, v) if len(v) == 0 {
return 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Marshal(field, buf, convert)
} }
func RepeatedUInt32Size(field int, v []uint32) (size, arraySize int) { func RepeatedUInt32Size(field int, v []uint32) (size, arraySize int) {
return repeatedUIntSize(field, v) if len(v) == 0 {
return 0, 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Size(field, convert)
} }
func RepeatedInt32Marshal(field int, buf []byte, v []int32) int { func RepeatedInt32Marshal(field int, buf []byte, v []int32) int {
return repeatedUIntMarshal(field, buf, v) if len(v) == 0 {
return 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Marshal(field, buf, convert)
} }
func RepeatedInt32Size(field int, v []int32) (size, arraySize int) { func RepeatedInt32Size(field int, v []int32) (size, arraySize int) {
return repeatedUIntSize(field, v) if len(v) == 0 {
return 0, 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Size(field, convert)
} }
// VarUIntSize returns length of varint byte sequence for uint64 value 'x'. // VarUIntSize returns length of varint byte sequence for uint64 value 'x'.
@ -249,27 +297,36 @@ func VarUIntSize(x uint64) int {
return (bits.Len64(x|1) + 6) / 7 return (bits.Len64(x|1) + 6) / 7
} }
func NestedStructureMarshal[T stableMarshaller](field int64, buf []byte, v T) int { func NestedStructurePrefix(field int64) (prefix uint64, ln int) {
n := v.StableSize() prefix = uint64(field<<3 | 0x02)
if n == 0 { return prefix, VarUIntSize(prefix)
}
func NestedStructureMarshal(field int64, buf []byte, v stableMarshaller) int {
if v == nil || reflect.ValueOf(v).IsNil() {
return 0 return 0
} }
prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) prefix, _ := NestedStructurePrefix(field)
offset := binary.PutUvarint(buf, prefix) offset := binary.PutUvarint(buf, prefix)
n := v.StableSize()
offset += binary.PutUvarint(buf[offset:], uint64(n)) offset += binary.PutUvarint(buf[offset:], uint64(n))
v.StableMarshal(buf[offset:]) v.StableMarshal(buf[offset:])
return offset + n return offset + n
} }
func NestedStructureSize[T stableMarshaller](field int64, v T) (size int) { func NestedStructureSize(field int64, v stableMarshaller) (size int) {
n := v.StableSize() if v == nil || reflect.ValueOf(v).IsNil() {
if n == 0 {
return 0 return 0
} }
size = protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(n))
return _, ln := NestedStructurePrefix(field)
n := v.StableSize()
size = ln + VarUIntSize(uint64(n)) + n
return size
} }
func Fixed64Marshal(field int, buf []byte, v uint64) int { func Fixed64Marshal(field int, buf []byte, v uint64) int {
@ -277,7 +334,7 @@ func Fixed64Marshal(field int, buf []byte, v uint64) int {
return 0 return 0
} }
prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed64Type) prefix := field<<3 | 1
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
@ -291,7 +348,10 @@ func Fixed64Size(fNum int, v uint64) int {
if v == 0 { if v == 0 {
return 0 return 0
} }
return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed64())
prefix := fNum<<3 | 1
return VarUIntSize(uint64(prefix)) + 8
} }
func Float64Marshal(field int, buf []byte, v float64) int { func Float64Marshal(field int, buf []byte, v float64) int {
@ -299,7 +359,7 @@ func Float64Marshal(field int, buf []byte, v float64) int {
return 0 return 0
} }
prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed64Type) prefix := field<<3 | 1
i := binary.PutUvarint(buf, uint64(prefix)) i := binary.PutUvarint(buf, uint64(prefix))
binary.LittleEndian.PutUint64(buf[i:], math.Float64bits(v)) binary.LittleEndian.PutUint64(buf[i:], math.Float64bits(v))
@ -311,7 +371,10 @@ func Float64Size(fNum int, v float64) int {
if v == 0 { if v == 0 {
return 0 return 0
} }
return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed64())
prefix := fNum<<3 | 1
return VarUIntSize(uint64(prefix)) + 8
} }
// Fixed32Marshal encodes uint32 value to Protocol Buffers fixed32 field with specified number, // Fixed32Marshal encodes uint32 value to Protocol Buffers fixed32 field with specified number,
@ -323,7 +386,7 @@ func Fixed32Marshal(field int, buf []byte, v uint32) int {
return 0 return 0
} }
prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed32Type) prefix := field<<3 | 5
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
@ -339,5 +402,8 @@ func Fixed32Size(fNum int, v uint32) int {
if v == 0 { if v == 0 {
return 0 return 0
} }
return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed32())
prefix := fNum<<3 | 5
return VarUIntSize(uint64(prefix)) + 4
} }

Binary file not shown.

View file

@ -59,7 +59,6 @@ func emitMessage(g *protogen.GeneratedFile, msg *protogen.Message) {
g.P("//") g.P("//")
g.P("// Structures with the same field values have the same binary size.") g.P("// Structures with the same field values have the same binary size.")
g.P("func (x *", msg.GoIdent.GoName, ") StableSize() (size int) {") g.P("func (x *", msg.GoIdent.GoName, ") StableSize() (size int) {")
g.P("if x == nil { return 0 }")
if len(fs) != 0 { if len(fs) != 0 {
for _, f := range fs { for _, f := range fs {
if f.Desc.IsList() && marshalers[f.Desc.Kind()].RepeatedDouble { if f.Desc.IsList() && marshalers[f.Desc.Kind()].RepeatedDouble {