forked from TrueCloudLab/frostfs-api-go
[#168] acl: Implement binary/JSON encoders/decoders on Table
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
ae68790bbd
commit
233756ca8f
6 changed files with 117 additions and 96 deletions
|
@ -111,3 +111,47 @@ func NewTableFromV2(table *v2acl.Table) *Table {
|
|||
|
||||
return t
|
||||
}
|
||||
|
||||
// Marshal marshals Table into a protobuf binary form.
|
||||
//
|
||||
// Buffer is allocated when the argument is empty.
|
||||
// Otherwise, the first buffer is used.
|
||||
func (t *Table) Marshal(b ...[]byte) ([]byte, error) {
|
||||
var buf []byte
|
||||
if len(b) > 0 {
|
||||
buf = b[0]
|
||||
}
|
||||
|
||||
return t.ToV2().
|
||||
StableMarshal(buf)
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals protobuf binary representation of Table.
|
||||
func (t *Table) Unmarshal(data []byte) error {
|
||||
fV2 := new(v2acl.Table)
|
||||
if err := fV2.Unmarshal(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*t = *NewTableFromV2(fV2)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON encodes Table to protobuf JSON format.
|
||||
func (t *Table) MarshalJSON() ([]byte, error) {
|
||||
return t.ToV2().
|
||||
MarshalJSON()
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes Table from protobuf JSON format.
|
||||
func (t *Table) UnmarshalJSON(data []byte) error {
|
||||
tV2 := new(v2acl.Table)
|
||||
if err := tV2.UnmarshalJSON(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*t = *NewTableFromV2(tV2)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -78,3 +78,30 @@ func TestTable_AddRecord(t *testing.T) {
|
|||
|
||||
require.Equal(t, records, table.Records())
|
||||
}
|
||||
|
||||
func TestRecordEncoding(t *testing.T) {
|
||||
tab := eacl.NewTable()
|
||||
tab.AddRecord(
|
||||
eacl.CreateRecord(eacl.ActionDeny, eacl.OperationHead),
|
||||
)
|
||||
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
data, err := tab.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
tab2 := eacl.NewTable()
|
||||
require.NoError(t, tab2.Unmarshal(data))
|
||||
|
||||
require.Equal(t, tab, tab2)
|
||||
})
|
||||
|
||||
t.Run("json", func(t *testing.T) {
|
||||
data, err := tab.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
r2 := eacl.NewTable()
|
||||
require.NoError(t, r2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, tab, r2)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,54 +11,6 @@ var (
|
|||
errEmptyInput = errors.New("empty input")
|
||||
)
|
||||
|
||||
func RecordToJSON(r *Record) ([]byte, error) {
|
||||
if r == nil {
|
||||
return nil, errEmptyInput
|
||||
}
|
||||
|
||||
msg := RecordToGRPCMessage(r)
|
||||
|
||||
return protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(msg)
|
||||
}
|
||||
|
||||
func RecordFromJSON(data []byte) (*Record, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errEmptyInput
|
||||
}
|
||||
|
||||
msg := new(acl.EACLRecord)
|
||||
|
||||
if err := protojson.Unmarshal(data, msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return RecordFromGRPCMessage(msg), nil
|
||||
}
|
||||
|
||||
func TableToJSON(t *Table) ([]byte, error) {
|
||||
if t == nil {
|
||||
return nil, errEmptyInput
|
||||
}
|
||||
|
||||
msg := TableToGRPCMessage(t)
|
||||
|
||||
return protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(msg)
|
||||
}
|
||||
|
||||
func TableFromJSON(data []byte) (*Table, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errEmptyInput
|
||||
}
|
||||
|
||||
msg := new(acl.EACLTable)
|
||||
|
||||
if err := protojson.Unmarshal(data, msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return TableFromGRPCMessage(msg), nil
|
||||
}
|
||||
|
||||
func BearerTokenToJSON(t *BearerToken) ([]byte, error) {
|
||||
if t == nil {
|
||||
return nil, errEmptyInput
|
||||
|
@ -142,3 +94,23 @@ func (r *Record) UnmarshalJSON(data []byte) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Table) MarshalJSON() ([]byte, error) {
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
TableToGRPCMessage(t),
|
||||
)
|
||||
}
|
||||
|
||||
func (t *Table) UnmarshalJSON(data []byte) error {
|
||||
msg := new(acl.EACLTable)
|
||||
|
||||
if err := protojson.Unmarshal(data, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*t = *TableFromGRPCMessage(msg)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,50 +7,6 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRecordJSON(t *testing.T) {
|
||||
exp := generateRecord(false)
|
||||
|
||||
t.Run("non empty", func(t *testing.T) {
|
||||
data, err := acl.RecordToJSON(exp)
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := acl.RecordFromJSON(data)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, exp, got)
|
||||
})
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
_, err := acl.RecordToJSON(nil)
|
||||
require.Error(t, err)
|
||||
|
||||
_, err = acl.RecordFromJSON(nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestEACLTableJSON(t *testing.T) {
|
||||
exp := generateEACL()
|
||||
|
||||
t.Run("non empty", func(t *testing.T) {
|
||||
data, err := acl.TableToJSON(exp)
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := acl.TableFromJSON(data)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, exp, got)
|
||||
})
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
_, err := acl.TableToJSON(nil)
|
||||
require.Error(t, err)
|
||||
|
||||
_, err = acl.TableFromJSON(nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestBearerTokenJSON(t *testing.T) {
|
||||
exp := generateBearerToken("token")
|
||||
|
||||
|
@ -88,3 +44,16 @@ func TestTargetJSON(t *testing.T) {
|
|||
|
||||
require.Equal(t, tar, tar2)
|
||||
}
|
||||
|
||||
func TestTable_MarshalJSON(t *testing.T) {
|
||||
tab := new(acl.Table)
|
||||
tab.SetRecords([]*acl.Record{generateRecord(false)})
|
||||
|
||||
data, err := tab.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
tab2 := new(acl.Table)
|
||||
require.NoError(t, tab2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, tab, tab2)
|
||||
}
|
||||
|
|
|
@ -94,6 +94,17 @@ func (t *Table) StableSize() (size int) {
|
|||
return size
|
||||
}
|
||||
|
||||
func (t *Table) Unmarshal(data []byte) error {
|
||||
m := new(acl.EACLTable)
|
||||
if err := proto.Unmarshal(data, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*t = *TableFromGRPCMessage(m)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StableMarshal marshals unified acl record structure in a protobuf
|
||||
// compatible way without field order shuffle.
|
||||
func (r *Record) StableMarshal(buf []byte) ([]byte, error) {
|
||||
|
|
|
@ -170,7 +170,6 @@ func TestRecord_StableMarshal(t *testing.T) {
|
|||
|
||||
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)
|
||||
|
@ -190,10 +189,9 @@ func TestTable_StableMarshal(t *testing.T) {
|
|||
wire, err := tableFrom.StableMarshal(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = goproto.Unmarshal(wire, transport)
|
||||
require.NoError(t, err)
|
||||
tableTo := new(acl.Table)
|
||||
require.NoError(t, tableTo.Unmarshal(wire))
|
||||
|
||||
tableTo := acl.TableFromGRPCMessage(transport)
|
||||
require.Equal(t, tableFrom, tableTo)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue