difftreelog
refactor remove ManifestFormat from state
in: master
7 files changed
cmds/jrsonnet/src/main.rsdiffbeforeafterboth93enum Error {93enum Error {94 // Handled differently94 // Handled differently95 #[error("evaluation error")]95 #[error("evaluation error")]96 Evaluation(jrsonnet_evaluator::error::LocError),96 Evaluation(LocError),97 #[error("io error")]97 #[error("io error")]98 Io(#[from] std::io::Error),98 Io(#[from] std::io::Error),99 #[error("input is not utf8 encoded")]99 #[error("input is not utf8 encoded")]106 Self::Evaluation(e)106 Self::Evaluation(e)107 }107 }108}108}109impl From<jrsonnet_evaluator::error::Error> for Error {110 fn from(e: jrsonnet_evaluator::error::Error) -> Self {111 Self::from(LocError::from(e))112 }113}109114110fn main_catch(opts: Opts) -> bool {115fn main_catch(opts: Opts) -> bool {111 let s = State::default();116 let s = State::default();144 dir.pop();149 dir.pop();145 create_dir_all(dir)?;150 create_dir_all(dir)?;146 }151 }152 let Val::Obj(obj) = val else {153 throw!("value should be object for --multi manifest, got {}", val.value_type())154 };147 for (file, data) in s.manifest_multi(val)?.iter() {155 for (field, data) in obj.iter(156 #[cfg(feature = "exp-preserve-order")]157 opts.manifest.preserve_order,158 ) {159 let data = data.with_description(|| format!("getting field {field} for manifest"))?;160148 let mut path = multi.clone();161 let mut path = multi.clone();149 path.push(file as &str);162 path.push(&field as &str);150 if opts.output.create_output_dirs {163 if opts.output.create_output_dirs {151 let mut dir = path.clone();164 let mut dir = path.clone();152 dir.pop();165 dir.pop();155 println!("{}", path.to_str().expect("path"));168 println!("{}", path.to_str().expect("path"));156 let mut file = File::create(path)?;169 let mut file = File::create(path)?;157 writeln!(file, "{}", data)?;170 writeln!(158 }171 file,172 "{}",173 data.manifest(&manifest_format)174 .with_description(|| format!("manifesting {field}"))?175 )?;176 }159 } else if let Some(path) = opts.output.output_file {177 } else if let Some(path) = opts.output.output_file {160 if opts.output.create_output_dirs {178 if opts.output.create_output_dirs {161 let mut dir = path.clone();179 let mut dir = path.clone();162 dir.pop();180 dir.pop();163 create_dir_all(dir)?;181 create_dir_all(dir)?;164 }182 }165 let mut file = File::create(path)?;183 let mut file = File::create(path)?;166 writeln!(file, "{}", s.manifest(val)?)?;184 writeln!(file, "{}", val.manifest(manifest_format)?)?;167 } else {185 } else {168 let output = s.manifest(val)?;186 let output = val.manifest(manifest_format)?;169 if !output.is_empty() {187 if !output.is_empty() {170 println!("{}", output);188 println!("{}", output);171 }189 }crates/jrsonnet-cli/src/manifest.rsdiffbeforeafterboth3use clap::{Parser, ValueEnum};3use clap::{Parser, ValueEnum};4use jrsonnet_evaluator::{error::Result, ManifestFormat, State};4use jrsonnet_evaluator::{5 error::Result,6 stdlib::manifest::{JsonFormat, StringFormat, ToStringFormat, YamlFormat, YamlStreamFormat},7 ManifestFormat, State,8};596use crate::ConfigureState;10use crate::ConfigureState;36 #[clap(long, short = 'S', conflicts_with = "format")]40 #[clap(long, short = 'S', conflicts_with = "format")]37 string: bool,41 string: bool,38 /// Write output as YAML stream, can be used with --format json/yaml42 /// Write output as YAML stream, can be used with --format json/yaml39 #[clap(long, short = 'y')]43 #[clap(long, short = 'y', conflicts_with = "string")]40 yaml_stream: bool,44 yaml_stream: bool,41 /// Number of spaces to pad output manifest with.45 /// Number of spaces to pad output manifest with.42 /// `0` for hard tabs, `-1` for single line output [default: 3 for json, 2 for yaml]46 /// `0` for hard tabs, `-1` for single line output [default: 3 for json, 2 for yaml]45 /// Preserve order in object manifestification49 /// Preserve order in object manifestification46 #[cfg(feature = "exp-preserve-order")]50 #[cfg(feature = "exp-preserve-order")]47 #[clap(long)]51 #[clap(long)]48 exp_preserve_order: bool,52 preserve_order: bool,49}53}50impl ConfigureState for ManifestOpts {54impl ConfigureState for ManifestOpts {51 type Guards = ();55 type Guards = Box<dyn ManifestFormat>;52 fn configure(&self, s: &State) -> Result<()> {56 fn configure(&self, _s: &State) -> Result<Self::Guards> {53 if self.string {57 let format: Box<dyn ManifestFormat> = if self.string {54 s.set_manifest_format(ManifestFormat::String);58 Box::new(StringFormat)55 } else {59 } else {56 #[cfg(feature = "exp-preserve-order")]60 #[cfg(feature = "exp-preserve-order")]57 let preserve_order = self.exp_preserve_order;61 let preserve_order = self.preserve_order;58 match self.format {62 match self.format {59 ManifestFormatName::String => s.set_manifest_format(ManifestFormat::String),63 ManifestFormatName::String => Box::new(ToStringFormat),60 ManifestFormatName::Json => s.set_manifest_format(ManifestFormat::Json {64 ManifestFormatName::Json => Box::new(JsonFormat::cli(61 padding: self.line_padding.unwrap_or(3),65 self.line_padding.unwrap_or(3),62 #[cfg(feature = "exp-preserve-order")]66 #[cfg(feature = "exp-preserve-order")]63 preserve_order,67 preserve_order,64 }),68 )),65 ManifestFormatName::Yaml => s.set_manifest_format(ManifestFormat::Yaml {69 ManifestFormatName::Yaml => Box::new(YamlFormat::cli(66 padding: self.line_padding.unwrap_or(2),70 self.line_padding.unwrap_or(2),67 #[cfg(feature = "exp-preserve-order")]71 #[cfg(feature = "exp-preserve-order")]68 preserve_order,72 preserve_order,69 }),73 )),70 }74 }71 }75 };72 if self.yaml_stream {76 Ok(if self.yaml_stream {73 s.set_manifest_format(ManifestFormat::YamlStream(Box::new(s.manifest_format())))77 Box::new(YamlStreamFormat(format))74 }78 } else {75 Ok(())79 format80 })76 }81 }77}82}7883crates/jrsonnet-cli/src/stdlib.rsdiffbeforeafterboth60pub struct StdOpts {60pub struct StdOpts {61 /// Disable standard library.61 /// Disable standard library.62 /// By default standard library will be available via global `std` variable.62 /// By default standard library will be available via global `std` variable.63 /// Note that standard library will still be loaded64 /// if chosen manifestification method is not `none`.65 #[clap(long)]63 #[clap(long)]66 no_stdlib: bool,64 no_stdlib: bool,67 /// Add string external variable.65 /// Add string external variable.crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth149 pub context_initializer: TraceBox<dyn ContextInitializer>,149 pub context_initializer: TraceBox<dyn ContextInitializer>,150 /// Used to resolve file locations/contents150 /// Used to resolve file locations/contents151 pub import_resolver: TraceBox<dyn ImportResolver>,151 pub import_resolver: TraceBox<dyn ImportResolver>,152 /// Used in manifestification functions153 pub manifest_format: ManifestFormat,154 /// Used for bindings155 pub trace_format: TraceBox<dyn TraceFormat>,156}152}157impl Default for EvaluationSettings {153impl Default for EvaluationSettings {158 fn default() -> Self {154 fn default() -> Self {449 Ref::map(self.settings(), |s| &*s.context_initializer)445 Ref::map(self.settings(), |s| &*s.context_initializer)450 }446 }451452 pub fn manifest_format(&self) -> ManifestFormat {453 self.settings().manifest_format.clone()454 }455 pub fn set_manifest_format(&self, format: ManifestFormat) {456 self.settings_mut().manifest_format = format;457 }458459 pub fn trace_format(&self) -> Ref<'_, dyn TraceFormat> {460 Ref::map(self.settings(), |s| &*s.trace_format)461 }462 pub fn set_trace_format(&self, format: impl TraceFormat) {463 self.settings_mut().trace_format = tb!(format);464 }465466 pub fn max_trace(&self) -> usize {467 self.settings().max_trace468 }469 pub fn set_max_trace(&self, trace: usize) {470 self.settings_mut().max_trace = trace;471 }472}447}473448crates/jrsonnet-evaluator/src/stdlib/manifest.rsdiffbeforeafterboth1use std::{borrow::Cow, fmt::Write};21use crate::{3use crate::{2 error::{Error::*, Result},4 error::{Error::*, Result},3 throw, State, Val,5 throw, ManifestFormat, State, Val,4};6};576#[derive(PartialEq, Eq, Clone, Copy)]8#[derive(PartialEq, Eq, Clone, Copy)]16 Minify,18 Minify,17}19}182019pub struct ManifestJsonOptions<'s> {21pub struct JsonFormat<'s> {20 pub padding: &'s str,22 padding: Cow<'s, str>,21 pub mtype: ManifestType,23 mtype: ManifestType,22 pub newline: &'s str,24 newline: &'s str,23 pub key_val_sep: &'s str,25 key_val_sep: &'s str,24 #[cfg(feature = "exp-preserve-order")]26 #[cfg(feature = "exp-preserve-order")]25 pub preserve_order: bool,27 preserve_order: bool,26}28}2930impl<'s> JsonFormat<'s> {31 // Minifying format32 pub fn minify(#[cfg(feature = "exp-preserve-order")] preserve_order: bool) -> Self {33 Self {34 padding: Cow::Borrowed(""),35 mtype: ManifestType::Minify,36 newline: "\n",37 key_val_sep: ":",38 #[cfg(feature = "exp-preserve-order")]39 preserve_order,40 }41 }42 // Same format as std.toString43 pub fn std_to_string() -> Self {44 Self {45 padding: Cow::Borrowed(""),46 mtype: ManifestType::ToString,47 newline: "\n",48 key_val_sep: ": ",49 #[cfg(feature = "exp-preserve-order")]50 preserve_order: false,51 }52 }53 pub fn std_to_json(54 padding: String,55 newline: &'s str,56 key_val_sep: &'s str,57 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,58 ) -> Self {59 Self {60 padding: Cow::Owned(padding),61 mtype: ManifestType::Std,62 newline,63 key_val_sep,64 #[cfg(feature = "exp-preserve-order")]65 preserve_order,66 }67 }68 // Same format as CLI manifestification69 pub fn cli(70 padding: usize,71 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,72 ) -> Self {73 if padding == 0 {74 return Self::minify(75 #[cfg(feature = "exp-preserve-order")]76 preserve_order,77 );78 }79 Self {80 padding: Cow::Owned(" ".repeat(padding)),81 mtype: ManifestType::Manifest,82 newline: "\n",83 key_val_sep: ": ",84 #[cfg(feature = "exp-preserve-order")]85 preserve_order,86 }87 }88}89impl Default for JsonFormat<'static> {90 fn default() -> Self {91 Self {92 padding: Cow::Borrowed(" "),93 mtype: ManifestType::Manifest,94 newline: "\n",95 key_val_sep: ": ",96 #[cfg(feature = "exp-preserve-order")]97 preserve_order: false,98 }99 }100}2710128pub fn manifest_json_ex(val: &Val, options: &ManifestJsonOptions<'_>) -> Result<String> {102pub fn manifest_json_ex(val: &Val, options: &JsonFormat<'_>) -> Result<String> {29 let mut out = String::new();103 let mut out = String::new();30 manifest_json_ex_buf(val, &mut out, &mut String::new(), options)?;104 manifest_json_ex_buf(val, &mut out, &mut String::new(), options)?;31 Ok(out)105 Ok(out)34 val: &Val,108 val: &Val,35 buf: &mut String,109 buf: &mut String,36 cur_padding: &mut String,110 cur_padding: &mut String,37 options: &ManifestJsonOptions<'_>,111 options: &JsonFormat<'_>,38) -> Result<()> {112) -> Result<()> {39 use std::fmt::Write;40 let mtype = options.mtype;113 let mtype = options.mtype;41 match val {114 match val {42 Val::Bool(v) => {115 Val::Bool(v) => {57 }130 }5813159 let old_len = cur_padding.len();132 let old_len = cur_padding.len();60 cur_padding.push_str(options.padding);133 cur_padding.push_str(&options.padding);61 for (i, item) in items.iter().enumerate() {134 for (i, item) in items.iter().enumerate() {62 if i != 0 {135 if i != 0 {63 buf.push(',');136 buf.push(',');97 }170 }9817199 let old_len = cur_padding.len();172 let old_len = cur_padding.len();100 cur_padding.push_str(options.padding);173 cur_padding.push_str(&options.padding);101 for (i, field) in fields.into_iter().enumerate() {174 for (i, field) in fields.into_iter().enumerate() {102 if i != 0 {175 if i != 0 {103 buf.push(',');176 buf.push(',');138 Ok(())211 Ok(())139}212}213214impl ManifestFormat for JsonFormat<'_> {215 fn manifest_buf(&self, val: Val, buf: &mut String) -> Result<()> {216 manifest_json_ex_buf(&val, buf, &mut String::new(), &self)217 }218}219220pub struct ToStringFormat;221impl ManifestFormat for ToStringFormat {222 fn manifest_buf(&self, val: Val, out: &mut String) -> Result<()> {223 JsonFormat::std_to_string().manifest_buf(val, out)224 }225}226pub struct StringFormat;227impl ManifestFormat for StringFormat {228 fn manifest_buf(&self, val: Val, out: &mut String) -> Result<()> {229 let Val::Str(s) = val else {230 throw!("output should be string for string manifest format, got {}", val.value_type())231 };232 out.write_str(&s).unwrap();233 Ok(())234 }235}236237pub struct YamlStreamFormat<I>(pub I);238impl<I: ManifestFormat> ManifestFormat for YamlStreamFormat<I> {239 fn manifest_buf(&self, val: Val, out: &mut String) -> Result<()> {240 let Val::Arr(arr) = val else {241 throw!("output should be array for yaml stream format, got {}", val.value_type())242 };243 if !arr.is_empty() {244 for v in arr.iter() {245 let v = v?;246 out.push_str("---\n");247 self.0.manifest_buf(v, out)?;248 out.push('\n');249 }250 out.push_str("...");251 }252 Ok(())253 }254}140255141pub fn escape_string_json(s: &str) -> String {256pub fn escape_string_json(s: &str) -> String {142 let mut buf = String::new();257 let mut buf = String::new();145}260}146261147fn escape_string_json_buf(s: &str, buf: &mut String) {262fn escape_string_json_buf(s: &str, buf: &mut String) {148 use std::fmt::Write;149 buf.push('"');263 buf.push('"');150 for c in s.chars() {264 for c in s.chars() {151 match c {265 match c {165 buf.push('"');279 buf.push('"');166}280}167281168pub struct ManifestYamlOptions<'s> {282pub struct YamlFormat<'s> {169 /// Padding before fields, i.e283 /// Padding before fields, i.e170 /// ```yaml284 /// ```yaml171 /// a:285 /// a:172 /// b:286 /// b:173 /// ## <- this287 /// ## <- this174 /// ```288 /// ```175 pub padding: &'s str,289 padding: Cow<'s, str>,176 /// Padding before array elements in objects290 /// Padding before array elements in objects177 /// ```yaml291 /// ```yaml178 /// a:292 /// a:179 /// - 1293 /// - 1180 /// ## <- this294 /// ## <- this181 /// ```295 /// ```182 pub arr_element_padding: &'s str,296 arr_element_padding: Cow<'s, str>,183 /// Should yaml keys appear unescaped, when possible297 /// Should yaml keys appear unescaped, when possible184 /// ```yaml298 /// ```yaml185 /// "safe_key": 1299 /// "safe_key": 1186 /// # vs300 /// # vs187 /// safe_key: 1301 /// safe_key: 1188 /// ```302 /// ```189 pub quote_keys: bool,303 quote_keys: bool,190 /// If true - then order of fields is preserved as written,304 /// If true - then order of fields is preserved as written,191 /// instead of sorting alphabetically305 /// instead of sorting alphabetically192 #[cfg(feature = "exp-preserve-order")]306 #[cfg(feature = "exp-preserve-order")]193 pub preserve_order: bool,307 preserve_order: bool,194}308}309impl YamlFormat<'_> {310 pub fn cli(311 padding: usize,312 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,313 ) -> Self {314 let padding = " ".repeat(padding);315 Self {316 padding: Cow::Owned(padding.clone()),317 arr_element_padding: Cow::Owned(padding),318 quote_keys: false,319 #[cfg(feature = "exp-preserve-order")]320 preserve_order,321 }322 }323 pub fn std_to_yaml(324 indent_array_in_object: bool,325 quote_keys: bool,326 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,327 ) -> Self {328 Self {329 padding: Cow::Borrowed(" "),330 arr_element_padding: Cow::Borrowed(if indent_array_in_object { " " } else { "" }),331 quote_keys,332 #[cfg(feature = "exp-preserve-order")]333 preserve_order,334 }335 }336}337impl ManifestFormat for YamlFormat<'_> {338 fn manifest_buf(&self, val: Val, buf: &mut String) -> Result<()> {339 manifest_yaml_ex_buf(&val, buf, &mut String::new(), self)340 }341}195342196/// From <https://github.com/chyh1990/yaml-rust/blob/da52a68615f2ecdd6b7e4567019f280c433c1521/src/emitter.rs#L289>343/// From <https://github.com/chyh1990/yaml-rust/blob/da52a68615f2ecdd6b7e4567019f280c433c1521/src/emitter.rs#L289>197/// With added date check344/// With added date check221 || string.parse::<f64>().is_ok()368 || string.parse::<f64>().is_ok()222}369}223370224pub fn manifest_yaml_ex(val: &Val, options: &ManifestYamlOptions<'_>) -> Result<String> {371pub fn manifest_yaml_ex(val: &Val, options: &YamlFormat<'_>) -> Result<String> {225 let mut out = String::new();372 let mut out = String::new();226 manifest_yaml_ex_buf(val, &mut out, &mut String::new(), options)?;373 manifest_yaml_ex_buf(val, &mut out, &mut String::new(), options)?;227 Ok(out)374 Ok(out)232 val: &Val,379 val: &Val,233 buf: &mut String,380 buf: &mut String,234 cur_padding: &mut String,381 cur_padding: &mut String,235 options: &ManifestYamlOptions<'_>,382 options: &YamlFormat<'_>,236) -> Result<()> {383) -> Result<()> {237 use std::fmt::Write;238 match val {384 match val {239 Val::Bool(v) => {385 Val::Bool(v) => {240 if *v {386 if *v {252 for line in s.split('\n') {398 for line in s.split('\n') {253 buf.push('\n');399 buf.push('\n');254 buf.push_str(cur_padding);400 buf.push_str(cur_padding);255 buf.push_str(options.padding);401 buf.push_str(&options.padding);256 buf.push_str(line);402 buf.push_str(line);257 }403 }258 } else if !options.quote_keys && !yaml_needs_quotes(s) {404 } else if !options.quote_keys && !yaml_needs_quotes(s) {277 Val::Arr(a) if !a.is_empty() => {423 Val::Arr(a) if !a.is_empty() => {278 buf.push('\n');424 buf.push('\n');279 buf.push_str(cur_padding);425 buf.push_str(cur_padding);280 buf.push_str(options.padding);426 buf.push_str(&options.padding);281 }427 }282 _ => buf.push(' '),428 _ => buf.push(' '),283 }429 }288 };434 };289 let prev_len = cur_padding.len();435 let prev_len = cur_padding.len();290 if extra_padding {436 if extra_padding {291 cur_padding.push_str(options.padding);437 cur_padding.push_str(&options.padding);292 }438 }293 manifest_yaml_ex_buf(&item, buf, cur_padding, options)?;439 manifest_yaml_ex_buf(&item, buf, cur_padding, options)?;294 cur_padding.truncate(prev_len);440 cur_padding.truncate(prev_len);323 Val::Arr(a) if !a.is_empty() => {469 Val::Arr(a) if !a.is_empty() => {324 buf.push('\n');470 buf.push('\n');325 buf.push_str(cur_padding);471 buf.push_str(cur_padding);326 buf.push_str(options.arr_element_padding);472 buf.push_str(&options.arr_element_padding);327 cur_padding.push_str(options.arr_element_padding);473 cur_padding.push_str(&options.arr_element_padding);328 }474 }329 Val::Obj(o) if !o.is_empty() => {475 Val::Obj(o) if !o.is_empty() => {330 buf.push('\n');476 buf.push('\n');331 buf.push_str(cur_padding);477 buf.push_str(cur_padding);332 buf.push_str(options.padding);478 buf.push_str(&options.padding);333 cur_padding.push_str(options.padding);479 cur_padding.push_str(&options.padding);334 }480 }335 _ => buf.push(' '),481 _ => buf.push(' '),336 }482 }crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth1use std::{cell::RefCell, fmt::Debug, rc::Rc};1use std::{cell::RefCell, fmt::Debug};223use jrsonnet_gcmodule::{Cc, Trace};3use jrsonnet_gcmodule::{Cc, Trace};4use jrsonnet_interner::{IBytes, IStr};4use jrsonnet_interner::{IBytes, IStr};8 error::{Error::*, LocError},8 error::{Error::*, LocError},9 function::FuncVal,9 function::FuncVal,10 gc::{GcHashMap, TraceBox},10 gc::{GcHashMap, TraceBox},11 stdlib::manifest::{12 manifest_json_ex, manifest_yaml_ex, ManifestJsonOptions, ManifestType, ManifestYamlOptions,13 },14 throw,11 throw,15 typed::BoundedUsize,12 typed::BoundedUsize,16 ObjValue, Result, Unbound, WeakObjValue,13 ObjValue, Result, Unbound, WeakObjValue,122 }119 }123}120}124121125#[derive(Clone, Trace)]126pub enum ManifestFormat {122pub trait ManifestFormat {127 YamlStream(Box<ManifestFormat>),128 Yaml {129 padding: usize,123 fn manifest_buf(&self, val: Val, buf: &mut String) -> Result<()>;130 #[cfg(feature = "exp-preserve-order")]131 preserve_order: bool,132 },133 Json {134 padding: usize,124 fn manifest(&self, val: Val) -> Result<String> {135 #[cfg(feature = "exp-preserve-order")]125 let mut out = String::new();136 preserve_order: bool,126 self.manifest_buf(val, &mut out)?;137 },127 Ok(out)138 ToString,128 }139 String,140}129}130impl<T> ManifestFormat for Box<T>131where132 T: ManifestFormat + ?Sized,133{134 fn manifest_buf(&self, val: Val, buf: &mut String) -> Result<()> {135 let inner = &**self;136 inner.manifest_buf(val, buf)137 }138}141impl ManifestFormat {139impl<T> ManifestFormat for &'_ T142 #[cfg(feature = "exp-preserve-order")]140where141 T: ManifestFormat + ?Sized,142{143 fn preserve_order(&self) -> bool {143 fn manifest_buf(&self, val: Val, buf: &mut String) -> Result<()> {144 match self {145 ManifestFormat::YamlStream(s) => s.preserve_order(),146 ManifestFormat::Yaml { preserve_order, .. } => *preserve_order,147 ManifestFormat::Json { preserve_order, .. } => *preserve_order,144 let inner = &**self;148 ManifestFormat::ToString => false,149 ManifestFormat::String => false,145 inner.manifest_buf(val, buf)150 }146 }151 }152}147}153148154#[derive(Debug, Clone, Trace)]149#[derive(Debug, Clone, Trace)]641 }636 }642 }637 }643638644 pub fn to_string(&self) -> Result<IStr> {639 pub fn manifest(&self, format: impl ManifestFormat) -> Result<String> {645 Ok(match self {646 Self::Bool(true) => "true".into(),647 Self::Bool(false) => "false".into(),648 Self::Null => "null".into(),649 Self::Str(s) => s.clone(),650 v => manifest_json_ex(651 v,652 &ManifestJsonOptions {653 padding: "",654 mtype: ManifestType::ToString,655 newline: "\n",656 key_val_sep: ": ",657 #[cfg(feature = "exp-preserve-order")]658 preserve_order: false,659 },660 )?661 .into(),662 })663 }664665 /// Expects value to be object, outputs (key, manifested value) pairs666 pub fn manifest_multi(&self, ty: &ManifestFormat) -> Result<Vec<(IStr, IStr)>> {640 fn manifest_dyn(val: &Val, manifest: &dyn ManifestFormat) -> Result<String> {667 let Self::Obj(obj) = self else {668 throw!(MultiManifestOutputIsNotAObject);669 };670 let keys = obj.fields(671 #[cfg(feature = "exp-preserve-order")]672 ty.preserve_order(),673 );674 let mut out = Vec::with_capacity(keys.len());675 for key in keys {676 let value = obj677 .get(key.clone())?641 manifest.manifest(val.clone())678 .expect("item in object")679 .manifest(ty)?;680 out.push((key, value));681 }682 Ok(out)683 }642 }684685 /// Expects value to be array, outputs manifested values686 pub fn manifest_stream(&self, ty: &ManifestFormat) -> Result<Vec<IStr>> {643 manifest_dyn(self, &format)687 let Self::Arr(arr) = self else {644 }688 throw!(StreamManifestOutputIsNotAArray);689 };690 let mut out = Vec::with_capacity(arr.len());691 for i in arr.iter() {692 out.push(i?.manifest(ty)?);693 }694 Ok(out)695 }696645697 pub fn manifest(&self, ty: &ManifestFormat) -> Result<IStr> {646 pub fn to_string(&self) -> Result<IStr> {698 Ok(match ty {647 Ok(match self {699 ManifestFormat::YamlStream(format) => {700 let Self::Arr(arr) = self else {648 Self::Bool(true) => "true".into(),701 throw!(StreamManifestOutputIsNotAArray)702 };703 let mut out = String::new();704705 match format as &ManifestFormat {706 ManifestFormat::YamlStream(_) => throw!(StreamManifestOutputCannotBeRecursed),707 ManifestFormat::String => throw!(StreamManifestCannotNestString),708 _ => {}709 };710711 if !arr.is_empty() {712 for v in arr.iter() {713 out.push_str("---\n");714 out.push_str(&v?.manifest(format)?);715 out.push('\n');716 }717 out.push_str("...");718 }719720 out.into()721 }722 ManifestFormat::Yaml {649 Self::Bool(false) => "false".into(),723 padding,724 #[cfg(feature = "exp-preserve-order")]725 preserve_order,726 } => self.to_yaml(727 *padding,728 #[cfg(feature = "exp-preserve-order")]729 *preserve_order,730 )?,731 ManifestFormat::Json {732 padding,733 #[cfg(feature = "exp-preserve-order")]734 preserve_order,735 } => self.to_json(736 *padding,737 #[cfg(feature = "exp-preserve-order")]738 *preserve_order,739 )?,740 ManifestFormat::ToString => self.to_string()?,650 Self::Null => "null".into(),741 ManifestFormat::String => match self {742 Self::Str(s) => s.clone(),651 Self::Str(s) => s.clone(),743 _ => throw!(StringManifestOutputIsNotAString),652 _ => self744 },653 .manifest(crate::stdlib::manifest::ToStringFormat)654 .map(IStr::from)?,745 })655 })746 }656 }747657748 /// For manifestification749 pub fn to_json(750 &self,751 padding: usize,752 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,753 ) -> Result<IStr> {754 manifest_json_ex(755 self,756 &ManifestJsonOptions {757 padding: &" ".repeat(padding),758 mtype: if padding == 0 {759 ManifestType::Minify760 } else {761 ManifestType::Manifest762 },763 newline: "\n",764 key_val_sep: ": ",765 #[cfg(feature = "exp-preserve-order")]766 preserve_order,767 },768 )769 .map(Into::into)770 }771772 /// Calls `std.manifestJson`773 pub fn to_std_json(774 &self,775 padding: usize,776 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,777 ) -> Result<Rc<str>> {778 manifest_json_ex(779 self,780 &ManifestJsonOptions {781 padding: &" ".repeat(padding),782 mtype: ManifestType::Std,783 newline: "\n",784 key_val_sep: ": ",785 #[cfg(feature = "exp-preserve-order")]786 preserve_order,787 },788 )789 .map(Into::into)790 }791792 pub fn to_yaml(793 &self,794 padding: usize,795 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,796 ) -> Result<IStr> {797 let padding = &" ".repeat(padding);798 manifest_yaml_ex(799 self,800 &ManifestYamlOptions {801 padding,802 arr_element_padding: padding,803 quote_keys: false,804 #[cfg(feature = "exp-preserve-order")]805 preserve_order,806 },807 )808 .map(Into::into)809 }810 pub fn into_indexable(self) -> Result<IndexableVal> {658 pub fn into_indexable(self) -> Result<IndexableVal> {811 Ok(match self {659 Ok(match self {812 Val::Str(s) => IndexableVal::Str(s),660 Val::Str(s) => IndexableVal::Str(s),crates/jrsonnet-stdlib/src/manifest.rsdiffbeforeafterboth1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{2 error::Result,2 error::Result,3 function::builtin,3 function::builtin,4 stdlib::manifest::{4 stdlib::manifest::{escape_string_json, JsonFormat, YamlFormat},5 escape_string_json, manifest_json_ex, manifest_yaml_ex, ManifestJsonOptions, ManifestType,6 ManifestYamlOptions,7 },8 typed::Any,5 typed::Any,9 IStr,6 IStr,24) -> Result<String> {21) -> Result<String> {25 let newline = newline.as_deref().unwrap_or("\n");22 let newline = newline.as_deref().unwrap_or("\n");26 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");23 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");27 manifest_json_ex(28 &value.0,24 value.0.manifest(JsonFormat::std_to_json(29 &ManifestJsonOptions {30 padding: &indent,25 indent.to_string(),31 mtype: ManifestType::Std,32 newline,26 newline,33 key_val_sep,27 key_val_sep,34 #[cfg(feature = "exp-preserve-order")]28 #[cfg(feature = "exp-preserve-order")]35 preserve_order: preserve_order.unwrap_or(false),29 preserve_order.unwrap_or(false),36 },30 ))37 )38}31}393240#[builtin]33#[builtin]44 quote_keys: Option<bool>,37 quote_keys: Option<bool>,45 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,38 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,46) -> Result<String> {39) -> Result<String> {47 manifest_yaml_ex(48 &value.0,40 value.0.manifest(YamlFormat::std_to_yaml(49 &ManifestYamlOptions {50 padding: " ",51 arr_element_padding: if indent_array_in_object.unwrap_or(false) {41 indent_array_in_object.unwrap_or(false),52 " "53 } else {54 ""55 },56 quote_keys: quote_keys.unwrap_or(true),42 quote_keys.unwrap_or(true),57 #[cfg(feature = "exp-preserve-order")]43 #[cfg(feature = "exp-preserve-order")]58 preserve_order: preserve_order.unwrap_or(false),44 preserve_order.unwrap_or(false),59 },45 ))60 )61}46}6247