6 个版本
0.4.0 | 2024年6月18日 |
---|---|
0.3.11 | 2024年1月22日 |
0.3.10 | 2023年9月23日 |
#816 在 数据库接口
每月305 次下载
59KB
856 行
regorust
Rego 是 Open Policy Agent 项目的本地查询语言。如果您想了解更多关于 Rego 语言的详细信息以及其各种用法,请参阅 OPA 提供的语言文档。
本 crate 是围绕 Microsoft 开发和维护的开源跨平台 C++ 实现 Rego 语言编译器和运行时的 rego-cpp
的包装器。您可以在 这里 了解更多关于该项目的信息。在这个包装器中,我们尽可能提供符合 Rust 语言的 Rego 查询引擎接口。我们希望这个项目对希望在 Rust 环境中利用 Rego 的力量的人有所帮助。
警告 虽然该项目已经发展到支持完整的 Rego 语言(见下文 语言支持),但我们不支持所有内置函数。尽管如此,我们已经验证了与 OPA Rego 测试套件的兼容性。即使如此,它仍应被视为实验性软件,并谨慎使用。
示例用法
use regorust::Interpreter;
fn main() {
// The Interpreter is the main interface into the library
let rego = Interpreter::new();
match rego.query("x=5;y=x + (2 - 4 * 0.25) * -3 + 7.4") {
Ok(result) => {
let x = result.binding("x").expect("cannot get x");
let y = result.binding("y").expect("cannot get y");
println!("x = {}", x.json().unwrap());
println!("y = {}", y.json().unwrap());
}
Err(e) => {
panic!("error: {}", e);
}
}
}
use regorust::Interpreter;
fn main() {
let input = r#"
{
"a": 10,
"b": "20",
"c": 30.0,
"d": true
}
"#;
let data0 = r#"
{
"one": {
"bar": "Foo",
"baz": 5,
"be": true,
"bop": 23.4
},
"two": {
"bar": "Bar",
"baz": 12.3,
"be": false,
"bop": 42
}
}
"#;
let data1 = r#"
{
"three": {
"bar": "Baz",
"baz": 15,
"be": true,
"bop": 4.23
}
}
"#;
let module = r#"
package objects
rect := {`width`: 2, "height": 4}
cube := {"width": 3, `height`: 4, "depth": 5}
a := 42
b := false
c := null
d := {"a": a, "x": [b, c]}
index := 1
shapes := [rect, cube]
names := ["prod", `smoke1`, "dev"]
sites := [{"name": "prod"}, {"name": names[index]}, {"name": "dev"}]
e := {
a: "foo",
"three": c,
names[2]: b,
"four": d,
}
f := e["dev"]
"#;
let rego = Interpreter::new();
rego.set_input_json(input);
rego.add_data_json(data0);
rego.add_data_json(data1);
rego.add_module("objects", module);
match rego.query("x=[data.one, input.b, data.objects.sites[1]]") {
Ok(result) => {
println!("{}", result.to_str().unwrap());
let x = result.binding("x").expect("cannot get x");
let data_one = x.index(0).unwrap();
if let NodeValue::String(bar) = data_one
.lookup("bar")
.unwrap()
.value()
.unwrap()
{
println!("data.one.bar = {}", bar);
}
}
Err(e) => {
panic!("error: {}", e);
}
}
}
语言支持
目前我们支持 OPA 定义的 Rego v0.65.0 版本,语法如下
module = package { import } policy
package = "package" ref
import = "import" ref [ "as" var ]
policy = { rule }
rule = [ "default" ] rule-head { rule-body }
rule-head = ( ref | var ) ( rule-head-set | rule-head-obj | rule-head-func | rule-head-comp )
rule-head-comp = [ assign-operator term ] [ "if" ]
rule-head-obj = "[" term "]" [ assign-operator term ] [ "if" ]
rule-head-func = "(" rule-args ")" [ assign-operator term ] [ "if" ]
rule-head-set = "contains" term [ "if" ] | "[" term "]"
rule-args = term { "," term }
rule-body = [ "else" [ assign-operator term ] [ "if" ] ] ( "{" query "}" ) | literal
query = literal { ( ";" | ( [CR] LF ) ) literal }
literal = ( some-decl | expr | "not" expr ) { with-modifier }
with-modifier = "with" term "as" term
some-decl = "some" term { "," term } { "in" expr }
expr = term | expr-call | expr-infix | expr-every | expr-parens | unary-expr
expr-call = var [ "." var ] "(" [ expr { "," expr } ] ")"
expr-infix = expr infix-operator expr
expr-every = "every" var { "," var } "in" ( term | expr-call | expr-infix ) "{" query "}"
expr-parens = "(" expr ")"
unary-expr = "-" expr
membership = term [ "," term ] "in" term
term = ref | var | scalar | array | object | set | membership | array-compr | object-compr | set-compr
array-compr = "[" term "|" query "]"
set-compr = "{" term "|" query "}"
object-compr = "{" object-item "|" query "}"
infix-operator = assign-operator | bool-operator | arith-operator | bin-operator
bool-operator = "==" | "!=" | "<" | ">" | ">=" | "<="
arith-operator = "+" | "-" | "*" | "/" | "%"
bin-operator = "&" | "|"
assign-operator = ":=" | "="
ref = ( var | array | object | set | array-compr | object-compr | set-compr | expr-call ) { ref-arg }
ref-arg = ref-arg-dot | ref-arg-brack
ref-arg-brack = "[" ( scalar | var | array | object | set | "_" ) "]"
ref-arg-dot = "." var
var = ( ALPHA | "_" ) { ALPHA | DIGIT | "_" }
scalar = string | NUMBER | TRUE | FALSE | NULL
string = STRING | raw-string
raw-string = "`" { CHAR-"`" } "`"
array = "[" term { "," term } "]"
object = "{" object-item { "," object-item } "}"
object-item = ( scalar | ref | var ) ":" term
set = empty-set | non-empty-set
non-empty-set = "{" term { "," term } "}"
empty-set = "set(" ")"
[!NOTE] 此语法对应于启用了
rego.v1
的 Rego(更多信息请参阅 OPA v1.0)。
定义
[] optional (zero or one instances)
{} repetition (zero or more instances)
| alternation (one of the instances)
() grouping (order of expansion)
STRING JSON string
NUMBER JSON number
TRUE JSON true
FALSE JSON false
NULL JSON null
CHAR Unicode character
ALPHA ASCII characters A-Z and a-z
DIGIT ASCII characters 0-9
CR Carriage Return
LF Line Feed
内置函数
目前仅支持少数内置函数,但我们正在积极添加所有标准内置函数。以下是目前支持的内置函数:
聚合
数组
位运算
类型转换
编码
图
数字
对象
正则表达式
语义版本
集合
字符串
类型
单位
- 杂项
opa.运行时
打印
时间.now_ns
与 OPA Rego Go 实现的兼容性
我们的目标是实现并与参考Go实现保持完全兼容。我们已经开发了一个测试驱动程序,它运行相同的测试并验证我们产生的输出是否相同。在这个阶段,我们通过了所有非内建特定的测试套件,这些测试套件是从OPA仓库克隆的。要使用可用的OPA测试进行构建,请使用以下预设之一
release-clang-opa
release-opa
目前,我们还没有完全通过以下测试套件
crypto*
glob*
graphql
invalidkeyerror
json*
(除了jsonbuiltins
)jwt*
net*
planner-ir
providers-aws
时间
walkbuiltin
无运行时依赖
~0–1.8MB
~36K SLoC