difftreelog
refactor move more stdlib functions to builtins
in: master
16 files changed
crates/jrsonnet-cli/src/manifest.rsdiffbeforeafterboth4use 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};889#[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}171818#[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 format79 }81 }crates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth1use std::any::Any;1use std::{2 any::Any,3 num::{NonZeroU32, NonZeroUsize},4};253use 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 }101104105 /// # Panics106 /// If step == 0102 #[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"));113117114 if from >= to || step == 0 {118 if index >= end {115 return None;119 return Self::empty();116 }120 }117121118 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 }125129126 /// Array length.130 /// Array length.crates/jrsonnet-evaluator/src/manifest.rsdiffbeforeafterboth340 }340 }341}341}342342343pub 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 end354 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}crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth2 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};78277 .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);289290 if index >= end {291 return Ok(Self::Arr(ArrValue::empty()));292 }293294 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}crates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth343435 Ok(Some(attr))35 Ok(Some(attr))36}36}37fn remove_attr<I>(attrs: &mut Vec<Attribute>, ident: I)38where39 Ident: PartialEq<I>,40{41 attrs.retain(|a| !a.path().is_ident(&ident));42}374338fn 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}129130enum Optionality {131 Required,132 Optional,133 Default(Expr),134}135impl Optionality {136 fn is_optional(&self) -> bool {137 !matches!(self, Self::Required)138 }139}123140124enum 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}139156140impl 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 }165182166 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 }173193174 (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 };178198179 let cfg_attrs = arg199 let cfg_attrs = arg185205186 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);203223204 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}209229210#[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 = fun225 .sig241 .sig226 .inputs242 .inputs227 .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<_>>>()?;230246231 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 = name239 .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 #eval303 },},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 None287 },}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 #eval311 } else {312 let v: #ty = #expr;313 v292 },}314 },},293 };315 };294 quote! {316 quote! {295 #(#cfg_attrs)*317 #(#cfg_attrs)*296 #value318 #value343 };365 };344366345 Ok(quote! {367 Ok(quote! {346 #item368 #fun347369348 #[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 PARAMS375 }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)?;379401crates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth265}265}266266267#[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);271271272 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}277274278#[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> {crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth102 ("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 // Manifest165 ("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 // Parse171 ("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 // Strings174 ("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 // Misc192 ("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 // Setscrates/jrsonnet-stdlib/src/manifest/mod.rsdiffbeforeafterboth1mod python;1mod toml;2mod toml;3mod xml;2mod yaml;4mod yaml;354use 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;111512#[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>,2728 #[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}4243#[builtin]44pub fn builtin_manifest_json(45 value: Val,4647 #[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}6061#[builtin]62pub fn builtin_manifest_json_minified(63 value: Val,6465 #[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}357436#[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,8081 #[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}9293#[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,99100 #[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}5011451#[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,119120 #[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}130131#[builtin]132pub fn builtin_manifest_toml(133 value: ObjValue,134135 #[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}6314664#[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}151152#[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}160161#[builtin]162pub fn builtin_escape_string_xml(str_: String) -> String {163 xml::escape_string_xml(str_.as_str())164}165166#[builtin]167pub fn builtin_manifest_xml_jsonml(value: Val) -> Result<String> {168 value.manifest(XmlJsonmlFormat::std_to_xml())169}68170crates/jrsonnet-stdlib/src/manifest/python.rsdiffbeforeafterbothno changes
crates/jrsonnet-stdlib/src/manifest/xml.rsdiffbeforeafterbothno changes
crates/jrsonnet-stdlib/src/math.rsdiffbeforeafterboth24 a.min(b)24 a.min(b)25}25}2627#[allow(non_snake_case)]28#[builtin]29pub fn builtin_clamp(x: f64, minVal: f64, maxVal: f64) -> f64 {30 x.clamp(minVal, maxVal)31}263227#[builtin]33#[builtin]28pub fn builtin_sum(arr: Vec<f64>) -> f64 {34pub fn builtin_sum(arr: Vec<f64>) -> f64 {crates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth23 }23 }24}24}2526#[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 fields41 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}254926#[builtin(fields(50#[builtin(fields(27 settings: Rc<RefCell<Settings>>,51 settings: Rc<RefCell<Settings>>,crates/jrsonnet-stdlib/src/objects.rsdiffbeforeafterboth9 obj: ObjValue,9 obj: ObjValue,10 hidden: bool,10 hidden: bool,1112 #[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,2728 #[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,4344 #[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,5952 #[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,7172 #[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,8687 #[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,113114 #[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,128129 #[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(160144 // Standard implementation uses std.objectFields without such argument, we can't161 // Standard implementation uses std.objectFields without such argument, we can't145 // assume order preservation should always be enabled/disabled162 // assume order preservation should always be enabled/disabled163 #[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")]crates/jrsonnet-stdlib/src/sort.rsdiffbeforeafterboth139}139}140140141#[builtin]141#[builtin]142pub fn builtin_sort(arr: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {142pub fn builtin_sort(143 arr: ArrValue,144145 #[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}145149146fn uniq_identity(arr: Vec<Val>) -> Result<Vec<Val>> {150fn uniq_identity(arr: Vec<Val>) -> Result<Vec<Val>> {174178175#[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,183184 #[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>>>()?,190197191#[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,202203 #[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)?;crates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth1{1{2 local std = self,2 local std = self,3 local id = std.id,435 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',6520 stripChars(str, chars)::19 stripChars(str, chars)::21 std.lstripChars(std.rstripChars(str, chars), chars),20 std.lstripChars(std.rstripChars(str, chars), chars),222123 split(str, c):: std.splitLimit(str, c, -1),2425 mapWithIndex(func, arr)::22 mapWithIndex(func, arr)::26 if !std.isFunction(func) then23 if !std.isFunction(func) then27 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 else56 error 'Assertion failed. ' + a + ' != ' + b,53 error 'Assertion failed. ' + a + ' != ' + b,575458 clamp(x, minVal, maxVal)::59 if x < minVal then minVal60 else if x > maxVal then maxVal61 else x,6263 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) + ['']),827483 manifestToml(value):: std.manifestTomlEx(value, ' '),8485 escapeStringPython(str)::86 std.escapeStringJson(str),8788 escapeStringBash(str_)::89 local str = std.toString(str_);90 local trans(ch) =91 if ch == "'" then92 "'\"'\"'"93 else94 ch;95 "'%s'" % std.join('', [trans(ch) for ch in std.stringChars(str)]),9697 escapeStringDollars(str_)::98 local str = std.toString(str_);99 local trans(ch) =100 if ch == '$' then101 '$$'102 else103 ch;104 std.foldl(function(a, b) a + trans(b), std.stringChars(str), ''),105106 local xml_escapes = {107 '<': '<',108 '>': '>',109 '&': '&',110 '"': '"',111 "'": ''',112 },113114 escapeStringXML(str_)::115 local str = std.toString(str_);116 std.join('', [std.get(xml_escapes, ch, ch) for ch in std.stringChars(str)]),117118 manifestJson(value):: std.manifestJsonEx(value, ' ') tailstrict,119120 manifestJsonMinified(value):: std.manifestJsonEx(value, '', '', ':'),121122 manifestYamlStream(value, indent_array_in_object=false, c_document_end=true, quote_keys=true)::123 if !std.isArray(value) then124 error 'manifestYamlStream only takes arrays, got ' + std.type(value)125 else126 '---\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',129130 manifestPython(v)::131 if std.isObject(v) then132 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) then138 '[%s]' % [std.join(', ', [std.manifestPython(v2) for v2 in v])]139 else if std.isString(v) then140 '%s' % [std.escapeStringPython(v)]141 else if std.isFunction(v) then142 error 'cannot manifest function'143 else if std.isNumber(v) then144 std.toString(v)145 else if v == true then146 'True'147 else if v == false then148 'False'149 else if v == null then150 'None',151152 manifestPythonVars(conf)::153 local vars = ['%s = %s' % [k, std.manifestPython(conf[k])] for k in std.objectFields(conf)];154 std.join('\n', vars + ['']),155156 manifestXmlJsonml(value)::157 if !std.isArray(value) then158 error 'Expected a JSONML value (an array), got %s' % std.type(value)159 else160 local aux(v) =161 if std.isString(v) then162 v163 else164 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, '>']);171172 aux(value),173174 mergePatch(target, patch)::75 mergePatch(target, patch)::175 if std.isObject(patch) then76 if std.isObject(patch) then194 }95 }195 else96 else196 patch,97 patch,197198 get(o, f, default=null, inc_hidden=true)::199 if std.objectHasEx(o, f, inc_hidden) then o[f] else default,20098201 resolvePath(f, r)::99 resolvePath(f, r)::202 local arr = std.split(f, '/');100 local arr = std.split(f, '/');crates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth27 str.replace(&from as &str, &to as &str)27 str.replace(&from as &str, &to as &str)28}28}2930#[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 out37}3839#[builtin]40pub fn builtin_escape_string_dollars(str: String) -> String {41 str.replace('$', "$$")42}294330#[builtin]44#[builtin]31pub fn builtin_is_empty(str: String) -> bool {45pub fn builtin_is_empty(str: String) -> bool {65 }79 }66}80}8182#[builtin]83pub fn builtin_split(str: IStr, c: IStr) -> ArrValue {84 use Either2::*;85 builtin_splitlimit(str, c, B(M1))86}678768#[builtin]88#[builtin]69pub fn builtin_ascii_upper(str: IStr) -> String {89pub fn builtin_ascii_upper(str: IStr) -> String {