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
14
Makefile
14
Makefile
|
@ -5,6 +5,8 @@ TMP_DIR := .cache
|
|||
OUTPUT_LINT_DIR ?= $(shell pwd)/bin
|
||||
LINT_VERSION ?= 1.55.1
|
||||
LINT_DIR = $(OUTPUT_LINT_DIR)/golangci-lint-$(LINT_VERSION)-v$(TRUECLOUDLAB_LINT_VERSION)
|
||||
EASYJSON_VERSION ?= $(shell go list -f '{{.Version}}' -m github.com/mailru/easyjson)
|
||||
EASYJSON_DIR ?= $(shell pwd)/bin/easyjson-$(EASYJSON_VERSION)
|
||||
|
||||
# Run all code formatters
|
||||
fmts: fmt imports
|
||||
|
@ -60,3 +62,15 @@ staticcheck-install:
|
|||
# Run staticcheck
|
||||
staticcheck-run:
|
||||
@staticcheck ./...
|
||||
|
||||
easyjson-install:
|
||||
@rm -rf $(EASYJSON_DIR)
|
||||
@mkdir -p $(EASYJSON_DIR)
|
||||
@GOBIN=$(EASYJSON_DIR) go install github.com/mailru/easyjson/...@$(EASYJSON_VERSION)
|
||||
|
||||
generate:
|
||||
@if [ ! -d "$(EASYJSON_DIR)" ]; then \
|
||||
make easyjson-install; \
|
||||
fi
|
||||
find ./ -name "_easyjson.go" -exec rm -rf {} \;
|
||||
$(EASYJSON_DIR)/easyjson ./pkg/chain/chain.go
|
2
go.mod
2
go.mod
|
@ -5,6 +5,7 @@ go 1.20
|
|||
require (
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231129062201-a1b61d394958
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/mailru/easyjson v0.7.7
|
||||
github.com/nspcc-dev/neo-go v0.103.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
|
||||
|
@ -14,6 +15,7 @@ require (
|
|||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
github.com/hashicorp/golang-lru v0.6.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 // indirect
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -11,6 +11,10 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
|||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4=
|
||||
github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg=
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package chain
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -23,6 +22,7 @@ const (
|
|||
MatchTypeFirstMatch MatchType = 1
|
||||
)
|
||||
|
||||
//easyjson:json
|
||||
type Chain struct {
|
||||
ID ID
|
||||
|
||||
|
@ -31,19 +31,6 @@ type Chain struct {
|
|||
MatchType MatchType
|
||||
}
|
||||
|
||||
func (id ID) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal([]byte(id))
|
||||
}
|
||||
|
||||
func (id *ID) UnmarshalJSON(data []byte) error {
|
||||
var idRaw []byte
|
||||
if err := json.Unmarshal(data, &idRaw); err != nil {
|
||||
return err
|
||||
}
|
||||
*id = ID(idRaw)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Chain) Bytes() []byte {
|
||||
data, err := c.MarshalBinary()
|
||||
if err != nil {
|
||||
|
@ -123,45 +110,36 @@ const (
|
|||
CondSliceContains
|
||||
)
|
||||
|
||||
var condToStr = []struct {
|
||||
ct ConditionType
|
||||
str string
|
||||
}{
|
||||
{CondStringEquals, "StringEquals"},
|
||||
{CondStringNotEquals, "StringNotEquals"},
|
||||
{CondStringEqualsIgnoreCase, "StringEqualsIgnoreCase"},
|
||||
{CondStringNotEqualsIgnoreCase, "StringNotEqualsIgnoreCase"},
|
||||
{CondStringLike, "StringLike"},
|
||||
{CondStringNotLike, "StringNotLike"},
|
||||
{CondStringLessThan, "StringLessThan"},
|
||||
{CondStringLessThanEquals, "StringLessThanEquals"},
|
||||
{CondStringGreaterThan, "StringGreaterThan"},
|
||||
{CondStringGreaterThanEquals, "StringGreaterThanEquals"},
|
||||
{CondNumericEquals, "NumericEquals"},
|
||||
{CondNumericNotEquals, "NumericNotEquals"},
|
||||
{CondNumericLessThan, "NumericLessThan"},
|
||||
{CondNumericLessThanEquals, "NumericLessThanEquals"},
|
||||
{CondNumericGreaterThan, "NumericGreaterThan"},
|
||||
{CondNumericGreaterThanEquals, "NumericGreaterThanEquals"},
|
||||
{CondSliceContains, "SliceContains"},
|
||||
}
|
||||
|
||||
func (c ConditionType) String() string {
|
||||
switch c {
|
||||
case CondStringEquals:
|
||||
return "StringEquals"
|
||||
case CondStringNotEquals:
|
||||
return "StringNotEquals"
|
||||
case CondStringEqualsIgnoreCase:
|
||||
return "StringEqualsIgnoreCase"
|
||||
case CondStringNotEqualsIgnoreCase:
|
||||
return "StringNotEqualsIgnoreCase"
|
||||
case CondStringLike:
|
||||
return "StringLike"
|
||||
case CondStringNotLike:
|
||||
return "StringNotLike"
|
||||
case CondStringLessThan:
|
||||
return "StringLessThan"
|
||||
case CondStringLessThanEquals:
|
||||
return "StringLessThanEquals"
|
||||
case CondStringGreaterThan:
|
||||
return "StringGreaterThan"
|
||||
case CondStringGreaterThanEquals:
|
||||
return "StringGreaterThanEquals"
|
||||
case CondNumericEquals:
|
||||
return "NumericEquals"
|
||||
case CondNumericNotEquals:
|
||||
return "NumericNotEquals"
|
||||
case CondNumericLessThan:
|
||||
return "NumericLessThan"
|
||||
case CondNumericLessThanEquals:
|
||||
return "NumericLessThanEquals"
|
||||
case CondNumericGreaterThan:
|
||||
return "NumericGreaterThan"
|
||||
case CondNumericGreaterThanEquals:
|
||||
return "NumericGreaterThanEquals"
|
||||
case CondSliceContains:
|
||||
return "SliceContains"
|
||||
default:
|
||||
return "unknown condition type"
|
||||
for _, v := range condToStr {
|
||||
if v.ct == c {
|
||||
return v.str
|
||||
}
|
||||
}
|
||||
return "unknown condition type"
|
||||
}
|
||||
|
||||
const condSliceContainsDelimiter = "\x00"
|
||||
|
|
458
pkg/chain/chain_easyjson.go
Normal file
458
pkg/chain/chain_easyjson.go
Normal file
|
@ -0,0 +1,458 @@
|
|||
// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
|
||||
|
||||
package chain
|
||||
|
||||
import (
|
||||
json "encoding/json"
|
||||
easyjson "github.com/mailru/easyjson"
|
||||
jlexer "github.com/mailru/easyjson/jlexer"
|
||||
jwriter "github.com/mailru/easyjson/jwriter"
|
||||
)
|
||||
|
||||
// suppress unused package warning
|
||||
var (
|
||||
_ *json.RawMessage
|
||||
_ *jlexer.Lexer
|
||||
_ *jwriter.Writer
|
||||
_ easyjson.Marshaler
|
||||
)
|
||||
|
||||
func easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain(in *jlexer.Lexer, out *Chain) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
in.Skip()
|
||||
return
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
in.WantComma()
|
||||
continue
|
||||
}
|
||||
switch key {
|
||||
case "ID":
|
||||
(out.ID).UnmarshalEasyJSON(in)
|
||||
case "Rules":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.Rules = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.Rules == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Rules = make([]Rule, 0, 0)
|
||||
} else {
|
||||
out.Rules = []Rule{}
|
||||
}
|
||||
} else {
|
||||
out.Rules = (out.Rules)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v1 Rule
|
||||
easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain1(in, &v1)
|
||||
out.Rules = append(out.Rules, v1)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
case "MatchType":
|
||||
(out.MatchType).UnmarshalEasyJSON(in)
|
||||
default:
|
||||
in.SkipRecursive()
|
||||
}
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
}
|
||||
func easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain(out *jwriter.Writer, in Chain) {
|
||||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
{
|
||||
const prefix string = ",\"ID\":"
|
||||
out.RawString(prefix[1:])
|
||||
(in.ID).MarshalEasyJSON(out)
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Rules\":"
|
||||
out.RawString(prefix)
|
||||
if in.Rules == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 {
|
||||
out.RawString("null")
|
||||
} else {
|
||||
out.RawByte('[')
|
||||
for v2, v3 := range in.Rules {
|
||||
if v2 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain1(out, v3)
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"MatchType\":"
|
||||
out.RawString(prefix)
|
||||
(in.MatchType).MarshalEasyJSON(out)
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
|
||||
// MarshalJSON supports json.Marshaler interface
|
||||
func (v Chain) MarshalJSON() ([]byte, error) {
|
||||
w := jwriter.Writer{}
|
||||
easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain(&w, v)
|
||||
return w.Buffer.BuildBytes(), w.Error
|
||||
}
|
||||
|
||||
// MarshalEasyJSON supports easyjson.Marshaler interface
|
||||
func (v Chain) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain(w, v)
|
||||
}
|
||||
|
||||
// UnmarshalJSON supports json.Unmarshaler interface
|
||||
func (v *Chain) UnmarshalJSON(data []byte) error {
|
||||
r := jlexer.Lexer{Data: data}
|
||||
easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain(&r, v)
|
||||
return r.Error()
|
||||
}
|
||||
|
||||
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
|
||||
func (v *Chain) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain(l, v)
|
||||
}
|
||||
func easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain1(in *jlexer.Lexer, out *Rule) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
in.Skip()
|
||||
return
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
in.WantComma()
|
||||
continue
|
||||
}
|
||||
switch key {
|
||||
case "Status":
|
||||
(out.Status).UnmarshalEasyJSON(in)
|
||||
case "Actions":
|
||||
easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain2(in, &out.Actions)
|
||||
case "Resources":
|
||||
easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain3(in, &out.Resources)
|
||||
case "Any":
|
||||
out.Any = bool(in.Bool())
|
||||
case "Condition":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.Condition = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.Condition == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Condition = make([]Condition, 0, 1)
|
||||
} else {
|
||||
out.Condition = []Condition{}
|
||||
}
|
||||
} else {
|
||||
out.Condition = (out.Condition)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v4 Condition
|
||||
easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain4(in, &v4)
|
||||
out.Condition = append(out.Condition, v4)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
default:
|
||||
in.SkipRecursive()
|
||||
}
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
}
|
||||
func easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain1(out *jwriter.Writer, in Rule) {
|
||||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
{
|
||||
const prefix string = ",\"Status\":"
|
||||
out.RawString(prefix[1:])
|
||||
(in.Status).MarshalEasyJSON(out)
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Actions\":"
|
||||
out.RawString(prefix)
|
||||
easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain2(out, in.Actions)
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Resources\":"
|
||||
out.RawString(prefix)
|
||||
easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain3(out, in.Resources)
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Any\":"
|
||||
out.RawString(prefix)
|
||||
out.Bool(bool(in.Any))
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Condition\":"
|
||||
out.RawString(prefix)
|
||||
if in.Condition == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 {
|
||||
out.RawString("null")
|
||||
} else {
|
||||
out.RawByte('[')
|
||||
for v5, v6 := range in.Condition {
|
||||
if v5 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain4(out, v6)
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
func easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain4(in *jlexer.Lexer, out *Condition) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
in.Skip()
|
||||
return
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
in.WantComma()
|
||||
continue
|
||||
}
|
||||
switch key {
|
||||
case "Op":
|
||||
(out.Op).UnmarshalEasyJSON(in)
|
||||
case "Object":
|
||||
(out.Object).UnmarshalEasyJSON(in)
|
||||
case "Key":
|
||||
out.Key = string(in.String())
|
||||
case "Value":
|
||||
out.Value = string(in.String())
|
||||
default:
|
||||
in.SkipRecursive()
|
||||
}
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
}
|
||||
func easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain4(out *jwriter.Writer, in Condition) {
|
||||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
{
|
||||
const prefix string = ",\"Op\":"
|
||||
out.RawString(prefix[1:])
|
||||
(in.Op).MarshalEasyJSON(out)
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Object\":"
|
||||
out.RawString(prefix)
|
||||
(in.Object).MarshalEasyJSON(out)
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Key\":"
|
||||
out.RawString(prefix)
|
||||
out.String(string(in.Key))
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Value\":"
|
||||
out.RawString(prefix)
|
||||
out.String(string(in.Value))
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
func easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain3(in *jlexer.Lexer, out *Resources) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
in.Skip()
|
||||
return
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
in.WantComma()
|
||||
continue
|
||||
}
|
||||
switch key {
|
||||
case "Inverted":
|
||||
out.Inverted = bool(in.Bool())
|
||||
case "Names":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.Names = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.Names == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Names = make([]string, 0, 4)
|
||||
} else {
|
||||
out.Names = []string{}
|
||||
}
|
||||
} else {
|
||||
out.Names = (out.Names)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v7 string
|
||||
v7 = string(in.String())
|
||||
out.Names = append(out.Names, v7)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
default:
|
||||
in.SkipRecursive()
|
||||
}
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
}
|
||||
func easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain3(out *jwriter.Writer, in Resources) {
|
||||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
{
|
||||
const prefix string = ",\"Inverted\":"
|
||||
out.RawString(prefix[1:])
|
||||
out.Bool(bool(in.Inverted))
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Names\":"
|
||||
out.RawString(prefix)
|
||||
if in.Names == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 {
|
||||
out.RawString("null")
|
||||
} else {
|
||||
out.RawByte('[')
|
||||
for v8, v9 := range in.Names {
|
||||
if v8 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v9))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
func easyjsonE2758465DecodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain2(in *jlexer.Lexer, out *Actions) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
in.Skip()
|
||||
return
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
in.WantComma()
|
||||
continue
|
||||
}
|
||||
switch key {
|
||||
case "Inverted":
|
||||
out.Inverted = bool(in.Bool())
|
||||
case "Names":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.Names = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.Names == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Names = make([]string, 0, 4)
|
||||
} else {
|
||||
out.Names = []string{}
|
||||
}
|
||||
} else {
|
||||
out.Names = (out.Names)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v10 string
|
||||
v10 = string(in.String())
|
||||
out.Names = append(out.Names, v10)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
default:
|
||||
in.SkipRecursive()
|
||||
}
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
}
|
||||
func easyjsonE2758465EncodeGitFrostfsInfoTrueCloudLabPolicyEnginePkgChain2(out *jwriter.Writer, in Actions) {
|
||||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
{
|
||||
const prefix string = ",\"Inverted\":"
|
||||
out.RawString(prefix[1:])
|
||||
out.Bool(bool(in.Inverted))
|
||||
}
|
||||
{
|
||||
const prefix string = ",\"Names\":"
|
||||
out.RawString(prefix)
|
||||
if in.Names == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 {
|
||||
out.RawString("null")
|
||||
} else {
|
||||
out.RawByte('[')
|
||||
for v11, v12 := range in.Names {
|
||||
if v11 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v12))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
153
pkg/chain/marshal_json.go
Normal file
153
pkg/chain/marshal_json.go
Normal file
|
@ -0,0 +1,153 @@
|
|||
package chain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
jlexer "github.com/mailru/easyjson/jlexer"
|
||||
jwriter "github.com/mailru/easyjson/jwriter"
|
||||
)
|
||||
|
||||
// Run `make generate`` if types added or changed
|
||||
|
||||
var matchTypeToJSONValue = []struct {
|
||||
mt MatchType
|
||||
str string
|
||||
}{
|
||||
{MatchTypeDenyPriority, "DenyPriority"},
|
||||
{MatchTypeFirstMatch, "FirstMatch"},
|
||||
}
|
||||
|
||||
var statusToJSONValue = []struct {
|
||||
s Status
|
||||
str string
|
||||
}{
|
||||
{Allow, "Allow"},
|
||||
{NoRuleFound, "NoRuleFound"},
|
||||
{AccessDenied, "AccessDenied"},
|
||||
{QuotaLimitReached, "QuotaLimitReached"},
|
||||
}
|
||||
|
||||
var objectTypeToJSONValue = []struct {
|
||||
t ObjectType
|
||||
str string
|
||||
}{
|
||||
{ObjectRequest, "Request"},
|
||||
{ObjectResource, "Resource"},
|
||||
}
|
||||
|
||||
func (mt MatchType) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
for _, p := range matchTypeToJSONValue {
|
||||
if p.mt == mt {
|
||||
w.String(p.str)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.String(strconv.FormatUint(uint64(mt), 10))
|
||||
}
|
||||
|
||||
func (mt *MatchType) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
str := l.String()
|
||||
for _, p := range matchTypeToJSONValue {
|
||||
if p.str == str {
|
||||
*mt = p.mt
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
v, err := strconv.ParseUint(str, 10, 8)
|
||||
if err != nil {
|
||||
l.AddError(fmt.Errorf("failed to parse match type: %w", err))
|
||||
return
|
||||
}
|
||||
*mt = MatchType(v)
|
||||
}
|
||||
|
||||
func (st Status) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
for _, p := range statusToJSONValue {
|
||||
if p.s == st {
|
||||
w.String(p.str)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.String(strconv.FormatUint(uint64(st), 10))
|
||||
}
|
||||
|
||||
func (st *Status) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
str := l.String()
|
||||
for _, p := range statusToJSONValue {
|
||||
if p.str == str {
|
||||
*st = p.s
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
v, err := strconv.ParseUint(str, 10, 8)
|
||||
if err != nil {
|
||||
l.AddError(fmt.Errorf("failed to parse status: %w", err))
|
||||
return
|
||||
}
|
||||
*st = Status(v)
|
||||
}
|
||||
|
||||
func (ot ObjectType) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
for _, p := range objectTypeToJSONValue {
|
||||
if p.t == ot {
|
||||
w.String(p.str)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.String(strconv.FormatUint(uint64(ot), 10))
|
||||
}
|
||||
|
||||
func (ot *ObjectType) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
str := l.String()
|
||||
for _, p := range objectTypeToJSONValue {
|
||||
if p.str == str {
|
||||
*ot = p.t
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
v, err := strconv.ParseUint(str, 10, 8)
|
||||
if err != nil {
|
||||
l.AddError(fmt.Errorf("failed to parse object type: %w", err))
|
||||
return
|
||||
}
|
||||
*ot = ObjectType(v)
|
||||
}
|
||||
|
||||
func (ct ConditionType) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
for _, p := range condToStr {
|
||||
if p.ct == ct {
|
||||
w.String(p.str)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.String(strconv.FormatUint(uint64(ct), 10))
|
||||
}
|
||||
|
||||
func (ct *ConditionType) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
str := l.String()
|
||||
for _, p := range condToStr {
|
||||
if p.str == str {
|
||||
*ct = p.ct
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
v, err := strconv.ParseUint(str, 10, 8)
|
||||
if err != nil {
|
||||
l.AddError(fmt.Errorf("failed to parse condition type: %w", err))
|
||||
return
|
||||
}
|
||||
*ct = ConditionType(v)
|
||||
}
|
||||
|
||||
func (id ID) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
w.Base64Bytes([]byte(id))
|
||||
}
|
||||
|
||||
func (id *ID) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
*id = ID(l.Bytes())
|
||||
}
|
121
pkg/chain/marshal_json_test.go
Normal file
121
pkg/chain/marshal_json_test.go
Normal file
|
@ -0,0 +1,121 @@
|
|||
package chain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestID(t *testing.T) {
|
||||
key, err := keys.NewPrivateKeyFromWIF("L5eVx6HcHaFpQpvjQ3fy29uKDZ8rQ34bfMVx4XfZMm52EqafpNMg") // s3-gw key
|
||||
require.NoError(t, err)
|
||||
|
||||
chain1 := &Chain{ID: ID(key.PublicKey().GetScriptHash().BytesBE())}
|
||||
data := chain1.Bytes()
|
||||
|
||||
var chain2 Chain
|
||||
require.NoError(t, chain2.DecodeBytes(data))
|
||||
|
||||
require.Equal(t, chain1.ID, chain2.ID)
|
||||
|
||||
data, err = chain1.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, chain2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, chain1.ID, chain2.ID)
|
||||
}
|
||||
|
||||
func TestMatchTypeJson(t *testing.T) {
|
||||
for _, mt := range []MatchType{MatchTypeDenyPriority, MatchTypeFirstMatch, MatchType(100)} {
|
||||
var chain Chain
|
||||
chain.MatchType = mt
|
||||
|
||||
data, err := chain.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
if mt == MatchTypeDenyPriority {
|
||||
require.Equal(t, []byte("{\"ID\":\"\",\"Rules\":null,\"MatchType\":\"DenyPriority\"}"), data)
|
||||
} else if mt == MatchTypeFirstMatch {
|
||||
require.Equal(t, []byte("{\"ID\":\"\",\"Rules\":null,\"MatchType\":\"FirstMatch\"}"), data)
|
||||
} else {
|
||||
require.Equal(t, []byte(fmt.Sprintf("{\"ID\":\"\",\"Rules\":null,\"MatchType\":\"%d\"}", mt)), data)
|
||||
}
|
||||
|
||||
var parsed Chain
|
||||
require.NoError(t, parsed.UnmarshalJSON(data))
|
||||
require.Equal(t, chain, parsed)
|
||||
|
||||
require.Error(t, parsed.UnmarshalJSON([]byte("{\"ID\":\"\",\"Rules\":null,\"MatchType\":\"NotValid\"}")))
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonEnums(t *testing.T) {
|
||||
chain := Chain{
|
||||
ID: "2cca5ae7-cee8-428d-b45f-567fb1d03f01", // will be encoded to base64
|
||||
MatchType: MatchTypeFirstMatch,
|
||||
Rules: []Rule{
|
||||
{
|
||||
Status: AccessDenied,
|
||||
Actions: Actions{
|
||||
Names: []string{native.MethodDeleteObject, native.MethodGetContainer},
|
||||
},
|
||||
Resources: Resources{
|
||||
Names: []string{native.ResourceFormatAllObjects},
|
||||
},
|
||||
Condition: []Condition{
|
||||
{
|
||||
Op: CondStringEquals,
|
||||
Object: ObjectRequest,
|
||||
Key: native.PropertyKeyActorRole,
|
||||
Value: native.PropertyValueContainerRoleOthers,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Status: QuotaLimitReached,
|
||||
Actions: Actions{
|
||||
Inverted: true,
|
||||
Names: []string{native.MethodPutObject},
|
||||
},
|
||||
Resources: Resources{
|
||||
Names: []string{fmt.Sprintf(native.ResourceFormatRootContainerObjects, "9LPLUFZpEmfidG4n44vi2cjXKXSqWT492tCvLJiJ8W1J")},
|
||||
},
|
||||
Any: true,
|
||||
Condition: []Condition{
|
||||
{
|
||||
Op: CondStringNotLike,
|
||||
Object: ObjectResource,
|
||||
Key: native.PropertyKeyObjectType,
|
||||
Value: "regular",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Status: Status(100),
|
||||
Condition: []Condition{
|
||||
{
|
||||
Op: ConditionType(255),
|
||||
Object: ObjectType(128),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := chain.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
var parsed Chain
|
||||
require.NoError(t, parsed.UnmarshalJSON(data))
|
||||
require.Equal(t, chain, parsed)
|
||||
|
||||
expected, err := os.ReadFile("./testdata/test_status_json.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, parsed.UnmarshalJSON(expected))
|
||||
require.Equal(t, chain, parsed)
|
||||
}
|
75
pkg/chain/testdata/test_status_json.json
vendored
Normal file
75
pkg/chain/testdata/test_status_json.json
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"ID": "MmNjYTVhZTctY2VlOC00MjhkLWI0NWYtNTY3ZmIxZDAzZjAx",
|
||||
"Rules": [
|
||||
{
|
||||
"Status": "AccessDenied",
|
||||
"Actions": {
|
||||
"Inverted": false,
|
||||
"Names": [
|
||||
"DeleteObject",
|
||||
"GetContainer"
|
||||
]
|
||||
},
|
||||
"Resources": {
|
||||
"Inverted": false,
|
||||
"Names": [
|
||||
"native:object/*"
|
||||
]
|
||||
},
|
||||
"Any": false,
|
||||
"Condition": [
|
||||
{
|
||||
"Op": "StringEquals",
|
||||
"Object": "Request",
|
||||
"Key": "$Actor:role",
|
||||
"Value": "others"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Status": "QuotaLimitReached",
|
||||
"Actions": {
|
||||
"Inverted": true,
|
||||
"Names": [
|
||||
"PutObject"
|
||||
]
|
||||
},
|
||||
"Resources": {
|
||||
"Inverted": false,
|
||||
"Names": [
|
||||
"native:object//9LPLUFZpEmfidG4n44vi2cjXKXSqWT492tCvLJiJ8W1J/*"
|
||||
]
|
||||
},
|
||||
"Any": true,
|
||||
"Condition": [
|
||||
{
|
||||
"Op": "StringNotLike",
|
||||
"Object": "Resource",
|
||||
"Key": "$Object:objectType",
|
||||
"Value": "regular"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Status": "100",
|
||||
"Actions": {
|
||||
"Inverted": false,
|
||||
"Names": null
|
||||
},
|
||||
"Resources": {
|
||||
"Inverted": false,
|
||||
"Names": null
|
||||
},
|
||||
"Any": false,
|
||||
"Condition": [
|
||||
{
|
||||
"Op": "255",
|
||||
"Object": "128",
|
||||
"Key": "",
|
||||
"Value": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"MatchType": "FirstMatch"
|
||||
}
|
Loading…
Reference in a new issue