mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
no_std support (#232)
- Disable default features in dependencies - Use anyhow::Error::msg to map errors. Note: anyhow will itself be removed later. - lazy_static/spin_no_std used in no_std environments - ensure_no_std binary is built to target thumbv7m-none-eabi to ensure that there are no std dependencies. thumbv7m-none-eabi target has no std support. - The opa-no-std feature enables only those Regorus features that work with no_std. - Enable tests with no_std - Update sizes of regorus binary in README.md - Ensure that regorus example can be built with only std - Ensure that regorus example can be built with no_std Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
01fc234a33
commit
e86b590f91
@@ -1,53 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use crate::ast::{Expr, Ref};
|
||||
use crate::builtins;
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
// TODO: Should we avoid this limit?
|
||||
const MAX_ARGS: u8 = core::u8::MAX;
|
||||
|
||||
pub fn register(m: &mut builtins::BuiltinsMap<&'static str, builtins::BuiltinFcn>) {
|
||||
m.insert("print", (print, MAX_ARGS));
|
||||
}
|
||||
|
||||
pub fn print_to_string(
|
||||
span: &Span,
|
||||
_params: &[Ref<Expr>],
|
||||
args: &[Value],
|
||||
_strict: bool,
|
||||
) -> Result<String> {
|
||||
if args.len() > MAX_ARGS as usize {
|
||||
bail!(span.error("print supports up to 100 arguments"));
|
||||
}
|
||||
|
||||
let mut msg = String::default();
|
||||
for a in args {
|
||||
match a {
|
||||
Value::Undefined => msg += " <undefined>",
|
||||
Value::String(s) => msg += &format!(" {s}"),
|
||||
_ => msg += &format!(" {a}"),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
// Symbol analyzer must ensure that vars used by print are defined before
|
||||
// the print statement. Scheduler must ensure the above constraint.
|
||||
// Additionally interpreter must allow undefined inputs to print.
|
||||
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() {
|
||||
std::eprintln!("{}", &msg[1..]);
|
||||
}
|
||||
|
||||
Ok(Value::Bool(true))
|
||||
}
|
||||
+21
-13
@@ -63,7 +63,13 @@ fn base64_decode(
|
||||
ensure_args_count(span, name, params, args, 1)?;
|
||||
|
||||
let encoded_str = ensure_string(name, ¶ms[0], &args[0])?;
|
||||
let decoded_bytes = data_encoding::BASE64.decode(encoded_str.as_bytes())?;
|
||||
let decoded_bytes = data_encoding::BASE64
|
||||
.decode(encoded_str.as_bytes())
|
||||
.map_err(|e| {
|
||||
params[0]
|
||||
.span()
|
||||
.error(&format!("decode failed\nCaused by\n{e}"))
|
||||
})?;
|
||||
Ok(Value::String(
|
||||
String::from_utf8_lossy(&decoded_bytes).into(),
|
||||
))
|
||||
@@ -173,7 +179,13 @@ fn hex_decode(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool)
|
||||
ensure_args_count(span, name, params, args, 1)?;
|
||||
|
||||
let encoded_str = ensure_string(name, ¶ms[0], &args[0])?;
|
||||
let decoded_bytes = data_encoding::HEXLOWER_PERMISSIVE.decode(encoded_str.as_bytes())?;
|
||||
let decoded_bytes = data_encoding::HEXLOWER_PERMISSIVE
|
||||
.decode(encoded_str.as_bytes())
|
||||
.map_err(|e| {
|
||||
params[0]
|
||||
.span()
|
||||
.error(&format!("decode failure\nCaused by\n{e}"))
|
||||
})?;
|
||||
Ok(Value::String(
|
||||
String::from_utf8_lossy(&decoded_bytes).into(),
|
||||
))
|
||||
@@ -361,11 +373,9 @@ fn json_is_valid(
|
||||
fn json_marshal(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Result<Value> {
|
||||
let name = "json.marshal";
|
||||
ensure_args_count(span, name, params, args, 1)?;
|
||||
Ok(Value::String(
|
||||
serde_json::to_string(&args[0])
|
||||
.with_context(|| span.error("could not serialize to json"))?
|
||||
.into(),
|
||||
))
|
||||
Ok(Value::from(serde_json::to_string(&args[0]).map_err(
|
||||
|e| span.error(&format!("could not serialize to json\nCaused by\n{e}")),
|
||||
)?))
|
||||
}
|
||||
|
||||
fn json_marshal_with_options(
|
||||
@@ -406,15 +416,13 @@ fn json_marshal_with_options(
|
||||
}
|
||||
|
||||
if !pretty || options.is_empty() {
|
||||
return Ok(Value::String(
|
||||
serde_json::to_string(&args[0])
|
||||
.with_context(|| span.error("could not serialize to json"))?
|
||||
.into(),
|
||||
));
|
||||
return Ok(Value::from(serde_json::to_string(&args[0]).map_err(
|
||||
|e| span.error(&format!("could not serialize to json\nCaused by\n{e}")),
|
||||
)?));
|
||||
}
|
||||
|
||||
let lines: Vec<String> = serde_json::to_string_pretty(&args[0])
|
||||
.with_context(|| span.error("could not serialize to json"))?
|
||||
.map_err(|e| span.error(&format!("could not serialize to json\nCaused by\n{e}")))?
|
||||
.split('\n')
|
||||
.map(|line| {
|
||||
let mut line = line.to_string();
|
||||
|
||||
@@ -9,7 +9,6 @@ mod conversions;
|
||||
|
||||
#[cfg(feature = "crypto")]
|
||||
mod crypto;
|
||||
mod debugging;
|
||||
#[cfg(feature = "deprecated")]
|
||||
pub mod deprecated;
|
||||
mod encoding;
|
||||
@@ -54,8 +53,6 @@ use lazy_static::lazy_static;
|
||||
|
||||
pub type BuiltinFcn = (fn(&Span, &[Ref<Expr>], &[Value], bool) -> Result<Value>, u8);
|
||||
|
||||
pub use debugging::print_to_string;
|
||||
|
||||
#[cfg(feature = "deprecated")]
|
||||
pub use deprecated::DEPRECATED;
|
||||
|
||||
@@ -104,7 +101,6 @@ lazy_static! {
|
||||
//rego::register(&mut m);
|
||||
#[cfg(feature = "opa-runtime")]
|
||||
opa::register(&mut m);
|
||||
debugging::register(&mut m);
|
||||
tracing::register(&mut m);
|
||||
units::register(&mut m);
|
||||
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
|
||||
use crate::ast::{ArithOp, Expr, Ref};
|
||||
use crate::builtins;
|
||||
use crate::builtins::utils::{ensure_args_count, ensure_numeric, ensure_string};
|
||||
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};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
pub fn register(m: &mut builtins::BuiltinsMap<&'static str, builtins::BuiltinFcn>) {
|
||||
@@ -18,6 +20,7 @@ pub fn register(m: &mut builtins::BuiltinsMap<&'static str, builtins::BuiltinFcn
|
||||
m.insert("floor", (floor, 1));
|
||||
m.insert("numbers.range", (range, 2));
|
||||
m.insert("numbers.range_step", (range_step, 3));
|
||||
#[cfg(feature = "std")]
|
||||
m.insert("rand.intn", (intn, 2));
|
||||
m.insert("round", (round, 1));
|
||||
}
|
||||
@@ -155,10 +158,11 @@ fn round(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Re
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn intn(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Result<Value> {
|
||||
let fcn = "rand.intn";
|
||||
ensure_args_count(span, fcn, params, args, 2)?;
|
||||
let _ = ensure_string(fcn, ¶ms[0], &args[0])?;
|
||||
let _ = crate::builtins::utils::ensure_string(fcn, ¶ms[0], &args[0])?;
|
||||
let n = ensure_numeric(fcn, ¶ms[0], &args[1])?;
|
||||
|
||||
Ok(match n.as_u64() {
|
||||
|
||||
@@ -38,6 +38,7 @@ fn opa_runtime(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool)
|
||||
);
|
||||
|
||||
// Emitting environment variables could lead to confidential data being leaked.
|
||||
#[cfg(feature = "std")]
|
||||
if false {
|
||||
obj.insert(
|
||||
Value::String("env".into()),
|
||||
|
||||
@@ -24,8 +24,8 @@ fn compare(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) ->
|
||||
|
||||
let v1 = ensure_string(name, ¶ms[0], &args[0])?;
|
||||
let v2 = ensure_string(name, ¶ms[1], &args[1])?;
|
||||
let version1 = Version::parse(&v1)?;
|
||||
let version2 = Version::parse(&v2)?;
|
||||
let version1 = Version::parse(&v1).map_err(|_| params[0].span().error("invalid semver"))?;
|
||||
let version2 = Version::parse(&v2).map_err(|_| params[0].span().error("invalid semver"))?;
|
||||
let result = match version1.cmp_precedence(&version2) {
|
||||
Ordering::Less => -1,
|
||||
Ordering::Equal => 0,
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::builtins::time;
|
||||
use crate::builtins::utils::{ensure_args_count, ensure_string};
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
use crate::*;
|
||||
|
||||
use std::thread;
|
||||
|
||||
@@ -21,7 +22,8 @@ fn sleep(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Re
|
||||
ensure_args_count(span, name, params, args, 1)?;
|
||||
|
||||
let val = ensure_string(name, ¶ms[0], &args[0])?;
|
||||
let dur = time::compat::parse_duration(val.as_ref())?;
|
||||
let dur = time::compat::parse_duration(val.as_ref())
|
||||
.map_err(|e| params[0].span().error(&format!("{e}")))?;
|
||||
|
||||
thread::sleep(dur.to_std()?);
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ fn parse_duration_ns(
|
||||
ensure_args_count(span, name, params, args, 1)?;
|
||||
|
||||
let value = ensure_string(name, ¶ms[0], &args[0])?;
|
||||
let dur = compat::parse_duration(value.as_ref())?;
|
||||
let dur = compat::parse_duration(value.as_ref()).map_err(anyhow::Error::msg)?;
|
||||
safe_timestamp_nanos(span, strict, dur.num_nanoseconds())
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
use crate::*;
|
||||
use core::fmt;
|
||||
use core::iter;
|
||||
use std::error::Error;
|
||||
|
||||
use chrono::TimeZone;
|
||||
use chrono::{
|
||||
@@ -72,8 +71,6 @@ impl fmt::Display for ParseDurationError {
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ParseDurationError {}
|
||||
|
||||
// Parses a duration string in the form of `10h12m45s`.
|
||||
//
|
||||
// Adapted from Go's `time.ParseDuration`:
|
||||
|
||||
Reference in New Issue
Block a user