--- a/cmds/jrsonnet/src/main.rs +++ b/cmds/jrsonnet/src/main.rs @@ -42,19 +42,42 @@ } } +#[derive(Clone)] +struct ExtStr { + name: String, + value: String, +} +impl FromStr for ExtStr { + type Err = &'static str; + fn from_str(s: &str) -> Result { + let out: Vec<_> = s.split('=').collect(); + match out.len() { + 1 => Ok(ExtStr { + name: out[0].to_owned(), + value: std::env::var(out[0]).or(Err("missing env var"))?, + }), + 2 => Ok(ExtStr { + name: out[0].to_owned(), + value: out[1].to_owned(), + }), + _ => Err("bad ext-str syntax"), + } + } +} + #[derive(Clap)] #[clap(version = "0.1.0", author = "Lach ")] struct Opts { #[clap(long, about = "Disable global std variable")] no_stdlib: bool, #[clap(long, about = "Add external string")] - ext_str: Option>, + ext_str: Vec, #[clap(long, about = "Add external string from code")] - ext_code: Option>, + ext_code: Vec, #[clap(long, about = "Add TLA")] - tla_str: Option>, + tla_str: Vec, #[clap(long, about = "Add TLA from code")] - tla_code: Option>, + tla_code: Vec, #[clap(long, short = "f", default_value = "json", possible_values = &["none", "json", "yaml"], about = "Output format, wraps resulting value to corresponding std.manifest call")] format: Format, #[clap(long, default_value = "default", possible_values = &["cpp", "go", "default"], about = "Emulated needed stacktrace display")] @@ -92,6 +115,12 @@ if !opts.no_stdlib { evaluator.with_stdlib(); } + for ExtStr { name, value } in opts.ext_str.iter().cloned() { + evaluator.add_ext_var(name, Val::Str(value)); + } + for ExtStr { name, value } in opts.ext_code.iter().cloned() { + evaluator.add_ext_var(name, evaluator.parse_evaluate_raw(&value).unwrap()); + } let mut input = current_dir().unwrap(); input.push(opts.input.clone()); let code_string = String::from_utf8(std::fs::read(opts.input.clone()).unwrap()).unwrap(); --- a/crates/jsonnet-evaluator/src/error.rs +++ b/crates/jsonnet-evaluator/src/error.rs @@ -12,6 +12,8 @@ TooManyArgsFunctionHas(usize), FunctionParameterNotBoundInCall(String), + UndefinedExternalVariable(String), + RuntimeError(String), StackOverflow, FractionalIndex, --- a/crates/jsonnet-evaluator/src/evaluate.rs +++ b/crates/jsonnet-evaluator/src/evaluate.rs @@ -533,6 +533,20 @@ panic!("bad pow call"); } } + ("std", "extVar") => { + assert_eq!(args.len(), 1); + if let Val::Str(a) = evaluate(context, &args[0].1)? { + with_state(|s| s.0.ext_vars.borrow().get(&a).cloned()).ok_or_else( + || { + create_error::<()>(crate::Error::UndefinedExternalVariable(a)) + .err() + .unwrap() + }, + )? + } else { + panic!("bad extVar call"); + } + } (ns, name) => panic!("Intristic not found: {}.{}", ns, name), }, Val::Func(f) => { --- a/crates/jsonnet-evaluator/src/lib.rs +++ b/crates/jsonnet-evaluator/src/lib.rs @@ -72,6 +72,9 @@ files: RefCell>, globals: RefCell>, + /// Values to use with std.extVar + ext_vars: RefCell>, + settings: EvaluationSettings, } @@ -177,6 +180,9 @@ pub fn add_global(&self, name: String, value: Val) { self.0.globals.borrow_mut().insert(name, value); } + pub fn add_ext_var(&self, name: String, value: Val) { + self.0.ext_vars.borrow_mut().insert(name, value); + } pub fn with_stdlib(&self) -> &Self { self.begin_state();