mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
Compare commits
10 Commits
regorus-v0
...
regorus-v0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c56da34843 | ||
|
|
61f82d1b34 | ||
|
|
00f45c70fe | ||
|
|
df73b20192 | ||
|
|
992b202f60 | ||
|
|
ce6ecd6fd6 | ||
|
|
37262ccf8f | ||
|
|
dcd040cf40 | ||
|
|
f0a3cf26a0 | ||
|
|
13d8289a58 |
20
CHANGELOG.md
20
CHANGELOG.md
@@ -6,6 +6,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.2.7](https://github.com/microsoft/regorus/compare/regorus-v0.2.6...regorus-v0.2.7) - 2024-10-22
|
||||
|
||||
### Fixed
|
||||
- docs failing to build ([#334](https://github.com/microsoft/regorus/pull/334))
|
||||
|
||||
### Other
|
||||
- *(deps)* update jsonschema requirement from 0.23.0 to 0.24.0 ([#332](https://github.com/microsoft/regorus/pull/332))
|
||||
- *(deps)* update jsonschema requirement from 0.22.3 to 0.23.0 ([#331](https://github.com/microsoft/regorus/pull/331))
|
||||
|
||||
## [0.2.6](https://github.com/microsoft/regorus/compare/regorus-v0.2.5...regorus-v0.2.6) - 2024-10-09
|
||||
|
||||
### Added
|
||||
- integer conversion functions for Value ([#328](https://github.com/microsoft/regorus/pull/328))
|
||||
|
||||
### Other
|
||||
- update to OPA v0.69.0 ([#327](https://github.com/microsoft/regorus/pull/327))
|
||||
- *(deps)* update jsonschema requirement from 0.21.0 to 0.22.3 ([#326](https://github.com/microsoft/regorus/pull/326))
|
||||
- *(deps)* update jsonschema requirement from 0.20.0 to 0.21.0 ([#325](https://github.com/microsoft/regorus/pull/325))
|
||||
- update to jsonschema 0.20.0 ([#323](https://github.com/microsoft/regorus/pull/323))
|
||||
|
||||
## [0.2.5](https://github.com/microsoft/regorus/compare/regorus-v0.2.4...regorus-v0.2.5) - 2024-09-18
|
||||
|
||||
### Added
|
||||
|
||||
@@ -12,7 +12,7 @@ members = [
|
||||
[package]
|
||||
name = "regorus"
|
||||
description = "A fast, lightweight Rego (OPA policy language) interpreter"
|
||||
version = "0.2.5"
|
||||
version = "0.2.7"
|
||||
edition = "2021"
|
||||
license-file = "LICENSE"
|
||||
repository = "https://github.com/microsoft/regorus"
|
||||
@@ -120,7 +120,7 @@ semver = {version = "1.0.20", optional = true, default-features = false }
|
||||
wax = { version = "0.6.0", features = [], default-features = false, optional = true }
|
||||
url = { version = "2.5.0", optional = true }
|
||||
uuid = { version = "1.6.1", default-features = false, features = ["v4", "fast-rng"], optional = true }
|
||||
jsonschema = { version = "0.19.1", default-features = false, optional = true }
|
||||
jsonschema = { version = "0.24.0", default-features = false, optional = true }
|
||||
chrono = { version = "0.4.31", optional = true }
|
||||
chrono-tz = { version = "0.10.0", optional = true }
|
||||
jsonwebtoken = { version = "9.2.0", optional = true }
|
||||
|
||||
@@ -10,7 +10,7 @@ Regorus is also
|
||||
- *cross-platform* - Written in platform-agnostic Rust.
|
||||
- *no_std compatible* - Regorus can be used in `no_std` environments too. Most of the builtins are supported.
|
||||
- *current* - We strive to keep Regorus up to date with latest OPA release. Regorus supports `import rego.v1`.
|
||||
- *compliant* - Regorus is mostly compliant with the latest [OPA release v0.68.0](https://github.com/open-policy-agent/opa/releases/tag/v0.68.0). See [OPA Conformance](#opa-conformance) for details. Note that while we behaviorally produce the same results, we don't yet support all the builtins.
|
||||
- *compliant* - Regorus is mostly compliant with the latest [OPA release v0.69.0](https://github.com/open-policy-agent/opa/releases/tag/v0.69.0). See [OPA Conformance](#opa-conformance) for details. Note that while we behaviorally produce the same results, we don't yet support all the builtins.
|
||||
- *extensible* - Extend the Rego language by implementing custom stateful builtins in Rust.
|
||||
See [add_extension](https://github.com/microsoft/regorus/blob/fc68bf9c8bea36427dae9401a7d1f6ada771f7ab/src/engine.rs#L352).
|
||||
Support for extensibility using other languages coming soon.
|
||||
@@ -99,7 +99,7 @@ $ cargo build -r --example regorus --no-default-features; strip target/release/e
|
||||
-rwxr-xr-x 1 anand staff 1.9M May 11 22:04 target/release/examples/regorus*
|
||||
```
|
||||
|
||||
Regorus passes the [OPA v0.68.0 test-suite](https://www.openpolicyagent.org/docs/latest/ir/#test-suite) barring a few
|
||||
Regorus passes the [OPA v0.69.0 test-suite](https://www.openpolicyagent.org/docs/latest/ir/#test-suite) barring a few
|
||||
builtins. See [OPA Conformance](#opa-conformance) below.
|
||||
|
||||
## Bindings
|
||||
@@ -276,7 +276,7 @@ Benchmark 1: opa eval -b tests/aci -d tests/aci/data.json -i tests/aci/input.jso
|
||||
```
|
||||
## OPA Conformance
|
||||
|
||||
Regorus has been verified to be compliant with [OPA v0.68.0](https://github.com/open-policy-agent/opa/releases/tag/v0.68.0)
|
||||
Regorus has been verified to be compliant with [OPA v0.69.0](https://github.com/open-policy-agent/opa/releases/tag/v0.69.0)
|
||||
using a [test driver](https://github.com/microsoft/regorus/blob/main/tests/opa.rs) that loads and runs the OPA testsuite using Regorus, and verifies that expected outputs are produced.
|
||||
|
||||
The test driver can be invoked by running:
|
||||
|
||||
@@ -191,6 +191,7 @@ mod tests {
|
||||
use wasm_bindgen_test::wasm_bindgen_test;
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
#[allow(dead_code)]
|
||||
pub fn basic() -> Result<(), JsValue> {
|
||||
let mut engine = crate::Engine::new();
|
||||
engine.setEnableCoverage(true);
|
||||
|
||||
@@ -391,14 +391,14 @@ fn object_union_n(
|
||||
}
|
||||
|
||||
#[cfg(feature = "jsonschema")]
|
||||
fn compile_json_schema(param: &Ref<Expr>, arg: &Value) -> Result<jsonschema::JSONSchema> {
|
||||
fn compile_json_schema(param: &Ref<Expr>, arg: &Value) -> Result<jsonschema::Validator> {
|
||||
let schema_str = match arg {
|
||||
Value::String(schema_str) => schema_str.as_ref().to_string(),
|
||||
_ => arg.to_json_str()?,
|
||||
};
|
||||
|
||||
if let Ok(schema) = serde_json::from_str(&schema_str) {
|
||||
match jsonschema::JSONSchema::compile(&schema) {
|
||||
match jsonschema::validator_for(&schema) {
|
||||
Ok(schema) => return Ok(schema),
|
||||
Err(e) => bail!(e.to_string()),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(clippy::doc_lazy_continuation)]
|
||||
// Use README.md as crate documentation.
|
||||
|
||||
180
src/value.rs
180
src/value.rs
@@ -322,7 +322,8 @@ impl Value {
|
||||
/// // Convert the value back to json.
|
||||
/// let json_str = value.to_json_str()?;
|
||||
///
|
||||
/// assert_eq!(json_str.trim(), std::fs::read_to_string("tests/aci/input.json")?.trim());
|
||||
/// assert_eq!(json_str.trim(),
|
||||
/// std::fs::read_to_string("tests/aci/input.json")?.trim().replace("\r\n", "\n"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
@@ -345,7 +346,8 @@ impl Value {
|
||||
/// // Convert the value back to json.
|
||||
/// let json_str = value.to_json_str()?;
|
||||
///
|
||||
/// assert_eq!(json_str.trim(), std::fs::read_to_string("tests/aci/input.json")?.trim());
|
||||
/// assert_eq!(json_str.trim(),
|
||||
/// std::fs::read_to_string("tests/aci/input.json")?.trim().replace("\r\n", "\n"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
@@ -902,6 +904,180 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast value to [`& u32`] if [`Value::Number`].
|
||||
///
|
||||
/// Error is raised if the value is not a number or if the numeric value
|
||||
/// does not fit in a u32.
|
||||
///
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// let v = Value::from(10);
|
||||
/// assert_eq!(v.as_u32()?, 10u32);
|
||||
///
|
||||
/// let v = Value::from(-10);
|
||||
/// assert!(v.as_u32().is_err());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
pub fn as_u32(&self) -> Result<u32> {
|
||||
match self {
|
||||
Value::Number(b) => {
|
||||
if let Some(n) = b.as_u64() {
|
||||
if let Ok(v) = u32::try_from(n) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
bail!("not a u32");
|
||||
}
|
||||
_ => Err(anyhow!("not a u32")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast value to [`& i32`] if [`Value::Number`].
|
||||
///
|
||||
/// Error is raised if the value is not a number or if the numeric value
|
||||
/// does not fit in a i32.
|
||||
///
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// let v = Value::from(-10);
|
||||
/// assert_eq!(v.as_i32()?, -10i32);
|
||||
///
|
||||
/// let v = Value::from(2_147_483_648i64);
|
||||
/// assert!(v.as_i32().is_err());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
pub fn as_i32(&self) -> Result<i32> {
|
||||
match self {
|
||||
Value::Number(b) => {
|
||||
if let Some(n) = b.as_i64() {
|
||||
if let Ok(v) = i32::try_from(n) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
bail!("not an i32");
|
||||
}
|
||||
_ => Err(anyhow!("not an i32")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast value to [`& u16`] if [`Value::Number`].
|
||||
///
|
||||
/// Error is raised if the value is not a number or if the numeric value
|
||||
/// does not fit in a u16.
|
||||
///
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// let v = Value::from(10);
|
||||
/// assert_eq!(v.as_u16()?, 10u16);
|
||||
///
|
||||
/// let v = Value::from(-10);
|
||||
/// assert!(v.as_u16().is_err());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
pub fn as_u16(&self) -> Result<u16> {
|
||||
match self {
|
||||
Value::Number(b) => {
|
||||
if let Some(n) = b.as_u64() {
|
||||
if let Ok(v) = u16::try_from(n) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
bail!("not a u16");
|
||||
}
|
||||
_ => Err(anyhow!("not a u16")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast value to [`& i16`] if [`Value::Number`].
|
||||
///
|
||||
/// Error is raised if the value is not a number or if the numeric value
|
||||
/// does not fit in a i16.
|
||||
///
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// let v = Value::from(-10);
|
||||
/// assert_eq!(v.as_i16()?, -10i16);
|
||||
///
|
||||
/// let v = Value::from(32768i64);
|
||||
/// assert!(v.as_i16().is_err());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
pub fn as_i16(&self) -> Result<i16> {
|
||||
match self {
|
||||
Value::Number(b) => {
|
||||
if let Some(n) = b.as_i64() {
|
||||
if let Ok(v) = i16::try_from(n) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
bail!("not an i16");
|
||||
}
|
||||
_ => Err(anyhow!("not an i16")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast value to [`& u8`] if [`Value::Number`].
|
||||
///
|
||||
/// Error is raised if the value is not a number or if the numeric value
|
||||
/// does not fit in a u8.
|
||||
///
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// let v = Value::from(10);
|
||||
/// assert_eq!(v.as_u8()?, 10u8);
|
||||
///
|
||||
/// let v = Value::from(-10);
|
||||
/// assert!(v.as_u8().is_err());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
pub fn as_u8(&self) -> Result<u8> {
|
||||
match self {
|
||||
Value::Number(b) => {
|
||||
if let Some(n) = b.as_u64() {
|
||||
if let Ok(v) = u8::try_from(n) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
bail!("not a u8");
|
||||
}
|
||||
_ => Err(anyhow!("not a u8")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast value to [`& i8`] if [`Value::Number`].
|
||||
///
|
||||
/// Error is raised if the value is not a number or if the numeric value
|
||||
/// does not fit in a i8.
|
||||
///
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// let v = Value::from(-10);
|
||||
/// assert_eq!(v.as_i8()?, -10i8);
|
||||
///
|
||||
/// let v = Value::from(128);
|
||||
/// assert!(v.as_i8().is_err());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
pub fn as_i8(&self) -> Result<i8> {
|
||||
match self {
|
||||
Value::Number(b) => {
|
||||
if let Some(n) = b.as_i64() {
|
||||
if let Ok(v) = i8::try_from(n) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
bail!("not an i8");
|
||||
}
|
||||
_ => Err(anyhow!("not an i8")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast value to [`& f64`] if [`Value::Number`].
|
||||
/// Error is raised if the value is not a number or if the numeric value
|
||||
/// does not fit in a i64.
|
||||
|
||||
@@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
const OPA_REPO: &str = "https://github.com/open-policy-agent/opa";
|
||||
const OPA_BRANCH: &str = "v0.68.0";
|
||||
const OPA_BRANCH: &str = "v0.69.0";
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
@@ -174,7 +174,7 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let is_rego_v1_test = path_dir_str.starts_with("v1/");
|
||||
let is_rego_v1_test = path_dir_str.starts_with("v1/") || path_dir.starts_with("v1\\");
|
||||
let entry = status.entry(path_dir_str).or_insert((0, 0, 0));
|
||||
|
||||
let yaml_str = std::fs::read_to_string(&path_str)?;
|
||||
|
||||
Reference in New Issue
Block a user