forked from TrueCloudLab/policy-engine
[#1] chain: Add json marshal/unmarshal
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
58386edf58
commit
88c2a476b0
10 changed files with 856 additions and 51 deletions
257
pkg/chain/marshal_binary.go
Normal file
257
pkg/chain/marshal_binary.go
Normal file
|
@ -0,0 +1,257 @@
|
|||
package chain
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/marshal"
|
||||
)
|
||||
|
||||
const (
|
||||
ChainMarshalVersion uint8 = 0 // increase if breaking change
|
||||
)
|
||||
|
||||
var (
|
||||
_ encoding.BinaryMarshaler = (*Chain)(nil)
|
||||
_ encoding.BinaryUnmarshaler = (*Chain)(nil)
|
||||
)
|
||||
|
||||
func (c *Chain) MarshalBinary() ([]byte, error) {
|
||||
s := marshal.UInt8Size // Marshaller version
|
||||
s += marshal.UInt8Size // Chain version
|
||||
s += marshal.StringSize(string(c.ID))
|
||||
s += marshal.SliceSize(c.Rules, ruleSize)
|
||||
s += marshal.UInt8Size // MatchType
|
||||
|
||||
buf := make([]byte, s)
|
||||
var offset int
|
||||
var err error
|
||||
offset, err = marshal.UInt8Marshal(buf, offset, marshal.Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err = marshal.UInt8Marshal(buf, offset, ChainMarshalVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err = marshal.StringMarshal(buf, offset, string(c.ID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err = marshal.SliceMarshal(buf, offset, c.Rules, marshalRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err = marshal.UInt8Marshal(buf, offset, uint8(c.MatchType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := marshal.VerifyMarshal(buf, offset); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (c *Chain) UnmarshalBinary(data []byte) error {
|
||||
var offset int
|
||||
|
||||
marshallerVersion, offset, err := marshal.UInt8Unmarshal(data, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if marshallerVersion != marshal.Version {
|
||||
return fmt.Errorf("unsupported marshaller version %d", marshallerVersion)
|
||||
}
|
||||
|
||||
chainVersion, offset, err := marshal.UInt8Unmarshal(data, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if chainVersion != ChainMarshalVersion {
|
||||
return fmt.Errorf("unsupported chain version %d", chainVersion)
|
||||
}
|
||||
|
||||
idStr, offset, err := marshal.StringUnmarshal(data, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.ID = ID(idStr)
|
||||
|
||||
c.Rules, offset, err = marshal.SliceUnmarshal(data, offset, unmarshalRule)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
matchTypeV, offset, err := marshal.UInt8Unmarshal(data, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.MatchType = MatchType(matchTypeV)
|
||||
|
||||
return marshal.VerifyUnmarshal(data, offset)
|
||||
}
|
||||
|
||||
func ruleSize(r Rule) int {
|
||||
s := marshal.ByteSize // Status
|
||||
s += actionsSize(r.Actions)
|
||||
s += resourcesSize(r.Resources)
|
||||
s += marshal.BoolSize // Any
|
||||
s += marshal.SliceSize(r.Condition, conditionSize)
|
||||
return s
|
||||
}
|
||||
|
||||
func marshalRule(buf []byte, offset int, r Rule) (int, error) {
|
||||
offset, err := marshal.ByteMarshal(buf, offset, byte(r.Status))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
offset, err = marshalActions(buf, offset, r.Actions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
offset, err = marshalResources(buf, offset, r.Resources)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
offset, err = marshal.BoolMarshal(buf, offset, r.Any)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return marshal.SliceMarshal(buf, offset, r.Condition, marshalCondition)
|
||||
}
|
||||
|
||||
func unmarshalRule(buf []byte, offset int) (Rule, int, error) {
|
||||
var r Rule
|
||||
statusV, offset, err := marshal.ByteUnmarshal(buf, offset)
|
||||
if err != nil {
|
||||
return Rule{}, 0, err
|
||||
}
|
||||
r.Status = Status(statusV)
|
||||
|
||||
r.Actions, offset, err = unmarshalActions(buf, offset)
|
||||
if err != nil {
|
||||
return Rule{}, 0, err
|
||||
}
|
||||
|
||||
r.Resources, offset, err = unmarshalResources(buf, offset)
|
||||
if err != nil {
|
||||
return Rule{}, 0, err
|
||||
}
|
||||
|
||||
r.Any, offset, err = marshal.BoolUnmarshal(buf, offset)
|
||||
if err != nil {
|
||||
return Rule{}, 0, err
|
||||
}
|
||||
|
||||
r.Condition, offset, err = marshal.SliceUnmarshal(buf, offset, unmarshalCondition)
|
||||
if err != nil {
|
||||
return Rule{}, 0, err
|
||||
}
|
||||
|
||||
return r, offset, nil
|
||||
}
|
||||
|
||||
func actionsSize(a Actions) int {
|
||||
return marshal.BoolSize + // Inverted
|
||||
marshal.SliceSize(a.Names, marshal.StringSize)
|
||||
}
|
||||
|
||||
func marshalActions(buf []byte, offset int, a Actions) (int, error) {
|
||||
offset, err := marshal.BoolMarshal(buf, offset, a.Inverted)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return marshal.SliceMarshal(buf, offset, a.Names, marshal.StringMarshal)
|
||||
}
|
||||
|
||||
func unmarshalActions(buf []byte, offset int) (Actions, int, error) {
|
||||
var a Actions
|
||||
var err error
|
||||
a.Inverted, offset, err = marshal.BoolUnmarshal(buf, offset)
|
||||
if err != nil {
|
||||
return Actions{}, 0, err
|
||||
}
|
||||
a.Names, offset, err = marshal.SliceUnmarshal(buf, offset, marshal.StringUnmarshal)
|
||||
if err != nil {
|
||||
return Actions{}, 0, err
|
||||
}
|
||||
return a, offset, nil
|
||||
}
|
||||
|
||||
func resourcesSize(r Resources) int {
|
||||
return marshal.BoolSize + // Inverted
|
||||
marshal.SliceSize(r.Names, marshal.StringSize)
|
||||
}
|
||||
|
||||
func marshalResources(buf []byte, offset int, r Resources) (int, error) {
|
||||
offset, err := marshal.BoolMarshal(buf, offset, r.Inverted)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return marshal.SliceMarshal(buf, offset, r.Names, marshal.StringMarshal)
|
||||
}
|
||||
|
||||
func unmarshalResources(buf []byte, offset int) (Resources, int, error) {
|
||||
var r Resources
|
||||
var err error
|
||||
r.Inverted, offset, err = marshal.BoolUnmarshal(buf, offset)
|
||||
if err != nil {
|
||||
return Resources{}, 0, err
|
||||
}
|
||||
r.Names, offset, err = marshal.SliceUnmarshal(buf, offset, marshal.StringUnmarshal)
|
||||
if err != nil {
|
||||
return Resources{}, 0, err
|
||||
}
|
||||
return r, offset, nil
|
||||
}
|
||||
|
||||
func conditionSize(c Condition) int {
|
||||
return marshal.ByteSize + // Op
|
||||
marshal.ByteSize + // Object
|
||||
marshal.StringSize(c.Key) +
|
||||
marshal.StringSize(c.Value)
|
||||
}
|
||||
|
||||
func marshalCondition(buf []byte, offset int, c Condition) (int, error) {
|
||||
offset, err := marshal.ByteMarshal(buf, offset, byte(c.Op))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
offset, err = marshal.ByteMarshal(buf, offset, byte(c.Object))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
offset, err = marshal.StringMarshal(buf, offset, c.Key)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return marshal.StringMarshal(buf, offset, c.Value)
|
||||
}
|
||||
|
||||
func unmarshalCondition(buf []byte, offset int) (Condition, int, error) {
|
||||
var c Condition
|
||||
opV, offset, err := marshal.ByteUnmarshal(buf, offset)
|
||||
if err != nil {
|
||||
return Condition{}, 0, err
|
||||
}
|
||||
c.Op = ConditionType(opV)
|
||||
|
||||
obV, offset, err := marshal.ByteUnmarshal(buf, offset)
|
||||
if err != nil {
|
||||
return Condition{}, 0, err
|
||||
}
|
||||
c.Object = ObjectType(obV)
|
||||
|
||||
c.Key, offset, err = marshal.StringUnmarshal(buf, offset)
|
||||
if err != nil {
|
||||
return Condition{}, 0, err
|
||||
}
|
||||
|
||||
c.Value, offset, err = marshal.StringUnmarshal(buf, offset)
|
||||
if err != nil {
|
||||
return Condition{}, 0, err
|
||||
}
|
||||
|
||||
return c, offset, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue