github.com/rajeev159/opa@v0.45.0/types/decode.go (about) 1 // Copyright 2020 The OPA Authors. All rights reserved. 2 // Use of this source code is governed by an Apache2 3 // license that can be found in the LICENSE file. 4 5 package types 6 7 import ( 8 "encoding/json" 9 "fmt" 10 11 "github.com/open-policy-agent/opa/util" 12 ) 13 14 const ( 15 typeNull = "null" 16 typeBoolean = "boolean" 17 typeNumber = "number" 18 typeString = "string" 19 typeArray = "array" 20 typeSet = "set" 21 typeObject = "object" 22 typeAny = "any" 23 typeFunction = "function" 24 ) 25 26 // Unmarshal deserializes bs and returns the resulting type. 27 func Unmarshal(bs []byte) (result Type, err error) { 28 29 var hint rawtype 30 31 if err = util.UnmarshalJSON(bs, &hint); err == nil { 32 switch hint.Type { 33 case typeNull: 34 result = NewNull() 35 case typeBoolean: 36 result = NewBoolean() 37 case typeNumber: 38 result = NewNumber() 39 case typeString: 40 result = NewString() 41 case typeArray: 42 var arr rawarray 43 if err = util.UnmarshalJSON(bs, &arr); err == nil { 44 var err error 45 var static []Type 46 var dynamic Type 47 if static, err = unmarshalSlice(arr.Static); err != nil { 48 return nil, err 49 } 50 if len(arr.Dynamic) != 0 { 51 if dynamic, err = Unmarshal(arr.Dynamic); err != nil { 52 return nil, err 53 } 54 } 55 result = NewArray(static, dynamic) 56 } 57 case typeObject: 58 var obj rawobject 59 if err = util.UnmarshalJSON(bs, &obj); err == nil { 60 var err error 61 var static []*StaticProperty 62 var dynamic *DynamicProperty 63 if static, err = unmarshalStaticPropertySlice(obj.Static); err != nil { 64 return nil, err 65 } 66 if dynamic, err = unmarshalDynamicProperty(obj.Dynamic); err != nil { 67 return nil, err 68 } 69 result = NewObject(static, dynamic) 70 } 71 case typeSet: 72 var set rawset 73 if err = util.UnmarshalJSON(bs, &set); err == nil { 74 var of Type 75 if of, err = Unmarshal(set.Of); err == nil { 76 result = NewSet(of) 77 } 78 } 79 case typeAny: 80 var any rawunion 81 if err = util.UnmarshalJSON(bs, &any); err == nil { 82 var of []Type 83 if of, err = unmarshalSlice(any.Of); err == nil { 84 result = NewAny(of...) 85 } 86 } 87 case typeFunction: 88 var decl rawdecl 89 if err = util.UnmarshalJSON(bs, &decl); err == nil { 90 args, err := unmarshalSlice(decl.Args) 91 if err != nil { 92 return nil, err 93 } 94 var ret Type 95 if len(decl.Result) > 0 { 96 ret, err = Unmarshal(decl.Result) 97 if err != nil { 98 return nil, err 99 } 100 } 101 if len(decl.Variadic) > 0 { 102 varargs, err := Unmarshal(decl.Variadic) 103 if err != nil { 104 return nil, err 105 } 106 result = NewVariadicFunction(args, varargs, ret) 107 } else { 108 result = NewFunction(args, ret) 109 } 110 } 111 default: 112 err = fmt.Errorf("unsupported type '%v'", hint.Type) 113 } 114 } 115 116 return result, err 117 } 118 119 type rawtype struct { 120 Type string `json:"type"` 121 } 122 123 type rawarray struct { 124 Static []json.RawMessage `json:"static"` 125 Dynamic json.RawMessage `json:"dynamic"` 126 } 127 128 type rawobject struct { 129 Static []rawstaticproperty `json:"static"` 130 Dynamic rawdynamicproperty `json:"dynamic"` 131 } 132 133 type rawstaticproperty struct { 134 Key interface{} `json:"key"` 135 Value json.RawMessage `json:"value"` 136 } 137 138 type rawdynamicproperty struct { 139 Key json.RawMessage `json:"key"` 140 Value json.RawMessage `json:"value"` 141 } 142 143 type rawset struct { 144 Of json.RawMessage `json:"of"` 145 } 146 147 type rawunion struct { 148 Of []json.RawMessage `json:"of"` 149 } 150 151 type rawdecl struct { 152 Args []json.RawMessage `json:"args"` 153 Result json.RawMessage `json:"result"` 154 Variadic json.RawMessage `json:"variadic"` 155 } 156 157 func unmarshalSlice(elems []json.RawMessage) (result []Type, err error) { 158 result = make([]Type, len(elems)) 159 for i := range elems { 160 if result[i], err = Unmarshal(elems[i]); err != nil { 161 return nil, err 162 } 163 } 164 return result, err 165 } 166 167 func unmarshalStaticPropertySlice(elems []rawstaticproperty) (result []*StaticProperty, err error) { 168 result = make([]*StaticProperty, len(elems)) 169 for i := range elems { 170 value, err := Unmarshal(elems[i].Value) 171 if err != nil { 172 return nil, err 173 } 174 result[i] = NewStaticProperty(elems[i].Key, value) 175 } 176 return result, err 177 } 178 179 func unmarshalDynamicProperty(x rawdynamicproperty) (result *DynamicProperty, err error) { 180 if len(x.Key) == 0 { 181 return nil, nil 182 } 183 var key Type 184 if key, err = Unmarshal(x.Key); err == nil { 185 var value Type 186 if value, err = Unmarshal(x.Value); err == nil { 187 return NewDynamicProperty(key, value), nil 188 } 189 } 190 return nil, err 191 }