1use std::{fs::read_to_string, str::FromStr};
2
3use clap::Parser;
4use jrsonnet_evaluator::{trace::PathResolver, Result};
5use jrsonnet_stdlib::ContextInitializer;
6
7#[derive(Clone)]
8pub struct ExtStr {
9 pub name: String,
10 pub value: String,
11}
12
13impl FromStr for ExtStr {
38 type Err = &'static str;
39
40 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
41 match s.find('=') {
42 Some(idx) => Ok(Self {
43 name: s[..idx].to_owned(),
44 value: s[idx + 1..].to_owned(),
45 }),
46 None => Ok(Self {
47 name: s.to_owned(),
48 value: std::env::var(s).or(Err("missing env var"))?,
49 }),
50 }
51 }
52}
53
54#[derive(Clone)]
55pub struct ExtFile {
56 pub name: String,
57 pub value: String,
58}
59
60impl FromStr for ExtFile {
61 type Err = String;
62
63 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
64 let out: Vec<&str> = s.split('=').collect();
65 if out.len() != 2 {
66 return Err("bad ext-file syntax".to_owned());
67 }
68 let file = read_to_string(out[1]);
69 match file {
70 Ok(content) => Ok(Self {
71 name: out[0].into(),
72 value: content,
73 }),
74 Err(e) => Err(format!("{e}")),
75 }
76 }
77}
78
79#[derive(Parser)]
80#[clap(next_help_heading = "STANDARD LIBRARY")]
81pub struct StdOpts {
82 #[clap(long)]
85 no_stdlib: bool,
86 #[clap(long, short = 'V', name = "name[=var data]", number_of_values = 1)]
92 ext_str: Vec<ExtStr>,
93 #[clap(long, name = "name=var path", number_of_values = 1)]
96 ext_str_file: Vec<ExtFile>,
97 #[clap(long, name = "name[=var source]", number_of_values = 1)]
100 ext_code: Vec<ExtStr>,
101 #[clap(long, name = "name=var code path", number_of_values = 1)]
104 ext_code_file: Vec<ExtFile>,
105}
106impl StdOpts {
107 pub fn context_initializer(&self) -> Result<Option<ContextInitializer>> {
108 if self.no_stdlib {
109 return Ok(None);
110 }
111 let ctx = ContextInitializer::new(PathResolver::new_cwd_fallback());
112 for ext in &self.ext_str {
113 ctx.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into());
114 }
115 for ext in &self.ext_str_file {
116 ctx.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into());
117 }
118 for ext in &self.ext_code {
119 ctx.add_ext_code(&ext.name as &str, &ext.value as &str)?;
120 }
121 for ext in &self.ext_code_file {
122 ctx.add_ext_code(&ext.name as &str, &ext.value as &str)?;
123 }
124 Ok(Some(ctx))
125 }
126}