mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
add std feature (#231)
- `std` feature is enabled by default - By default enable #![no_std] compilation - Import std create if `std` feature is enabled or if testing - Use core, alloc types - Make it clear where std types are being used - In no std, use BTreeMap in place of HashMap. HashMap is not available in no std due to lack of a secure random number generator Note: The project does not yet compile without std feature being specified. But it's really close to being able to do so. Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
e9cd6d6afc
commit
01fc234a33
2
.github/workflows/pr.yml
vendored
2
.github/workflows/pr.yml
vendored
@@ -22,6 +22,8 @@ jobs:
|
||||
run: sudo apt update && sudo apt install -y musl-tools
|
||||
- name: Format Check
|
||||
run: cargo fmt --check
|
||||
- name: Build (all features)
|
||||
run: cargo build -r --all-features --verbose
|
||||
- name: Build
|
||||
run: cargo build -r --verbose
|
||||
- name: Doc Tests
|
||||
|
||||
@@ -40,9 +40,10 @@ jsonschema = ["dep:jsonschema"]
|
||||
opa-runtime = []
|
||||
regex = ["dep:regex"]
|
||||
semver = ["dep:semver"]
|
||||
std = ["serde_json/std"]
|
||||
time = ["dep:chrono", "dep:chrono-tz"]
|
||||
uuid = ["dep:uuid"]
|
||||
urlquery = ["dep:url"]
|
||||
time = ["dep:chrono", "dep:chrono-tz"]
|
||||
yaml = ["serde_yaml"]
|
||||
full-opa = [
|
||||
"base64",
|
||||
@@ -59,6 +60,7 @@ full-opa = [
|
||||
"opa-runtime",
|
||||
"regex",
|
||||
"semver",
|
||||
"std",
|
||||
"time",
|
||||
"uuid",
|
||||
"urlquery",
|
||||
@@ -70,8 +72,8 @@ opa-testutil = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.45", default-features=false }
|
||||
serde = {version = "1.0.150", features = ["derive", "rc"] }
|
||||
serde_json = "1.0.89"
|
||||
serde = {version = "1.0.150", default-features = false, features = ["derive", "rc"] }
|
||||
serde_json = { version = "1.0.89", default-features=false, features = ["alloc"] }
|
||||
serde_yaml = {version = "0.9.16", optional = true }
|
||||
lazy_static = "1.4.0"
|
||||
rand = "0.8.5"
|
||||
|
||||
@@ -11,6 +11,9 @@ if [ -f Cargo.toml ]; then
|
||||
|
||||
# Ensure that the public API works
|
||||
cargo test -r --doc
|
||||
|
||||
# Ensure that we can build with all features
|
||||
cargo build -r --all-features
|
||||
|
||||
# Ensure that all tests pass
|
||||
cargo test -r
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::lexer::*;
|
||||
use crate::value::Value;
|
||||
use crate::Rc;
|
||||
use crate::*;
|
||||
|
||||
use core::{cmp, fmt, ops::Deref};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::builtins::utils::{ensure_args_count, ensure_numeric};
|
||||
use crate::lexer::Span;
|
||||
use crate::number::Number;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::builtins;
|
||||
use crate::builtins::utils::ensure_args_count;
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::ast::{Expr, Ref};
|
||||
use crate::builtins;
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
@@ -43,8 +44,10 @@ pub fn print_to_string(
|
||||
fn print(span: &Span, params: &[Ref<Expr>], args: &[Value], strict: bool) -> Result<Value> {
|
||||
let msg = print_to_string(span, params, args, strict)?;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
if !msg.is_empty() {
|
||||
eprintln!("{}", &msg[1..]);
|
||||
std::eprintln!("{}", &msg[1..]);
|
||||
}
|
||||
|
||||
Ok(Value::Bool(true))
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::builtins::utils::{ensure_args_count, ensure_set};
|
||||
use crate::builtins::BuiltinFcn;
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::builtins::utils::{
|
||||
};
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
#[allow(unused)]
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::builtins;
|
||||
use crate::builtins::utils::{ensure_args_count, ensure_string, ensure_string_collection};
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
//use glob::{Pattern, MatchOptions};
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::builtins;
|
||||
use crate::builtins::utils::{ensure_args_count, ensure_object};
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use alloc::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use crate::ast::{Expr, Ref};
|
||||
use crate::builtins;
|
||||
use crate::builtins::utils::{ensure_args_count, ensure_string};
|
||||
use crate::*;
|
||||
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
|
||||
@@ -47,7 +47,7 @@ use crate::ast::{Expr, Ref};
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
|
||||
use std::collections::HashMap as BuiltinsMap;
|
||||
use crate::Map as BuiltinsMap;
|
||||
|
||||
use anyhow::Result;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::builtins::utils::{ensure_args_count, ensure_numeric, ensure_string};
|
||||
use crate::lexer::Span;
|
||||
use crate::number::Number;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::builtins::utils::{ensure_args_count, ensure_array, ensure_object};
|
||||
use crate::lexer::Span;
|
||||
use crate::Rc;
|
||||
use crate::Value;
|
||||
use crate::*;
|
||||
|
||||
use alloc::collections::{BTreeMap, BTreeSet};
|
||||
use core::iter::Iterator;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use crate::ast::{Expr, Ref};
|
||||
use crate::builtins;
|
||||
use crate::builtins::utils::ensure_args_count;
|
||||
use crate::*;
|
||||
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::builtins;
|
||||
use crate::builtins::utils::{ensure_args_count, ensure_numeric, ensure_string};
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use regex::Regex;
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::builtins;
|
||||
use crate::builtins::utils::{ensure_args_count, ensure_set};
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use alloc::collections::BTreeSet;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ use crate::builtins::utils::{
|
||||
use crate::lexer::Span;
|
||||
use crate::number::Number;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::builtins;
|
||||
use crate::builtins::utils::{ensure_args_count, ensure_numeric, ensure_string};
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use crate::*;
|
||||
use core::fmt;
|
||||
use core::iter;
|
||||
use std::error::Error;
|
||||
@@ -1242,7 +1243,7 @@ mod tests {
|
||||
];
|
||||
|
||||
for tc in test_cases {
|
||||
println!("Test case {}", tc.name);
|
||||
std::println!("Test case {}", tc.name);
|
||||
let time = parse(&tc.format, &tc.value).unwrap();
|
||||
check_time(time, &tc);
|
||||
}
|
||||
@@ -1313,7 +1314,7 @@ mod tests {
|
||||
let time = PST8PDT.timestamp_nanos(1233810057012345600);
|
||||
|
||||
for tc in test_cases {
|
||||
println!("Test case {}", tc.name);
|
||||
std::println!("Test case {}", tc.name);
|
||||
let result = format(time, &tc.format);
|
||||
assert_eq!(result, tc.result);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,9 @@ use crate::builtins::utils::{ensure_args_count, ensure_string};
|
||||
use crate::lexer::Span;
|
||||
use crate::number::Number;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
pub fn register(m: &mut builtins::BuiltinsMap<&'static str, builtins::BuiltinFcn>) {
|
||||
m.insert("units.parse", (parse, 1));
|
||||
@@ -87,12 +88,13 @@ fn parse(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Re
|
||||
_ => (string, ""),
|
||||
};
|
||||
|
||||
// Propagating the underlying error is not useful here.
|
||||
let v: Value = if number_part.starts_with('.') {
|
||||
serde_json::from_str(format!("0{number_part}").as_str())
|
||||
} else {
|
||||
serde_json::from_str(number_part)
|
||||
}
|
||||
.with_context(|| span.error("could not parse number"))?;
|
||||
.map_err(|_| params[0].span().error("could not parse number"))?;
|
||||
|
||||
let mut n = match v {
|
||||
Value::Number(n) => n.clone(),
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::lexer::Span;
|
||||
use crate::number::Number;
|
||||
use crate::Rc;
|
||||
use crate::Value;
|
||||
use crate::*;
|
||||
|
||||
use alloc::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::builtins;
|
||||
use crate::builtins::utils::{ensure_args_count, ensure_string};
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use alloc::collections::BTreeMap;
|
||||
|
||||
|
||||
@@ -8,11 +8,9 @@ use crate::parser::*;
|
||||
use crate::scheduler::*;
|
||||
use crate::utils::gather_functions;
|
||||
use crate::value::*;
|
||||
use crate::*;
|
||||
use crate::{Extension, QueryResults};
|
||||
|
||||
use core::convert::AsRef;
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
/// The Rego evaluation engine.
|
||||
@@ -89,7 +87,8 @@ impl Engine {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn add_policy_from_file<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
|
||||
#[cfg(feature = "std")]
|
||||
pub fn add_policy_from_file<P: AsRef<std::path::Path>>(&mut self, path: P) -> Result<()> {
|
||||
let source = Source::from_file(path)?;
|
||||
let mut parser = Parser::new(&source)?;
|
||||
self.modules.push(Ref::new(parser.parse()?));
|
||||
|
||||
@@ -8,14 +8,13 @@ use crate::parser::Parser;
|
||||
use crate::scheduler::*;
|
||||
use crate::utils::*;
|
||||
use crate::value::*;
|
||||
use crate::Rc;
|
||||
use crate::*;
|
||||
use crate::{Expression, Extension, Location, QueryResult, QueryResults};
|
||||
|
||||
use alloc::collections::btree_map::Entry as BTreeMapEntry;
|
||||
use alloc::collections::{BTreeMap, BTreeSet};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use core::ops::Bound::*;
|
||||
use std::collections::{hash_map::Entry, HashMap, HashSet};
|
||||
|
||||
type Scope = BTreeMap<SourceStr, Value>;
|
||||
|
||||
@@ -53,8 +52,8 @@ pub struct Interpreter {
|
||||
loop_var_values: BTreeMap<ExprRef, Value>,
|
||||
contexts: Vec<Context>,
|
||||
functions: FunctionTable,
|
||||
rules: HashMap<String, Vec<Ref<Rule>>>,
|
||||
default_rules: HashMap<String, Vec<DefaultRuleInfo>>,
|
||||
rules: Map<String, Vec<Ref<Rule>>>,
|
||||
default_rules: Map<String, Vec<DefaultRuleInfo>>,
|
||||
processed: BTreeSet<Ref<Rule>>,
|
||||
processed_paths: Value,
|
||||
rule_values: BTreeMap<Vec<Value>, (Value, Ref<Expr>)>,
|
||||
@@ -65,16 +64,16 @@ pub struct Interpreter {
|
||||
allow_deprecated: bool,
|
||||
strict_builtin_errors: bool,
|
||||
imports: BTreeMap<String, Ref<Expr>>,
|
||||
extensions: HashMap<String, (u8, Rc<Box<dyn Extension>>)>,
|
||||
extensions: Map<String, (u8, Rc<Box<dyn Extension>>)>,
|
||||
|
||||
#[cfg(feature = "coverage")]
|
||||
coverage: HashMap<Source, Vec<bool>>,
|
||||
coverage: Map<Source, Vec<bool>>,
|
||||
#[cfg(feature = "coverage")]
|
||||
enable_coverage: bool,
|
||||
|
||||
gather_prints: bool,
|
||||
prints: Vec<String>,
|
||||
rule_paths: HashSet<String>,
|
||||
rule_paths: Set<String>,
|
||||
}
|
||||
|
||||
impl Default for Interpreter {
|
||||
@@ -178,8 +177,8 @@ impl Interpreter {
|
||||
contexts: vec![],
|
||||
loop_var_values: BTreeMap::new(),
|
||||
functions: FunctionTable::new(),
|
||||
rules: HashMap::new(),
|
||||
default_rules: HashMap::new(),
|
||||
rules: Map::new(),
|
||||
default_rules: Map::new(),
|
||||
processed: BTreeSet::new(),
|
||||
processed_paths: Value::new_object(),
|
||||
rule_values: BTreeMap::new(),
|
||||
@@ -190,16 +189,16 @@ impl Interpreter {
|
||||
allow_deprecated: true,
|
||||
strict_builtin_errors: true,
|
||||
imports: BTreeMap::default(),
|
||||
extensions: HashMap::new(),
|
||||
extensions: Map::new(),
|
||||
|
||||
#[cfg(feature = "coverage")]
|
||||
coverage: HashMap::new(),
|
||||
coverage: Map::new(),
|
||||
#[cfg(feature = "coverage")]
|
||||
enable_coverage: false,
|
||||
|
||||
gather_prints: false,
|
||||
prints: Vec::default(),
|
||||
rule_paths: HashSet::new(),
|
||||
rule_paths: Set::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3496,10 +3495,10 @@ impl Interpreter {
|
||||
}
|
||||
|
||||
match self.rules.entry(path) {
|
||||
Entry::Occupied(o) => {
|
||||
MapEntry::Occupied(o) => {
|
||||
o.into_mut().push(rule.clone());
|
||||
}
|
||||
Entry::Vacant(v) => {
|
||||
MapEntry::Vacant(v) => {
|
||||
v.insert(vec![rule.clone()]);
|
||||
}
|
||||
}
|
||||
@@ -3523,7 +3522,7 @@ impl Interpreter {
|
||||
}
|
||||
|
||||
match self.default_rules.entry(path) {
|
||||
Entry::Occupied(o) => {
|
||||
MapEntry::Occupied(o) => {
|
||||
if idx + 1 == comps.len() {
|
||||
for (_, i) in o.get() {
|
||||
if index.is_some() && i.is_some() {
|
||||
@@ -3539,7 +3538,7 @@ impl Interpreter {
|
||||
}
|
||||
o.into_mut().push((rule.clone(), index.clone()));
|
||||
}
|
||||
Entry::Vacant(v) => {
|
||||
MapEntry::Vacant(v) => {
|
||||
v.insert(vec![(rule.clone(), index.clone())]);
|
||||
}
|
||||
}
|
||||
@@ -3562,7 +3561,8 @@ impl Interpreter {
|
||||
},
|
||||
Expr::Var(v) if v.0.text() == "input" => {
|
||||
// Warn redundant import of input. Ignore it.
|
||||
eprintln!(
|
||||
#[cfg(feature = "std")]
|
||||
std::eprintln!(
|
||||
"{}",
|
||||
import
|
||||
.refr
|
||||
@@ -3639,7 +3639,7 @@ impl Interpreter {
|
||||
nargs: u8,
|
||||
extension: Box<dyn Extension>,
|
||||
) -> Result<()> {
|
||||
if let std::collections::hash_map::Entry::Vacant(v) = self.extensions.entry(path) {
|
||||
if let MapEntry::Vacant(v) = self.extensions.entry(path) {
|
||||
v.insert((nargs, Rc::new(extension)));
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -3765,7 +3765,7 @@ impl Interpreter {
|
||||
|
||||
#[cfg(feature = "coverage")]
|
||||
pub fn clear_coverage_data(&mut self) {
|
||||
self.coverage = HashMap::new();
|
||||
self.coverage = Map::new();
|
||||
}
|
||||
|
||||
pub fn set_gather_prints(&mut self, b: bool) {
|
||||
|
||||
14
src/lexer.rs
14
src/lexer.rs
@@ -1,16 +1,12 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use crate::*;
|
||||
use core::cmp;
|
||||
use core::convert::AsRef;
|
||||
use core::fmt::{self, Debug, Formatter};
|
||||
use core::iter::Peekable;
|
||||
use core::str::CharIndices;
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::path::Path;
|
||||
|
||||
use crate::Rc;
|
||||
use crate::Value;
|
||||
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
@@ -47,8 +43,9 @@ impl cmp::PartialEq for Source {
|
||||
|
||||
impl cmp::Eq for Source {}
|
||||
|
||||
impl Hash for Source {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
#[cfg(feature = "std")]
|
||||
impl std::hash::Hash for Source {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
Rc::as_ptr(&self.src).hash(state)
|
||||
}
|
||||
}
|
||||
@@ -156,7 +153,8 @@ impl Source {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Source> {
|
||||
#[cfg(feature = "std")]
|
||||
pub fn from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Source> {
|
||||
let contents = match std::fs::read_to_string(&path) {
|
||||
Ok(c) => c,
|
||||
Err(e) => bail!("Failed to read {}. {e}", path.as_ref().display()),
|
||||
|
||||
26
src/lib.rs
26
src/lib.rs
@@ -4,10 +4,19 @@
|
||||
// Use README.md as crate documentation.
|
||||
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
// We'll default to building for no_std - use core, alloc instead of std.
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
use serde::Serialize;
|
||||
|
||||
// Import std crate if building with std support.
|
||||
// We don't import types or macros from std.
|
||||
// As a result, types and macros from std must be qualified via `std::`
|
||||
// making dependencies on std easier to spot.
|
||||
#[cfg(any(feature = "std", test))]
|
||||
extern crate std;
|
||||
|
||||
mod ast;
|
||||
mod builtins;
|
||||
mod engine;
|
||||
@@ -28,6 +37,21 @@ use alloc::sync::Arc as Rc;
|
||||
#[cfg(not(feature = "arc"))]
|
||||
use alloc::rc::Rc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::collections::{hash_map::Entry as MapEntry, HashMap as Map, HashSet as Set};
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::collections::{btree_map::Entry as MapEntry, BTreeMap as Map, BTreeSet as Set};
|
||||
|
||||
use alloc::{
|
||||
borrow::ToOwned,
|
||||
boxed::Box,
|
||||
format,
|
||||
string::{String, ToString},
|
||||
vec,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use core::fmt;
|
||||
|
||||
/// Location of an [`Expression`] in a Rego query.
|
||||
@@ -346,6 +370,8 @@ impl fmt::Debug for dyn Extension {
|
||||
#[cfg(feature = "coverage")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "coverage")))]
|
||||
pub mod coverage {
|
||||
use crate::*;
|
||||
|
||||
#[derive(Default, serde::Serialize, serde::Deserialize)]
|
||||
/// Coverage information about a rego policy file.
|
||||
pub struct File {
|
||||
|
||||
@@ -10,7 +10,7 @@ use anyhow::{anyhow, bail, Result};
|
||||
use serde::ser::Serializer;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::Rc;
|
||||
use crate::*;
|
||||
|
||||
pub type BigInt = i128;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::ast::*;
|
||||
use crate::lexer::*;
|
||||
use crate::number::*;
|
||||
use crate::value::*;
|
||||
use crate::*;
|
||||
|
||||
use alloc::collections::BTreeMap;
|
||||
use core::str::FromStr;
|
||||
@@ -73,7 +74,8 @@ impl<'source> Parser<'source> {
|
||||
let msg = format!(
|
||||
"`{kw}` will be treated as identifier due to missing `import future.keywords.{kw}`"
|
||||
);
|
||||
println!(
|
||||
#[cfg(feature = "std")]
|
||||
std::println!(
|
||||
"{}",
|
||||
self.source
|
||||
.message(self.tok.1.line, self.tok.1.col, "warning", &msg)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use crate::ast::Expr::*;
|
||||
use crate::ast::Expr::{Set, *};
|
||||
use crate::ast::*;
|
||||
use crate::lexer::*;
|
||||
use crate::utils::*;
|
||||
use crate::*;
|
||||
|
||||
use alloc::collections::{BTreeMap, BTreeSet, VecDeque};
|
||||
use alloc::string::String;
|
||||
@@ -196,7 +197,8 @@ pub fn schedule<Str: Clone + cmp::Ord + fmt::Debug>(
|
||||
}
|
||||
|
||||
if order.len() != num_statements {
|
||||
eprintln!("could not schedule all statements {order:?} {orig_infos:?}");
|
||||
#[cfg(feature = "std")]
|
||||
std::eprintln!("could not schedule all statements {order:?} {orig_infos:?}");
|
||||
return Ok(SortResult::Order(
|
||||
(0..num_statements).map(|i| i as u16).collect(),
|
||||
));
|
||||
|
||||
@@ -176,7 +176,7 @@ pub fn eval_file(
|
||||
let r = engine.eval_query(query.to_string(), enable_tracing)?;
|
||||
let r_full = engine_full.eval_query_and_all_rules(query.to_string(), enable_tracing)?;
|
||||
if r != r_full {
|
||||
println!(
|
||||
std::println!(
|
||||
"{}\n{}",
|
||||
serde_json::to_string_pretty(&r_full)?,
|
||||
serde_json::to_string_pretty(&r)?
|
||||
@@ -194,7 +194,7 @@ pub fn eval_file(
|
||||
let r = engine.eval_query(query.to_string(), enable_tracing)?;
|
||||
let r_full = engine_full.eval_query_and_all_rules(query.to_string(), enable_tracing)?;
|
||||
if r != r_full {
|
||||
println!(
|
||||
std::println!(
|
||||
"{}\n{}",
|
||||
serde_json::to_string_pretty(&r_full)?,
|
||||
serde_json::to_string_pretty(&r)?
|
||||
@@ -277,12 +277,12 @@ fn yaml_test_impl(file: &str) -> Result<()> {
|
||||
let yaml_str = std::fs::read_to_string(file)?;
|
||||
let test: YamlTest = serde_yaml::from_str(&yaml_str)?;
|
||||
|
||||
println!("running {file}");
|
||||
std::println!("running {file}");
|
||||
|
||||
for case in test.cases {
|
||||
print!("case {} ", case.note);
|
||||
std::print!("case {} ", case.note);
|
||||
if case.skip == Some(true) {
|
||||
println!("skipped");
|
||||
std::println!("skipped");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -329,13 +329,13 @@ fn yaml_test_impl(file: &str) -> Result<()> {
|
||||
expected
|
||||
);
|
||||
}
|
||||
println!("{actual}");
|
||||
std::println!("{actual}");
|
||||
}
|
||||
_ => return Err(actual),
|
||||
},
|
||||
}
|
||||
|
||||
println!("passed");
|
||||
std::println!("passed");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use crate::*;
|
||||
use crate::{ast::*, lexer::*, parser::*, scheduler::*};
|
||||
use anyhow::{bail, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -73,25 +74,25 @@ fn analyze_file(regos: &[String], expected_scopes: &[Scope]) -> Result<()> {
|
||||
to_string_set(scope.inputs.iter()),
|
||||
expected_scopes[idx].inputs
|
||||
);
|
||||
println!("scope {idx} matched.")
|
||||
std::println!("scope {idx} matched.")
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn yaml_test_impl(file: &str) -> Result<()> {
|
||||
println!("\nrunning {file}");
|
||||
std::println!("\nrunning {file}");
|
||||
|
||||
let yaml_str = std::fs::read_to_string(file)?;
|
||||
let test: YamlTest = serde_yaml::from_str(&yaml_str)?;
|
||||
|
||||
for case in &test.cases {
|
||||
print!("\ncase {} ", case.note);
|
||||
std::print!("\ncase {} ", case.note);
|
||||
analyze_file(&case.modules, &case.scopes)?;
|
||||
println!("passed");
|
||||
std::println!("passed");
|
||||
}
|
||||
|
||||
println!("{} cases passed.", test.cases.len());
|
||||
std::println!("{} cases passed.", test.cases.len());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use crate::scheduler::*;
|
||||
use crate::*;
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
mod analyzer;
|
||||
@@ -20,7 +21,7 @@ fn make_info(definitions: &[(&'static str, &[&'static str])]) -> StmtInfo<&'stat
|
||||
|
||||
fn print_stmts(stmts: &[&str], order: &[u16]) {
|
||||
for idx in order.iter().cloned() {
|
||||
println!("{}", stmts[idx as usize]);
|
||||
std::println!("{}", stmts[idx as usize]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +30,7 @@ fn check_result(stmts: &[&str], expected: &[&str], r: SortResult) -> Result<()>
|
||||
SortResult::Order(order) => {
|
||||
print_stmts(stmts, &order);
|
||||
for (i, o) in order.iter().cloned().enumerate() {
|
||||
println!("{:30}{}", stmts[o as usize], expected[i]);
|
||||
std::println!("{:30}{}", stmts[o as usize], expected[i]);
|
||||
}
|
||||
for (i, o) in order.iter().cloned().enumerate() {
|
||||
assert_eq!(stmts[o as usize], expected[i]);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use crate::ast::*;
|
||||
use crate::builtins::*;
|
||||
use crate::lexer::*;
|
||||
use crate::*;
|
||||
|
||||
use alloc::collections::BTreeMap;
|
||||
|
||||
|
||||
20
src/value.rs
20
src/value.rs
@@ -7,16 +7,15 @@ use alloc::collections::{BTreeMap, BTreeSet};
|
||||
use core::fmt;
|
||||
use core::ops;
|
||||
|
||||
use std::convert::AsRef;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use core::convert::AsRef;
|
||||
use core::str::FromStr;
|
||||
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use serde::de::{self, Deserializer, MapAccess, SeqAccess, Visitor};
|
||||
use serde::ser::{SerializeMap, Serializer};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Rc;
|
||||
use crate::*;
|
||||
|
||||
/// A value in a Rego document.
|
||||
///
|
||||
@@ -310,7 +309,7 @@ impl Value {
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn from_json_str(json: &str) -> Result<Value> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
serde_json::from_str(json).map_err(anyhow::Error::msg)
|
||||
}
|
||||
|
||||
/// Deserialize a [`Value`] from a file containing JSON.
|
||||
@@ -327,7 +326,8 @@ impl Value {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn from_json_file<P: AsRef<Path>>(path: P) -> Result<Value> {
|
||||
#[cfg(feature = "std")]
|
||||
pub fn from_json_file<P: AsRef<std::path::Path>>(path: P) -> Result<Value> {
|
||||
match std::fs::read_to_string(&path) {
|
||||
Ok(c) => Self::from_json_str(c.as_str()),
|
||||
Err(e) => bail!("Failed to read {}. {e}", path.as_ref().display()),
|
||||
@@ -394,7 +394,7 @@ impl Value {
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn to_json_str(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string_pretty(self)?)
|
||||
serde_json::to_string_pretty(self).map_err(anyhow::Error::msg)
|
||||
}
|
||||
|
||||
/// Deserialize a value from YAML.
|
||||
@@ -1132,9 +1132,9 @@ impl Value {
|
||||
Some(pv) if *pv != *v => {
|
||||
bail!(
|
||||
"value for key `{}` generated multiple times: `{}` and `{}`",
|
||||
serde_json::to_string_pretty(&k)?,
|
||||
serde_json::to_string_pretty(&pv)?,
|
||||
serde_json::to_string_pretty(&v)?,
|
||||
serde_json::to_string_pretty(&k).map_err(anyhow::Error::msg)?,
|
||||
serde_json::to_string_pretty(&pv).map_err(anyhow::Error::msg)?,
|
||||
serde_json::to_string_pretty(&v).map_err(anyhow::Error::msg)?,
|
||||
)
|
||||
}
|
||||
_ => Rc::make_mut(map).insert(k.clone(), v.clone()),
|
||||
|
||||
Reference in New Issue
Block a user