mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
- Document Location, Expression, QueryResult (#109)
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
9e1e22432d
commit
d39200a52c
@@ -8,12 +8,14 @@ use crate::parser::*;
|
||||
use crate::scheduler::*;
|
||||
use crate::utils::gather_functions;
|
||||
use crate::value::*;
|
||||
use crate::QueryResults;
|
||||
|
||||
use std::convert::AsRef;
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
/// The Rego evaluation engine.
|
||||
#[derive(Clone)]
|
||||
pub struct Engine {
|
||||
modules: Vec<Ref<Module>>,
|
||||
@@ -21,6 +23,7 @@ pub struct Engine {
|
||||
prepared: bool,
|
||||
}
|
||||
|
||||
/// Create a default engine.
|
||||
impl Default for Engine {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
|
||||
+1
-37
@@ -9,10 +9,10 @@ use crate::parser::Parser;
|
||||
use crate::scheduler::*;
|
||||
use crate::utils::*;
|
||||
use crate::value::*;
|
||||
use crate::{Expression, Location, QueryResult, QueryResults};
|
||||
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use log::info;
|
||||
use serde::Serialize;
|
||||
use std::collections::btree_map::Entry as BTreeMapEntry;
|
||||
use std::collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap};
|
||||
use std::ops::Bound::*;
|
||||
@@ -73,42 +73,6 @@ impl Default for Interpreter {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct Location {
|
||||
pub row: u16,
|
||||
pub col: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct Expression {
|
||||
pub value: Value,
|
||||
pub text: Rc<str>,
|
||||
pub location: Location,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct QueryResult {
|
||||
// Expressions is shown first to match OPA.
|
||||
pub expressions: Vec<Expression>,
|
||||
#[serde(skip_serializing_if = "Value::is_empty_object")]
|
||||
pub bindings: Value,
|
||||
}
|
||||
|
||||
impl Default for QueryResult {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
bindings: Value::new_object(),
|
||||
expressions: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize)]
|
||||
pub struct QueryResults {
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub result: Vec<QueryResult>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Context {
|
||||
key_expr: Option<ExprRef>,
|
||||
|
||||
+160
-1
@@ -4,6 +4,8 @@
|
||||
// Use README.md as crate documentation.
|
||||
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
mod ast;
|
||||
mod builtins;
|
||||
mod engine;
|
||||
@@ -16,9 +18,166 @@ mod utils;
|
||||
mod value;
|
||||
|
||||
pub use engine::Engine;
|
||||
pub use interpreter::{QueryResult, QueryResults};
|
||||
pub use value::Value;
|
||||
|
||||
/// Location of an [`Expression`] in a Rego query.
|
||||
///
|
||||
/// ```
|
||||
/// # use regorus::Engine;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// // Create engine and evaluate " \n 1 + 2".
|
||||
/// let results = Engine::new().eval_query(" \n 1 + 2".to_string(), false)?;
|
||||
///
|
||||
/// // Fetch the location for the expression.
|
||||
/// let loc = &results.result[0].expressions[0].location;
|
||||
///
|
||||
/// assert_eq!(loc.row, 2);
|
||||
/// assert_eq!(loc.col, 3);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ````
|
||||
/// See also [`QueryResult`].
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct Location {
|
||||
/// Line number. Starts at 1.
|
||||
pub row: u16,
|
||||
/// Column number. Starts at 1.
|
||||
pub col: u16,
|
||||
}
|
||||
|
||||
/// An expression in a Rego query.
|
||||
///
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// // Create engine and evaluate "1 + 2".
|
||||
/// let results = Engine::new().eval_query("1 + 2".to_string(), false)?;
|
||||
///
|
||||
/// // Fetch the expression from results.
|
||||
/// let expr = &results.result[0].expressions[0];
|
||||
///
|
||||
/// assert_eq!(expr.value, Value::from(3u64));
|
||||
/// assert_eq!(expr.text.as_ref(), "1 + 2");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
/// See also [`QueryResult`].
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct Expression {
|
||||
/// Computed value of the expression.
|
||||
pub value: Value,
|
||||
|
||||
/// The Rego expression.
|
||||
pub text: std::rc::Rc<str>,
|
||||
|
||||
/// Location of the expression in the query string.
|
||||
pub location: Location,
|
||||
}
|
||||
|
||||
/// Result of evaluating a Rego query.
|
||||
///
|
||||
/// A query containing single expression.
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// // Create engine and evaluate "1 + 2".
|
||||
/// let results = Engine::new().eval_query("1 + 2".to_string(), false)?;
|
||||
///
|
||||
/// // Fetch the first (sole) result.
|
||||
/// let result = &results.result[0];
|
||||
///
|
||||
/// assert_eq!(result.expressions[0].value, Value::from(3u64));
|
||||
/// assert_eq!(result.expressions[0].text.as_ref(), "1 + 2");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// A query containing multiple expressions.
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// // Create engine and evaluate "1 + 2; 3.5 * 4".
|
||||
/// let results = Engine::new().eval_query("1 + 2; 3.55 * 4".to_string(), false)?;
|
||||
///
|
||||
/// // Fetch the first (sole) result.
|
||||
/// let result = &results.result[0];
|
||||
///
|
||||
/// // First expression.
|
||||
/// assert_eq!(result.expressions[0].value, Value::from(3u64));
|
||||
/// assert_eq!(result.expressions[0].text.as_ref(), "1 + 2");
|
||||
///
|
||||
/// // Second expression.
|
||||
/// assert_eq!(result.expressions[1].value, Value::from(14.2));
|
||||
/// assert_eq!(result.expressions[1].text.as_ref(), "3.55 * 4");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Expressions that create bindings (i.e. associate names to values) evaluate to
|
||||
/// either true or false. The value of bindings are available in the `bindings` field.
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// // Create engine and evaluate "x = 1; y = x > 0".
|
||||
/// let results = Engine::new().eval_query("x = 1; y = x > 0".to_string(), false)?;
|
||||
///
|
||||
/// // Fetch the first (sole) result.
|
||||
/// let result = &results.result[0];
|
||||
///
|
||||
/// // First expression is true.
|
||||
/// assert_eq!(result.expressions[0].value, Value::from(true));
|
||||
/// assert_eq!(result.expressions[0].text.as_ref(), "x = 1");
|
||||
///
|
||||
/// // Second expression is true.
|
||||
/// assert_eq!(result.expressions[1].value, Value::from(true));
|
||||
/// assert_eq!(result.expressions[1].text.as_ref(), "y = x > 0");
|
||||
///
|
||||
/// // bindings contains the value for each named expession.
|
||||
/// assert_eq!(result.bindings[&Value::from("x")], Value::from(1u64));
|
||||
/// assert_eq!(result.bindings[&Value::from("y")], Value::from(true));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// If any expression evaluates to false, then no results are produces.
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// // Create engine and evaluate "true; true; false".
|
||||
/// let results = Engine::new().eval_query("true; true; false".to_string(), false)?;
|
||||
///
|
||||
/// assert!(results.result.is_empty());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct QueryResult {
|
||||
/// Expressions in the query.
|
||||
///
|
||||
/// Each statement in the query is treated as a separte expression.
|
||||
///
|
||||
pub expressions: Vec<Expression>,
|
||||
|
||||
/// Bindings created in the query.
|
||||
#[serde(skip_serializing_if = "Value::is_empty_object")]
|
||||
pub bindings: Value,
|
||||
}
|
||||
|
||||
impl Default for QueryResult {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
bindings: Value::new_object(),
|
||||
expressions: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize)]
|
||||
pub struct QueryResults {
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub result: Vec<QueryResult>,
|
||||
}
|
||||
|
||||
/// Items in `unstable` are likely to change.
|
||||
pub mod unstable {
|
||||
pub use crate::ast::*;
|
||||
|
||||
@@ -238,6 +238,24 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Value {
|
||||
fn from(b: bool) -> Self {
|
||||
Value::Bool(b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Value {
|
||||
fn from(s: String) -> Self {
|
||||
Value::String(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Value {
|
||||
fn from(s: &str) -> Self {
|
||||
Value::String(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u128> for Value {
|
||||
fn from(n: u128) -> Self {
|
||||
Value::Number(Number::from(n))
|
||||
|
||||
Reference in New Issue
Block a user