diff --git a/v2/acl/marshal.go b/v2/acl/marshal.go index b1b6dcb..e4cb2e9 100644 --- a/v2/acl/marshal.go +++ b/v2/acl/marshal.go @@ -7,26 +7,91 @@ import ( ) const ( - FilterHeaderTypeField = 1 - FilterMatchTypeField = 2 - FilterNameField = 3 - FilterValueField = 4 + filterHeaderTypeField = 1 + filterMatchTypeField = 2 + filterNameField = 3 + filterValueField = 4 - TargetTypeField = 1 - TargetKeysField = 2 + targetTypeField = 1 + targetKeysField = 2 - RecordOperationField = 1 - RecordActionField = 2 - RecordFiltersField = 3 - RecordTargetsField = 4 + recordOperationField = 1 + recordActionField = 2 + recordFiltersField = 3 + recordTargetsField = 4 + + tableContainerIDField = 1 + tableRecordsField = 2 ) func (t *Table) StableMarshal(buf []byte) ([]byte, error) { - panic("not implemented") + if t == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var ( + offset, n int + prefix uint64 + err error + ) + + if t.cid != nil { + prefix, _ = proto.NestedStructurePrefix(tableContainerIDField) + offset += binary.PutUvarint(buf[offset:], prefix) + + n = t.cid.StableSize() + offset += binary.PutUvarint(buf[offset:], uint64(n)) + + _, err = t.cid.StableMarshal(buf[offset:]) + if err != nil { + return nil, err + } + + offset += n + } + + prefix, _ = proto.NestedStructurePrefix(tableRecordsField) + + for i := range t.records { + offset += binary.PutUvarint(buf[offset:], prefix) + + n = t.records[i].StableSize() + offset += binary.PutUvarint(buf[offset:], uint64(n)) + + _, err = t.records[i].StableMarshal(buf[offset:]) + if err != nil { + return nil, err + } + + offset += n + } + + return buf, nil } -func (t *Table) StableSize() int { - panic("not implemented") +func (t *Table) StableSize() (size int) { + if t == nil { + return 0 + } + + if t.cid != nil { + _, ln := proto.NestedStructurePrefix(tableContainerIDField) + n := t.cid.StableSize() + size += ln + proto.VarUIntSize(uint64(n)) + n + } + + _, ln := proto.NestedStructurePrefix(tableRecordsField) + + for i := range t.records { + n := t.records[i].StableSize() + size += ln + proto.VarUIntSize(uint64(n)) + n + } + + return size } func (r *Record) StableMarshal(buf []byte) ([]byte, error) { @@ -44,21 +109,21 @@ func (r *Record) StableMarshal(buf []byte) ([]byte, error) { err error ) - n, err = proto.EnumMarshal(RecordOperationField, buf, int32(r.op)) + n, err = proto.EnumMarshal(recordOperationField, buf, int32(r.op)) if err != nil { return nil, err } offset += n - n, err = proto.EnumMarshal(RecordActionField, buf[offset:], int32(r.action)) + n, err = proto.EnumMarshal(recordActionField, buf[offset:], int32(r.action)) if err != nil { return nil, err } offset += n - prefix, _ = proto.NestedStructurePrefix(RecordFiltersField) + prefix, _ = proto.NestedStructurePrefix(recordFiltersField) for i := range r.filters { offset += binary.PutUvarint(buf[offset:], prefix) @@ -74,7 +139,7 @@ func (r *Record) StableMarshal(buf []byte) ([]byte, error) { offset += n } - prefix, _ = proto.NestedStructurePrefix(RecordTargetsField) + prefix, _ = proto.NestedStructurePrefix(recordTargetsField) for i := range r.targets { offset += binary.PutUvarint(buf[offset:], prefix) @@ -98,17 +163,17 @@ func (r *Record) StableSize() (size int) { return 0 } - size += proto.EnumSize(RecordOperationField, int32(r.op)) - size += proto.EnumSize(RecordActionField, int32(r.op)) + size += proto.EnumSize(recordOperationField, int32(r.op)) + size += proto.EnumSize(recordActionField, int32(r.op)) - _, ln := proto.NestedStructurePrefix(RecordFiltersField) + _, ln := proto.NestedStructurePrefix(recordFiltersField) for i := range r.filters { n := r.filters[i].StableSize() size += ln + proto.VarUIntSize(uint64(n)) + n } - _, ln = proto.NestedStructurePrefix(RecordTargetsField) + _, ln = proto.NestedStructurePrefix(recordTargetsField) for i := range r.targets { n := r.targets[i].StableSize() @@ -132,28 +197,28 @@ func (f *HeaderFilter) StableMarshal(buf []byte) ([]byte, error) { err error ) - n, err = proto.EnumMarshal(FilterHeaderTypeField, buf, int32(f.hdrType)) + n, err = proto.EnumMarshal(filterHeaderTypeField, buf, int32(f.hdrType)) if err != nil { return nil, err } offset += n - n, err = proto.EnumMarshal(FilterMatchTypeField, buf[offset:], int32(f.matchType)) + n, err = proto.EnumMarshal(filterMatchTypeField, buf[offset:], int32(f.matchType)) if err != nil { return nil, err } offset += n - n, err = proto.StringMarshal(FilterNameField, buf[offset:], f.name) + n, err = proto.StringMarshal(filterNameField, buf[offset:], f.name) if err != nil { return nil, err } offset += n - n, err = proto.StringMarshal(FilterValueField, buf[offset:], f.value) + n, err = proto.StringMarshal(filterValueField, buf[offset:], f.value) if err != nil { return nil, err } @@ -166,10 +231,10 @@ func (f *HeaderFilter) StableSize() (size int) { return 0 } - size += proto.EnumSize(FilterHeaderTypeField, int32(f.hdrType)) - size += proto.EnumSize(FilterMatchTypeField, int32(f.matchType)) - size += proto.StringSize(FilterNameField, f.name) - size += proto.StringSize(FilterValueField, f.value) + size += proto.EnumSize(filterHeaderTypeField, int32(f.hdrType)) + size += proto.EnumSize(filterMatchTypeField, int32(f.matchType)) + size += proto.StringSize(filterNameField, f.name) + size += proto.StringSize(filterValueField, f.value) return size } @@ -188,14 +253,14 @@ func (t *TargetInfo) StableMarshal(buf []byte) ([]byte, error) { err error ) - n, err = proto.EnumMarshal(TargetTypeField, buf, int32(t.target)) + n, err = proto.EnumMarshal(targetTypeField, buf, int32(t.target)) if err != nil { return nil, err } offset += n - n, err = proto.RepeatedBytesMarshal(TargetKeysField, buf[offset:], t.keys) + n, err = proto.RepeatedBytesMarshal(targetKeysField, buf[offset:], t.keys) if err != nil { return nil, err } @@ -208,8 +273,8 @@ func (t *TargetInfo) StableSize() (size int) { return 0 } - size += proto.EnumSize(TargetTypeField, int32(t.target)) - size += proto.RepeatedBytesSize(TargetKeysField, t.keys) + size += proto.EnumSize(targetTypeField, int32(t.target)) + size += proto.RepeatedBytesSize(targetKeysField, t.keys) return size } diff --git a/v2/acl/marshal_test.go b/v2/acl/marshal_test.go index eea5d04..8874ccd 100644 --- a/v2/acl/marshal_test.go +++ b/v2/acl/marshal_test.go @@ -6,6 +6,7 @@ import ( "github.com/nspcc-dev/neofs-api-go/v2/acl" grpc "github.com/nspcc-dev/neofs-api-go/v2/acl/grpc" + "github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/stretchr/testify/require" ) @@ -120,3 +121,28 @@ func TestRecord_StableMarshal(t *testing.T) { require.Equal(t, recordFrom, recordTo) }) } + +func TestTable_StableMarshal(t *testing.T) { + tableFrom := new(acl.Table) + transport := new(grpc.EACLTable) + + t.Run("non empty", func(t *testing.T) { + cid := new(refs.ContainerID) + cid.SetValue([]byte("Container ID")) + + r1 := generateRecord(false) + r2 := generateRecord(true) + + tableFrom.SetContainerID(cid) + tableFrom.SetRecords([]*acl.Record{r1, r2}) + + wire, err := tableFrom.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + tableTo := acl.TableFromGRPCMessage(transport) + require.Equal(t, tableFrom, tableTo) + }) +}