git.delta.rocks / jrsonnet / refs/commits / f0883bbdc9f6

difftreelog

refactor move more stdlib functions to builtins

Yaroslav Bolyukin2024-06-18parent: #f319c35.patch.diff
in: master

16 files changed

modifiedcrates/jrsonnet-cli/src/manifest.rsdiffbeforeafterboth
4use jrsonnet_evaluator::manifest::{4use jrsonnet_evaluator::manifest::{
5 JsonFormat, ManifestFormat, StringFormat, ToStringFormat, YamlStreamFormat,5 JsonFormat, ManifestFormat, StringFormat, ToStringFormat, YamlStreamFormat,
6};6};
7use jrsonnet_stdlib::{TomlFormat, YamlFormat};7use jrsonnet_stdlib::{TomlFormat, XmlJsonmlFormat, YamlFormat};
88
9#[derive(Clone, Copy, ValueEnum)]9#[derive(Clone, Copy, ValueEnum)]
10pub enum ManifestFormatName {10pub enum ManifestFormatName {
13 Json,13 Json,
14 Yaml,14 Yaml,
15 Toml,15 Toml,
16 XmlJsonml,
16}17}
1718
18#[derive(Parser)]19#[derive(Parser)]
70 #[cfg(feature = "exp-preserve-order")]71 #[cfg(feature = "exp-preserve-order")]
71 preserve_order,72 preserve_order,
72 )),73 )),
74 ManifestFormatName::XmlJsonml => Box::new(XmlJsonmlFormat::cli()),
73 }75 }
74 };76 };
75 if self.yaml_stream {77 if self.yaml_stream {
76 Box::new(YamlStreamFormat(format))78 Box::new(YamlStreamFormat::cli(format))
77 } else {79 } else {
78 format80 format
79 }81 }
modifiedcrates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth
1use std::any::Any;1use std::{
2 any::Any,
3 num::{NonZeroU32, NonZeroUsize},
4};
25
3use jrsonnet_gcmodule::{Cc, Trace};6use jrsonnet_gcmodule::{Cc, Trace};
4use jrsonnet_interner::IBytes;7use jrsonnet_interner::IBytes;
99 Self::new(RangeArray::new_inclusive(a, b))102 Self::new(RangeArray::new_inclusive(a, b))
100 }103 }
101104
105 /// # Panics
106 /// If step == 0
102 #[must_use]107 #[must_use]
103 pub fn slice(108 pub fn slice(self, index: Option<i32>, end: Option<i32>, step: Option<NonZeroU32>) -> Self {
104 self,
105 from: Option<usize>,
106 to: Option<usize>,
107 step: Option<usize>,
108 ) -> Option<Self> {
109 let len = self.len();109 let get_idx = |pos: Option<i32>, len: usize, default| match pos {
110 Some(v) if v < 0 => len.saturating_sub((-v) as usize),
111 Some(v) => (v as usize).min(len),
112 None => default,
113 };
110 let from = from.unwrap_or(0);114 let index = get_idx(index, self.len(), 0);
111 let to = to.unwrap_or(len).min(len);115 let end = get_idx(end, self.len(), self.len());
112 let step = step.unwrap_or(1);116 let step = step.unwrap_or_else(|| NonZeroU32::new(1).expect("1 != 0"));
113117
114 if from >= to || step == 0 {118 if index >= end {
115 return None;119 return Self::empty();
116 }120 }
117121
118 Some(Self::new(SliceArray {122 Self::new(SliceArray {
119 inner: self,123 inner: self,
120 from: from as u32,124 from: index as u32,
121 to: to as u32,125 to: end as u32,
122 step: step as u32,126 step: step.get(),
123 }))127 })
124 }128 }
125129
126 /// Array length.130 /// Array length.
modifiedcrates/jrsonnet-evaluator/src/manifest.rsdiffbeforeafterboth
340 }340 }
341}341}
342342
343pub struct YamlStreamFormat<I>(pub I);343pub struct YamlStreamFormat<I> {
344 inner: I,
345 c_document_end: bool,
346 end_newline: bool,
347}
348impl<I> YamlStreamFormat<I> {
349 pub fn std_yaml_stream(inner: I, c_document_end: bool) -> Self {
350 Self {
351 inner,
352 c_document_end,
353 // Stdlib format always inserts newline at the end
354 end_newline: true,
355 }
356 }
357 pub fn cli(inner: I) -> Self {
358 Self {
359 inner,
360 c_document_end: true,
361 end_newline: false,
362 }
363 }
364}
344impl<I: ManifestFormat> ManifestFormat for YamlStreamFormat<I> {365impl<I: ManifestFormat> ManifestFormat for YamlStreamFormat<I> {
345 fn manifest_buf(&self, val: Val, out: &mut String) -> Result<()> {366 fn manifest_buf(&self, val: Val, out: &mut String) -> Result<()> {
346 let Val::Arr(arr) = val else {367 let Val::Arr(arr) = val else {
353 for v in arr.iter() {374 for v in arr.iter() {
354 let v = v?;375 let v = v?;
355 out.push_str("---\n");376 out.push_str("---\n");
356 self.0.manifest_buf(v, out)?;377 self.inner.manifest_buf(v, out)?;
357 out.push('\n');378 out.push('\n');
358 }379 }
359 out.push_str("...");
360 }380 }
381 if self.c_document_end {
382 out.push_str("...");
383 }
384 if self.end_newline {
385 out.push('\n');
386 }
361 Ok(())387 Ok(())
362 }388 }
363}389}
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
2 cell::RefCell,2 cell::RefCell,
3 fmt::{self, Debug, Display},3 fmt::{self, Debug, Display},
4 mem::replace,4 mem::replace,
5 num::{NonZeroU32, NonZeroUsize},
5 rc::Rc,6 rc::Rc,
6};7};
78
277 .into(),278 .into(),
278 ))279 ))
279 }280 }
280 Self::Arr(arr) => {281 Self::Arr(arr) => Ok(Self::Arr(arr.clone().slice(
281 let get_idx = |pos: Option<i32>, len: usize, default| match pos {
282 Some(v) if v < 0 => len.saturating_sub((-v) as usize),
283 Some(v) => (v as usize).min(len),
284 None => default,
285 };
286 let index = get_idx(index, arr.len(), 0);
287 let end = get_idx(end, arr.len(), arr.len());
288 let step = step.as_deref().copied().unwrap_or(1);
289
290 if index >= end {
291 return Ok(Self::Arr(ArrValue::empty()));
292 }
293
294 Ok(Self::Arr(
295 arr.clone()
296 .slice(Some(index), Some(end), Some(step))282 index,
297 .expect("arguments checked"),283 end,
284 step.map(|v| NonZeroU32::new(v.value() as u32).expect("bounded != 0")),
298 ))285 ))),
299 }
300 }286 }
301 }287 }
302}288}
modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
3434
35 Ok(Some(attr))35 Ok(Some(attr))
36}36}
37fn remove_attr<I>(attrs: &mut Vec<Attribute>, ident: I)
38where
39 Ident: PartialEq<I>,
40{
41 attrs.retain(|a| !a.path().is_ident(&ident));
42}
3743
38fn path_is(path: &Path, needed: &str) -> bool {44fn path_is(path: &Path, needed: &str) -> bool {
39 path.leading_colon.is_none()45 path.leading_colon.is_none()
121 }127 }
122}128}
129
130enum Optionality {
131 Required,
132 Optional,
133 Default(Expr),
134}
135impl Optionality {
136 fn is_optional(&self) -> bool {
137 !matches!(self, Self::Required)
138 }
139}
123140
124enum ArgInfo {141enum ArgInfo {
125 Normal {142 Normal {
126 ty: Box<Type>,143 ty: Box<Type>,
127 is_option: bool,144 optionality: Optionality,
128 name: Option<String>,145 name: Option<String>,
129 cfg_attrs: Vec<Attribute>,146 cfg_attrs: Vec<Attribute>,
130 },147 },
138}155}
139156
140impl ArgInfo {157impl ArgInfo {
141 fn parse(name: &str, arg: &FnArg) -> Result<Self> {158 fn parse(name: &str, arg: &mut FnArg) -> Result<Self> {
142 let FnArg::Typed(arg) = arg else {159 let FnArg::Typed(arg) = arg else {
143 unreachable!()160 unreachable!()
144 };161 };
163 _ => {}180 _ => {}
164 }181 }
165182
166 let (is_option, ty) = if let Some(ty) = extract_type_from_option(ty)? {183 let (optionality, ty) = if let Some(default) = parse_attr::<_, _>(&arg.attrs, "default")? {
184 remove_attr(&mut arg.attrs, "default");
185 (Optionality::Default(default), ty.clone())
186 } else if let Some(ty) = extract_type_from_option(ty)? {
167 if type_is_path(ty, "Thunk").is_some() {187 if type_is_path(ty, "Thunk").is_some() {
168 return Ok(Self::Lazy {188 return Ok(Self::Lazy {
169 is_option: true,189 is_option: true,
170 name: ident.map(|v| v.to_string()),190 name: ident.map(|v| v.to_string()),
171 });191 });
172 }192 }
173193
174 (true, Box::new(ty.clone()))194 (Optionality::Optional, Box::new(ty.clone()))
175 } else {195 } else {
176 (false, ty.clone())196 (Optionality::Required, ty.clone())
177 };197 };
178198
179 let cfg_attrs = arg199 let cfg_attrs = arg
185205
186 Ok(Self::Normal {206 Ok(Self::Normal {
187 ty,207 ty,
188 is_option,208 optionality,
189 name: ident.map(|v| v.to_string()),209 name: ident.map(|v| v.to_string()),
190 cfg_attrs,210 cfg_attrs,
191 })211 })
201 let item_fn = item.clone();221 let item_fn = item.clone();
202 let item_fn: ItemFn = parse_macro_input!(item_fn);222 let item_fn: ItemFn = parse_macro_input!(item_fn);
203223
204 match builtin_inner(attr, item_fn, item.into()) {224 match builtin_inner(attr, item_fn) {
205 Ok(v) => v.into(),225 Ok(v) => v.into(),
206 Err(e) => e.into_compile_error().into(),226 Err(e) => e.into_compile_error().into(),
207 }227 }
208}228}
209229
210#[allow(clippy::too_many_lines)]230#[allow(clippy::too_many_lines)]
211fn builtin_inner(231fn builtin_inner(attr: BuiltinAttrs, mut fun: ItemFn) -> syn::Result<TokenStream> {
212 attr: BuiltinAttrs,
213 fun: ItemFn,
214 item: proc_macro2::TokenStream,
215) -> syn::Result<TokenStream> {
216 let ReturnType::Type(_, result) = &fun.sig.output else {232 let ReturnType::Type(_, result) = &fun.sig.output else {
217 return Err(Error::new(233 return Err(Error::new(
224 let args = fun240 let args = fun
225 .sig241 .sig
226 .inputs242 .inputs
227 .iter()243 .iter_mut()
228 .map(|arg| ArgInfo::parse(&name, arg))244 .map(|arg| ArgInfo::parse(&name, arg))
229 .collect::<Result<Vec<_>>>()?;245 .collect::<Result<Vec<_>>>()?;
230246
231 let params_desc = args.iter().filter_map(|a| match a {247 let params_desc = args.iter().filter_map(|a| match a {
232 ArgInfo::Normal {248 ArgInfo::Normal {
233 is_option,249 optionality,
234 name,250 name,
235 cfg_attrs,251 cfg_attrs,
236 ..252 ..
237 } => {253 } => {
238 let name = name254 let name = name
239 .as_ref()255 .as_ref()
240 .map_or_else(|| quote! {None}, |n| quote! {ParamName::new_static(#n)});256 .map_or_else(|| quote! {None}, |n| quote! {ParamName::new_static(#n)});
257 let is_optional = optionality.is_optional();
241 Some(quote! {258 Some(quote! {
242 #(#cfg_attrs)*259 #(#cfg_attrs)*
243 BuiltinParam::new(#name, #is_option),260 BuiltinParam::new(#name, #is_optional),
244 })261 })
245 }262 }
246 ArgInfo::Lazy { is_option, name } => {263 ArgInfo::Lazy { is_option, name } => {
270 .map(|(id, a)| match a {287 .map(|(id, a)| match a {
271 ArgInfo::Normal {288 ArgInfo::Normal {
272 ty,289 ty,
273 is_option,290 optionality,
274 name,291 name,
275 cfg_attrs,292 cfg_attrs,
276 } => {293 } => {
279 || format!("argument <{}> evaluation", #name),296 || format!("argument <{}> evaluation", #name),
280 || <#ty>::from_untyped(value.evaluate()?),297 || <#ty>::from_untyped(value.evaluate()?),
281 )?};298 )?};
282 let value = if *is_option {299 let value = match optionality {
300 Optionality::Required => quote! {{
301 let value = parsed[#id].as_ref().expect("args shape is checked");
302 #eval
303 },},
283 quote! {if let Some(value) = &parsed[#id] {304 Optionality::Optional => quote! {if let Some(value) = &parsed[#id] {
284 Some(#eval)305 Some(#eval)
285 } else {306 } else {
286 None307 None
287 },}308 },},
288 } else {
289 quote! {{309 Optionality::Default(expr) => quote! {if let Some(value) = &parsed[#id] {
290 let value = parsed[#id].as_ref().expect("args shape is checked");
291 #eval310 #eval
311 } else {
312 let v: #ty = #expr;
313 v
292 },}314 },},
293 };315 };
294 quote! {316 quote! {
295 #(#cfg_attrs)*317 #(#cfg_attrs)*
296 #value318 #value
343 };365 };
344366
345 Ok(quote! {367 Ok(quote! {
346 #item368 #fun
347369
348 #[doc(hidden)]370 #[doc(hidden)]
349 #[allow(non_camel_case_types)]371 #[allow(non_camel_case_types)]
373 fn params(&self) -> &[BuiltinParam] {395 fn params(&self) -> &[BuiltinParam] {
374 PARAMS396 PARAMS
375 }397 }
376 #[allow(unused_variable)]398 #[allow(unused_variables)]
377 fn call(&self, ctx: Context, location: CallLocation, args: &dyn ArgsLike) -> Result<Val> {399 fn call(&self, ctx: Context, location: CallLocation, args: &dyn ArgsLike) -> Result<Val> {
378 let parsed = parse_builtin_call(ctx.clone(), &PARAMS, args, false)?;400 let parsed = parse_builtin_call(ctx.clone(), &PARAMS, args, false)?;
379401
modifiedcrates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth
265}265}
266266
267#[builtin]267#[builtin]
268pub fn builtin_remove_at(arr: ArrValue, at: usize) -> Result<ArrValue> {268pub fn builtin_remove_at(arr: ArrValue, at: i32) -> Result<ArrValue> {
269 let newArrLeft = arr.clone().slice(None, Some(at), None);269 let newArrLeft = arr.clone().slice(None, Some(at), None);
270 let newArrRight = arr.slice(Some(at + 1), None, None);270 let newArrRight = arr.slice(Some(at + 1), None, None);
271271
272 Ok(ArrValue::extended(272 Ok(ArrValue::extended(newArrLeft, newArrRight))
273 newArrLeft.unwrap_or_else(ArrValue::empty),
274 newArrRight.unwrap_or_else(ArrValue::empty),
275 ))
276}273}
277274
278#[builtin]275#[builtin]
279pub fn builtin_remove(arr: ArrValue, elem: Val) -> Result<ArrValue> {276pub fn builtin_remove(arr: ArrValue, elem: Val) -> Result<ArrValue> {
280 for (index, item) in arr.iter().enumerate() {277 for (index, item) in arr.iter().enumerate() {
281 if equals(&item?, &elem)? {278 if equals(&item?, &elem)? {
282 return builtin_remove_at(arr.clone(), index);279 return builtin_remove_at(arr.clone(), index as i32);
283 }280 }
284 }281 }
285 Ok(arr)282 Ok(arr)
325#[builtin]322#[builtin]
326pub fn builtin_prune(323pub fn builtin_prune(
327 a: Val,324 a: Val,
325 #[default(false)]
328 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,326 #[cfg(feature = "exp-preserve-order")]
327 preserve_order: bool,
329) -> Result<Val> {328) -> Result<Val> {
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
102 ("sign", builtin_sign::INST),102 ("sign", builtin_sign::INST),
103 ("max", builtin_max::INST),103 ("max", builtin_max::INST),
104 ("min", builtin_min::INST),104 ("min", builtin_min::INST),
105 ("clamp", builtin_clamp::INST),
105 ("sum", builtin_sum::INST),106 ("sum", builtin_sum::INST),
106 ("modulo", builtin_modulo::INST),107 ("modulo", builtin_modulo::INST),
107 ("floor", builtin_floor::INST),108 ("floor", builtin_floor::INST),
163 ("objectRemoveKey", builtin_object_remove_key::INST),164 ("objectRemoveKey", builtin_object_remove_key::INST),
164 // Manifest165 // Manifest
165 ("escapeStringJson", builtin_escape_string_json::INST),166 ("escapeStringJson", builtin_escape_string_json::INST),
167 ("escapeStringPython", builtin_escape_string_json::INST),
168 ("escapeStringXML", builtin_escape_string_xml::INST),
166 ("manifestJsonEx", builtin_manifest_json_ex::INST),169 ("manifestJsonEx", builtin_manifest_json_ex::INST),
170 ("manifestJson", builtin_manifest_json::INST),
171 ("manifestJsonMinified", builtin_manifest_json_minified::INST),
167 ("manifestYamlDoc", builtin_manifest_yaml_doc::INST),172 ("manifestYamlDoc", builtin_manifest_yaml_doc::INST),
173 ("manifestYamlStream", builtin_manifest_yaml_stream::INST),
168 ("manifestTomlEx", builtin_manifest_toml_ex::INST),174 ("manifestTomlEx", builtin_manifest_toml_ex::INST),
175 ("manifestToml", builtin_manifest_toml::INST),
169 ("toString", builtin_to_string::INST),176 ("toString", builtin_to_string::INST),
170 // Parsing177 ("manifestPython", builtin_manifest_python::INST),
178 ("manifestPythonVars", builtin_manifest_python_vars::INST),
179 ("manifestXmlJsonml", builtin_manifest_xml_jsonml::INST),
180 // Parse
171 ("parseJson", builtin_parse_json::INST),181 ("parseJson", builtin_parse_json::INST),
172 ("parseYaml", builtin_parse_yaml::INST),182 ("parseYaml", builtin_parse_yaml::INST),
173 // Strings183 // Strings
174 ("codepoint", builtin_codepoint::INST),184 ("codepoint", builtin_codepoint::INST),
175 ("substr", builtin_substr::INST),185 ("substr", builtin_substr::INST),
176 ("char", builtin_char::INST),186 ("char", builtin_char::INST),
177 ("strReplace", builtin_str_replace::INST),187 ("strReplace", builtin_str_replace::INST),
188 ("escapeStringBash", builtin_escape_string_bash::INST),
189 ("escapeStringDollars", builtin_escape_string_dollars::INST),
178 ("isEmpty", builtin_is_empty::INST),190 ("isEmpty", builtin_is_empty::INST),
179 ("equalsIgnoreCase", builtin_equals_ignore_case::INST),191 ("equalsIgnoreCase", builtin_equals_ignore_case::INST),
180 ("splitLimit", builtin_splitlimit::INST),192 ("splitLimit", builtin_splitlimit::INST),
181 ("splitLimitR", builtin_splitlimitr::INST),193 ("splitLimitR", builtin_splitlimitr::INST),
194 ("split", builtin_split::INST),
182 ("asciiUpper", builtin_ascii_upper::INST),195 ("asciiUpper", builtin_ascii_upper::INST),
183 ("asciiLower", builtin_ascii_lower::INST),196 ("asciiLower", builtin_ascii_lower::INST),
184 ("findSubstr", builtin_find_substr::INST),197 ("findSubstr", builtin_find_substr::INST),
190 ("stringChars", builtin_string_chars::INST),203 ("stringChars", builtin_string_chars::INST),
191 // Misc204 // Misc
192 ("length", builtin_length::INST),205 ("length", builtin_length::INST),
206 ("get", builtin_get::INST),
193 ("startsWith", builtin_starts_with::INST),207 ("startsWith", builtin_starts_with::INST),
194 ("endsWith", builtin_ends_with::INST),208 ("endsWith", builtin_ends_with::INST),
195 // Sets209 // Sets
modifiedcrates/jrsonnet-stdlib/src/manifest/mod.rsdiffbeforeafterboth
1mod python;
1mod toml;2mod toml;
3mod xml;
2mod yaml;4mod yaml;
35
4use jrsonnet_evaluator::{6use jrsonnet_evaluator::{
5 function::builtin,7 function::builtin,
6 manifest::{escape_string_json, JsonFormat},8 manifest::{escape_string_json, JsonFormat, YamlStreamFormat},
7 IStr, ObjValue, Result, Val,9 IStr, ObjValue, Result, Val,
8};10};
11pub use python::{PythonFormat, PythonVarsFormat};
9pub use toml::TomlFormat;12pub use toml::TomlFormat;
10pub use yaml::YamlFormat;13pub use yaml::YamlFormat;
14pub use xml::XmlJsonmlFormat;
1115
12#[builtin]16#[builtin]
13pub fn builtin_escape_string_json(str_: IStr) -> Result<String> {17pub fn builtin_escape_string_json(str_: IStr) -> Result<String> {
17#[builtin]21#[builtin]
18pub fn builtin_manifest_json_ex(22pub fn builtin_manifest_json_ex(
19 value: Val,23 value: Val,
20 indent: IStr,24 indent: String,
21 newline: Option<IStr>,25 newline: Option<IStr>,
22 key_val_sep: Option<IStr>,26 key_val_sep: Option<IStr>,
27
28 #[default(false)]
23 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,29 #[cfg(feature = "exp-preserve-order")]
30 preserve_order: bool,
24) -> Result<String> {31) -> Result<String> {
25 let newline = newline.as_deref().unwrap_or("\n");32 let newline = newline.as_deref().unwrap_or("\n");
26 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");33 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");
27 value.manifest(JsonFormat::std_to_json(34 value.manifest(JsonFormat::std_to_json(
28 indent.to_string(),35 indent,
29 newline,36 newline,
30 key_val_sep,37 key_val_sep,
31 #[cfg(feature = "exp-preserve-order")]38 #[cfg(feature = "exp-preserve-order")]
32 preserve_order.unwrap_or(false),39 preserve_order,
33 ))40 ))
34}41}
42
43#[builtin]
44pub fn builtin_manifest_json(
45 value: Val,
46
47 #[default(false)]
48 #[cfg(feature = "exp-preserve-order")]
49 preserve_order: bool,
50) -> Result<String> {
51 builtin_manifest_json_ex(
52 value,
53 " ".to_owned(),
54 None,
55 None,
56 #[cfg(feature = "exp-preserve-order")]
57 preserve_order,
58 )
59}
60
61#[builtin]
62pub fn builtin_manifest_json_minified(
63 value: Val,
64
65 #[default(false)]
66 #[cfg(feature = "exp-preserve-order")]
67 preserve_order: bool,
68) -> Result<String> {
69 value.manifest(JsonFormat::minify(
70 #[cfg(feature = "exp-preserve-order")]
71 preserve_order,
72 ))
73}
3574
36#[builtin]75#[builtin]
37pub fn builtin_manifest_yaml_doc(76pub fn builtin_manifest_yaml_doc(
38 value: Val,77 value: Val,
39 indent_array_in_object: Option<bool>,78 #[default(false)] indent_array_in_object: bool,
40 quote_keys: Option<bool>,79 #[default(true)] quote_keys: bool,
80
81 #[default(false)]
41 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,82 #[cfg(feature = "exp-preserve-order")]
83 preserve_order: bool,
42) -> Result<String> {84) -> Result<String> {
43 value.manifest(YamlFormat::std_to_yaml(85 value.manifest(YamlFormat::std_to_yaml(
44 indent_array_in_object.unwrap_or(false),86 indent_array_in_object,
45 quote_keys.unwrap_or(true),87 quote_keys,
46 #[cfg(feature = "exp-preserve-order")]88 #[cfg(feature = "exp-preserve-order")]
47 preserve_order.unwrap_or(false),89 preserve_order,
48 ))90 ))
49}91}
92
93#[builtin]
94pub fn builtin_manifest_yaml_stream(
95 value: Val,
96 #[default(false)] indent_array_in_object: bool,
97 #[default(true)] c_document_end: bool,
98 #[default(true)] quote_keys: bool,
99
100 #[default(false)]
101 #[cfg(feature = "exp-preserve-order")]
102 preserve_order: bool,
103) -> Result<String> {
104 value.manifest(YamlStreamFormat::std_yaml_stream(
105 YamlFormat::std_to_yaml(
106 indent_array_in_object,
107 quote_keys,
108 #[cfg(feature = "exp-preserve-order")]
109 preserve_order,
110 ),
111 c_document_end,
112 ))
113}
50114
51#[builtin]115#[builtin]
52pub fn builtin_manifest_toml_ex(116pub fn builtin_manifest_toml_ex(
53 value: ObjValue,117 value: ObjValue,
54 indent: IStr,118 indent: String,
119
120 #[default(false)]
55 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,121 #[cfg(feature = "exp-preserve-order")]
122 preserve_order: bool,
56) -> Result<String> {123) -> Result<String> {
57 Val::Obj(value).manifest(TomlFormat::std_to_toml(124 Val::Obj(value).manifest(TomlFormat::std_to_toml(
58 indent.to_string(),125 indent,
59 #[cfg(feature = "exp-preserve-order")]126 #[cfg(feature = "exp-preserve-order")]
60 preserve_order.unwrap_or(false),127 preserve_order,
61 ))128 ))
62}129}
130
131#[builtin]
132pub fn builtin_manifest_toml(
133 value: ObjValue,
134
135 #[default(false)]
136 #[cfg(feature = "exp-preserve-order")]
137 preserve_order: bool,
138) -> Result<String> {
139 builtin_manifest_toml_ex(
140 value,
141 " ".to_owned(),
142 #[cfg(feature = "exp-preserve-order")]
143 preserve_order,
144 )
145}
63146
64#[builtin]147#[builtin]
65pub fn builtin_to_string(a: Val) -> Result<IStr> {148pub fn builtin_to_string(a: Val) -> Result<IStr> {
66 a.to_string()149 a.to_string()
67}150}
151
152#[builtin]
153pub fn builtin_manifest_python(v: Val) -> Result<String> {
154 v.manifest(PythonFormat {})
155}
156#[builtin]
157pub fn builtin_manifest_python_vars(v: Val) -> Result<String> {
158 v.manifest(PythonVarsFormat {})
159}
160
161#[builtin]
162pub fn builtin_escape_string_xml(str_: String) -> String {
163 xml::escape_string_xml(str_.as_str())
164}
165
166#[builtin]
167pub fn builtin_manifest_xml_jsonml(value: Val) -> Result<String> {
168 value.manifest(XmlJsonmlFormat::std_to_xml())
169}
68170
addedcrates/jrsonnet-stdlib/src/manifest/python.rsdiffbeforeafterboth

no changes

addedcrates/jrsonnet-stdlib/src/manifest/xml.rsdiffbeforeafterboth

no changes

modifiedcrates/jrsonnet-stdlib/src/math.rsdiffbeforeafterboth
24 a.min(b)24 a.min(b)
25}25}
26
27#[allow(non_snake_case)]
28#[builtin]
29pub fn builtin_clamp(x: f64, minVal: f64, maxVal: f64) -> f64 {
30 x.clamp(minVal, maxVal)
31}
2632
27#[builtin]33#[builtin]
28pub fn builtin_sum(arr: Vec<f64>) -> f64 {34pub fn builtin_sum(arr: Vec<f64>) -> f64 {
modifiedcrates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth
23 }23 }
24}24}
25
26#[builtin]
27pub fn builtin_get(
28 o: ObjValue,
29 f: IStr,
30 default: Option<Thunk<Val>>,
31 #[default(true)]
32 inc_hidden: bool,
33) -> Result<Val> {
34 let do_default = move || {
35 let Some(default) = default else {
36 return Ok(Val::Null);
37 };
38 default.evaluate()
39 };
40 // Happy path for invisible fields
41 if !inc_hidden && !o.has_field_ex(f.clone(), false) {
42 return do_default();
43 }
44 let Some(v) = o.get(f)? else {
45 return do_default();
46 };
47 Ok(v)
48}
2549
26#[builtin(fields(50#[builtin(fields(
27 settings: Rc<RefCell<Settings>>,51 settings: Rc<RefCell<Settings>>,
modifiedcrates/jrsonnet-stdlib/src/objects.rsdiffbeforeafterboth
9 obj: ObjValue,9 obj: ObjValue,
10 hidden: bool,10 hidden: bool,
11
12 #[default(false)]
11 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,13 #[cfg(feature = "exp-preserve-order")]
14 preserve_order: bool,
12) -> Vec<Val> {15) -> Vec<Val> {
13 #[cfg(feature = "exp-preserve-order")]
14 let preserve_order = preserve_order.unwrap_or(false);
15 let out = obj.fields_ex(16 let out = obj.fields_ex(
16 hidden,17 hidden,
17 #[cfg(feature = "exp-preserve-order")]18 #[cfg(feature = "exp-preserve-order")]
24pub fn builtin_object_fields(25pub fn builtin_object_fields(
25 o: ObjValue,26 o: ObjValue,
27
28 #[default(false)]
26 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,29 #[cfg(feature = "exp-preserve-order")]
30 preserve_order: bool,
27) -> Vec<Val> {31) -> Vec<Val> {
28 builtin_object_fields_ex(32 builtin_object_fields_ex(
37pub fn builtin_object_fields_all(41pub fn builtin_object_fields_all(
38 o: ObjValue,42 o: ObjValue,
43
44 #[default(false)]
39 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,45 #[cfg(feature = "exp-preserve-order")]
46 preserve_order: bool,
40) -> Vec<Val> {47) -> Vec<Val> {
41 builtin_object_fields_ex(48 builtin_object_fields_ex(
50 o: ObjValue,57 o: ObjValue,
51 include_hidden: bool,58 include_hidden: bool,
59
52 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,60 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,
53) -> ArrValue {61) -> ArrValue {
54 #[cfg(feature = "exp-preserve-order")]
55 let preserve_order = preserve_order.unwrap_or(false);
56 o.values_ex(62 o.values_ex(
57 include_hidden,63 include_hidden,
58 #[cfg(feature = "exp-preserve-order")]64 #[cfg(feature = "exp-preserve-order")]
63pub fn builtin_object_values(69pub fn builtin_object_values(
64 o: ObjValue,70 o: ObjValue,
71
72 #[default(false)]
65 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,73 #[cfg(feature = "exp-preserve-order")]
74 preserve_order: bool,
66) -> ArrValue {75) -> ArrValue {
67 builtin_object_values_ex(76 builtin_object_values_ex(
75pub fn builtin_object_values_all(84pub fn builtin_object_values_all(
76 o: ObjValue,85 o: ObjValue,
86
87 #[default(false)]
77 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,88 #[cfg(feature = "exp-preserve-order")]
89 preserve_order: bool,
78) -> ArrValue {90) -> ArrValue {
79 builtin_object_values_ex(91 builtin_object_values_ex(
87pub fn builtin_object_keys_values_ex(99pub fn builtin_object_keys_values_ex(
88 o: ObjValue,100 o: ObjValue,
89 include_hidden: bool,101 include_hidden: bool,
90 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,102 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,
91) -> ArrValue {103) -> ArrValue {
92 #[cfg(feature = "exp-preserve-order")]
93 let preserve_order = preserve_order.unwrap_or(false);
94 o.key_values_ex(104 o.key_values_ex(
95 include_hidden,105 include_hidden,
96 #[cfg(feature = "exp-preserve-order")]106 #[cfg(feature = "exp-preserve-order")]
101pub fn builtin_object_keys_values(111pub fn builtin_object_keys_values(
102 o: ObjValue,112 o: ObjValue,
113
114 #[default(false)]
103 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,115 #[cfg(feature = "exp-preserve-order")]
116 preserve_order: bool,
104) -> ArrValue {117) -> ArrValue {
105 builtin_object_keys_values_ex(118 builtin_object_keys_values_ex(
113pub fn builtin_object_keys_values_all(126pub fn builtin_object_keys_values_all(
114 o: ObjValue,127 o: ObjValue,
128
129 #[default(false)]
115 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,130 #[cfg(feature = "exp-preserve-order")]
131 preserve_order: bool,
116) -> ArrValue {132) -> ArrValue {
117 builtin_object_keys_values_ex(133 builtin_object_keys_values_ex(
160
144 // Standard implementation uses std.objectFields without such argument, we can't161 // Standard implementation uses std.objectFields without such argument, we can't
145 // assume order preservation should always be enabled/disabled162 // assume order preservation should always be enabled/disabled
163 #[default(false)]
146 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,164 #[cfg(feature = "exp-preserve-order")]
165 preserve_order: bool,
147) -> ObjValue {166) -> ObjValue {
148 #[cfg(feature = "exp-preserve-order")]
149 let preserve_order = preserve_order.unwrap_or(false);
150 let mut new_obj = ObjValueBuilder::with_capacity(obj.len() - 1);167 let mut new_obj = ObjValueBuilder::with_capacity(obj.len() - 1);
151 for (k, v) in obj.iter(168 for (k, v) in obj.iter(
152 #[cfg(feature = "exp-preserve-order")]169 #[cfg(feature = "exp-preserve-order")]
modifiedcrates/jrsonnet-stdlib/src/sort.rsdiffbeforeafterboth
139}139}
140140
141#[builtin]141#[builtin]
142pub fn builtin_sort(arr: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {142pub fn builtin_sort(
143 arr: ArrValue,
144
145 #[default(FuncVal::identity())] keyF: FuncVal,
146) -> Result<ArrValue> {
143 super::sort::sort(arr, keyF.unwrap_or_else(FuncVal::identity))147 super::sort::sort(arr, keyF)
144}148}
145149
146fn uniq_identity(arr: Vec<Val>) -> Result<Vec<Val>> {150fn uniq_identity(arr: Vec<Val>) -> Result<Vec<Val>> {
174178
175#[builtin]179#[builtin]
176#[allow(non_snake_case)]180#[allow(non_snake_case)]
177pub fn builtin_uniq(arr: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {181pub fn builtin_uniq(
182 arr: ArrValue,
183
184 #[default(FuncVal::identity())] keyF: FuncVal,
185) -> Result<ArrValue> {
178 if arr.len() <= 1 {186 if arr.len() <= 1 {
179 return Ok(arr);187 return Ok(arr);
180 }188 }
181 let keyF = keyF.unwrap_or(FuncVal::identity());
182 if keyF.is_identity() {189 if keyF.is_identity() {
183 Ok(ArrValue::eager(uniq_identity(190 Ok(ArrValue::eager(uniq_identity(
184 arr.iter().collect::<Result<Vec<Val>>>()?,191 arr.iter().collect::<Result<Vec<Val>>>()?,
190197
191#[builtin]198#[builtin]
192#[allow(non_snake_case)]199#[allow(non_snake_case)]
193pub fn builtin_set(arr: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {200pub fn builtin_set(
201 arr: ArrValue,
202
203 #[default(FuncVal::identity())] keyF: FuncVal,
204) -> Result<ArrValue> {
194 if arr.len() <= 1 {205 if arr.len() <= 1 {
195 return Ok(arr);206 return Ok(arr);
196 }207 }
197 let keyF = keyF.unwrap_or(FuncVal::identity());
198 if keyF.is_identity() {208 if keyF.is_identity() {
199 let arr = arr.iter().collect::<Result<Vec<Val>>>()?;209 let arr = arr.iter().collect::<Result<Vec<Val>>>()?;
200 let arr = sort_identity(arr)?;210 let arr = sort_identity(arr)?;
modifiedcrates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth
1{1{
2 local std = self,2 local std = self,
3 local id = std.id,
43
5 thisFile:: error 'std.thisFile is deprecated, to enable its support in jrsonnet - recompile it with "legacy-this-file" support.\nThis will slow down stdlib caching a bit, though',4 thisFile:: error 'std.thisFile is deprecated, to enable its support in jrsonnet - recompile it with "legacy-this-file" support.\nThis will slow down stdlib caching a bit, though',
65
20 stripChars(str, chars)::19 stripChars(str, chars)::
21 std.lstripChars(std.rstripChars(str, chars), chars),20 std.lstripChars(std.rstripChars(str, chars), chars),
2221
23 split(str, c):: std.splitLimit(str, c, -1),
24
25 mapWithIndex(func, arr)::22 mapWithIndex(func, arr)::
26 if !std.isFunction(func) then23 if !std.isFunction(func) then
27 error ('std.mapWithIndex first param must be function, got ' + std.type(func))24 error ('std.mapWithIndex first param must be function, got ' + std.type(func))
55 else52 else
56 error 'Assertion failed. ' + a + ' != ' + b,53 error 'Assertion failed. ' + a + ' != ' + b,
5754
58 clamp(x, minVal, maxVal)::
59 if x < minVal then minVal
60 else if x > maxVal then maxVal
61 else x,
62
63 manifestIni(ini)::55 manifestIni(ini)::
64 local body_lines(body) =56 local body_lines(body) =
65 std.join([], [57 std.join([], [
80 ];72 ];
81 std.join('\n', main_body + std.flattenArrays(all_sections) + ['']),73 std.join('\n', main_body + std.flattenArrays(all_sections) + ['']),
8274
83 manifestToml(value):: std.manifestTomlEx(value, ' '),
84
85 escapeStringPython(str)::
86 std.escapeStringJson(str),
87
88 escapeStringBash(str_)::
89 local str = std.toString(str_);
90 local trans(ch) =
91 if ch == "'" then
92 "'\"'\"'"
93 else
94 ch;
95 "'%s'" % std.join('', [trans(ch) for ch in std.stringChars(str)]),
96
97 escapeStringDollars(str_)::
98 local str = std.toString(str_);
99 local trans(ch) =
100 if ch == '$' then
101 '$$'
102 else
103 ch;
104 std.foldl(function(a, b) a + trans(b), std.stringChars(str), ''),
105
106 local xml_escapes = {
107 '<': '&lt;',
108 '>': '&gt;',
109 '&': '&amp;',
110 '"': '&quot;',
111 "'": '&apos;',
112 },
113
114 escapeStringXML(str_)::
115 local str = std.toString(str_);
116 std.join('', [std.get(xml_escapes, ch, ch) for ch in std.stringChars(str)]),
117
118 manifestJson(value):: std.manifestJsonEx(value, ' ') tailstrict,
119
120 manifestJsonMinified(value):: std.manifestJsonEx(value, '', '', ':'),
121
122 manifestYamlStream(value, indent_array_in_object=false, c_document_end=true, quote_keys=true)::
123 if !std.isArray(value) then
124 error 'manifestYamlStream only takes arrays, got ' + std.type(value)
125 else
126 '---\n' + std.join(
127 '\n---\n', [std.manifestYamlDoc(e, indent_array_in_object, quote_keys) for e in value]
128 ) + if c_document_end then '\n...\n' else '\n',
129
130 manifestPython(v)::
131 if std.isObject(v) then
132 local fields = [
133 '%s: %s' % [std.escapeStringPython(k), std.manifestPython(v[k])]
134 for k in std.objectFields(v)
135 ];
136 '{%s}' % [std.join(', ', fields)]
137 else if std.isArray(v) then
138 '[%s]' % [std.join(', ', [std.manifestPython(v2) for v2 in v])]
139 else if std.isString(v) then
140 '%s' % [std.escapeStringPython(v)]
141 else if std.isFunction(v) then
142 error 'cannot manifest function'
143 else if std.isNumber(v) then
144 std.toString(v)
145 else if v == true then
146 'True'
147 else if v == false then
148 'False'
149 else if v == null then
150 'None',
151
152 manifestPythonVars(conf)::
153 local vars = ['%s = %s' % [k, std.manifestPython(conf[k])] for k in std.objectFields(conf)];
154 std.join('\n', vars + ['']),
155
156 manifestXmlJsonml(value)::
157 if !std.isArray(value) then
158 error 'Expected a JSONML value (an array), got %s' % std.type(value)
159 else
160 local aux(v) =
161 if std.isString(v) then
162 v
163 else
164 local tag = v[0];
165 local has_attrs = std.length(v) > 1 && std.isObject(v[1]);
166 local attrs = if has_attrs then v[1] else {};
167 local children = if has_attrs then v[2:] else v[1:];
168 local attrs_str =
169 std.join('', [' %s="%s"' % [k, attrs[k]] for k in std.objectFields(attrs)]);
170 std.deepJoin(['<', tag, attrs_str, '>', [aux(x) for x in children], '</', tag, '>']);
171
172 aux(value),
173
174 mergePatch(target, patch)::75 mergePatch(target, patch)::
175 if std.isObject(patch) then76 if std.isObject(patch) then
194 }95 }
195 else96 else
196 patch,97 patch,
197
198 get(o, f, default=null, inc_hidden=true)::
199 if std.objectHasEx(o, f, inc_hidden) then o[f] else default,
20098
201 resolvePath(f, r)::99 resolvePath(f, r)::
202 local arr = std.split(f, '/');100 local arr = std.split(f, '/');
modifiedcrates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth
27 str.replace(&from as &str, &to as &str)27 str.replace(&from as &str, &to as &str)
28}28}
29
30#[builtin]
31pub fn builtin_escape_string_bash(str: String) -> String {
32 const QUOTE: char = '\'';
33 let mut out = str.replace(QUOTE, "'\"'\"'");
34 out.insert(0, QUOTE);
35 out.push(QUOTE);
36 out
37}
38
39#[builtin]
40pub fn builtin_escape_string_dollars(str: String) -> String {
41 str.replace('$', "$$")
42}
2943
30#[builtin]44#[builtin]
31pub fn builtin_is_empty(str: String) -> bool {45pub fn builtin_is_empty(str: String) -> bool {
65 }79 }
66}80}
81
82#[builtin]
83pub fn builtin_split(str: IStr, c: IStr) -> ArrValue {
84 use Either2::*;
85 builtin_splitlimit(str, c, B(M1))
86}
6787
68#[builtin]88#[builtin]
69pub fn builtin_ascii_upper(str: IStr) -> String {89pub fn builtin_ascii_upper(str: IStr) -> String {