diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 14ae72f..ec4b4b9 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -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 diff --git a/Cargo.toml b/Cargo.toml index c3b40e2..7d753bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/scripts/pre-push b/scripts/pre-push index edb9ef6..7a2bec8 100755 --- a/scripts/pre-push +++ b/scripts/pre-push @@ -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 diff --git a/src/ast.rs b/src/ast.rs index eee207c..7863ddb 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -3,7 +3,7 @@ use crate::lexer::*; use crate::value::Value; -use crate::Rc; +use crate::*; use core::{cmp, fmt, ops::Deref}; diff --git a/src/builtins/aggregates.rs b/src/builtins/aggregates.rs index f35109e..9d7fc9d 100644 --- a/src/builtins/aggregates.rs +++ b/src/builtins/aggregates.rs @@ -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}; diff --git a/src/builtins/conversions.rs b/src/builtins/conversions.rs index 0905035..96d20ad 100644 --- a/src/builtins/conversions.rs +++ b/src/builtins/conversions.rs @@ -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}; diff --git a/src/builtins/debugging.rs b/src/builtins/debugging.rs index 6657c2c..003e138 100644 --- a/src/builtins/debugging.rs +++ b/src/builtins/debugging.rs @@ -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], args: &[Value], strict: bool) -> Result { 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)) } diff --git a/src/builtins/deprecated.rs b/src/builtins/deprecated.rs index da29c5a..78a8757 100644 --- a/src/builtins/deprecated.rs +++ b/src/builtins/deprecated.rs @@ -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; diff --git a/src/builtins/encoding.rs b/src/builtins/encoding.rs index 0538ccd..6c05a05 100644 --- a/src/builtins/encoding.rs +++ b/src/builtins/encoding.rs @@ -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}; diff --git a/src/builtins/glob.rs b/src/builtins/glob.rs index b062a36..8b6bfad 100644 --- a/src/builtins/glob.rs +++ b/src/builtins/glob.rs @@ -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}; diff --git a/src/builtins/graph.rs b/src/builtins/graph.rs index 9663344..a4926b9 100644 --- a/src/builtins/graph.rs +++ b/src/builtins/graph.rs @@ -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}; diff --git a/src/builtins/jwt.rs b/src/builtins/jwt.rs index a23e7cb..3cfa594 100644 --- a/src/builtins/jwt.rs +++ b/src/builtins/jwt.rs @@ -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; diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 676e307..9abfd58 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -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; diff --git a/src/builtins/numbers.rs b/src/builtins/numbers.rs index b9ac70a..a3bf55c 100644 --- a/src/builtins/numbers.rs +++ b/src/builtins/numbers.rs @@ -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}; diff --git a/src/builtins/objects.rs b/src/builtins/objects.rs index 4547788..dbb207a 100644 --- a/src/builtins/objects.rs +++ b/src/builtins/objects.rs @@ -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; diff --git a/src/builtins/opa.rs b/src/builtins/opa.rs index 0d96792..fc38865 100644 --- a/src/builtins/opa.rs +++ b/src/builtins/opa.rs @@ -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; diff --git a/src/builtins/regex.rs b/src/builtins/regex.rs index 5ceb818..f155949 100644 --- a/src/builtins/regex.rs +++ b/src/builtins/regex.rs @@ -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; diff --git a/src/builtins/sets.rs b/src/builtins/sets.rs index 978a8fa..797f917 100644 --- a/src/builtins/sets.rs +++ b/src/builtins/sets.rs @@ -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; diff --git a/src/builtins/strings.rs b/src/builtins/strings.rs index 6dc571e..9c9cb35 100644 --- a/src/builtins/strings.rs +++ b/src/builtins/strings.rs @@ -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}; diff --git a/src/builtins/time.rs b/src/builtins/time.rs index 47e5584..12cf474 100644 --- a/src/builtins/time.rs +++ b/src/builtins/time.rs @@ -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}; diff --git a/src/builtins/time/compat.rs b/src/builtins/time/compat.rs index 026fd0f..e2e0b44 100644 --- a/src/builtins/time/compat.rs +++ b/src/builtins/time/compat.rs @@ -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); } diff --git a/src/builtins/units.rs b/src/builtins/units.rs index ada4715..fec7bee 100644 --- a/src/builtins/units.rs +++ b/src/builtins/units.rs @@ -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], 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(), diff --git a/src/builtins/utils.rs b/src/builtins/utils.rs index 0b66b3c..798532d 100644 --- a/src/builtins/utils.rs +++ b/src/builtins/utils.rs @@ -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}; diff --git a/src/builtins/uuid.rs b/src/builtins/uuid.rs index f9d8d07..92c337e 100644 --- a/src/builtins/uuid.rs +++ b/src/builtins/uuid.rs @@ -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; diff --git a/src/engine.rs b/src/engine.rs index 4608f0b..073dc56 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -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>(&mut self, path: P) -> Result<()> { + #[cfg(feature = "std")] + pub fn add_policy_from_file>(&mut self, path: P) -> Result<()> { let source = Source::from_file(path)?; let mut parser = Parser::new(&source)?; self.modules.push(Ref::new(parser.parse()?)); diff --git a/src/interpreter.rs b/src/interpreter.rs index 562b11b..caa0a29 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -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; @@ -53,8 +52,8 @@ pub struct Interpreter { loop_var_values: BTreeMap, contexts: Vec, functions: FunctionTable, - rules: HashMap>>, - default_rules: HashMap>, + rules: Map>>, + default_rules: Map>, processed: BTreeSet>, processed_paths: Value, rule_values: BTreeMap, (Value, Ref)>, @@ -65,16 +64,16 @@ pub struct Interpreter { allow_deprecated: bool, strict_builtin_errors: bool, imports: BTreeMap>, - extensions: HashMap>)>, + extensions: Map>)>, #[cfg(feature = "coverage")] - coverage: HashMap>, + coverage: Map>, #[cfg(feature = "coverage")] enable_coverage: bool, gather_prints: bool, prints: Vec, - rule_paths: HashSet, + rule_paths: Set, } 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, ) -> 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) { diff --git a/src/lexer.rs b/src/lexer.rs index eed58c4..55420f5 100644 --- a/src/lexer.rs +++ b/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(&self, state: &mut H) { +#[cfg(feature = "std")] +impl std::hash::Hash for Source { + fn hash(&self, state: &mut H) { Rc::as_ptr(&self.src).hash(state) } } @@ -156,7 +153,8 @@ impl Source { }) } - pub fn from_file>(path: P) -> Result { + #[cfg(feature = "std")] + pub fn from_file>(path: P) -> Result { let contents = match std::fs::read_to_string(&path) { Ok(c) => c, Err(e) => bail!("Failed to read {}. {e}", path.as_ref().display()), diff --git a/src/lib.rs b/src/lib.rs index 2b50461..f30546c 100644 --- a/src/lib.rs +++ b/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 { diff --git a/src/number.rs b/src/number.rs index b876aea..ce78e11 100644 --- a/src/number.rs +++ b/src/number.rs @@ -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; diff --git a/src/parser.rs b/src/parser.rs index 6b0500c..3f34eab 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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) diff --git a/src/scheduler.rs b/src/scheduler.rs index a9423a7..98f96c5 100644 --- a/src/scheduler.rs +++ b/src/scheduler.rs @@ -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( } 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(), )); diff --git a/src/tests/interpreter/mod.rs b/src/tests/interpreter/mod.rs index 3bdfee5..a68701e 100644 --- a/src/tests/interpreter/mod.rs +++ b/src/tests/interpreter/mod.rs @@ -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(()) diff --git a/src/tests/scheduler/analyzer/mod.rs b/src/tests/scheduler/analyzer/mod.rs index 2e3509d..7b2360f 100644 --- a/src/tests/scheduler/analyzer/mod.rs +++ b/src/tests/scheduler/analyzer/mod.rs @@ -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(()) } diff --git a/src/tests/scheduler/mod.rs b/src/tests/scheduler/mod.rs index 9462dc8..1dece4b 100644 --- a/src/tests/scheduler/mod.rs +++ b/src/tests/scheduler/mod.rs @@ -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]); diff --git a/src/utils.rs b/src/utils.rs index a854903..cdb0b65 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -4,6 +4,7 @@ use crate::ast::*; use crate::builtins::*; use crate::lexer::*; +use crate::*; use alloc::collections::BTreeMap; diff --git a/src/value.rs b/src/value.rs index 53a1993..212aee3 100644 --- a/src/value.rs +++ b/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 { - 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>(path: P) -> Result { + #[cfg(feature = "std")] + pub fn from_json_file>(path: P) -> Result { 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 { - 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()),