difftreelog
style fix clippy warnings
in: master
20 files changed
bindings/jsonnet/src/lib.rsdiffbeforeafterboth707071/// Creates a new Jsonnet virtual machine.71/// Creates a new Jsonnet virtual machine.72#[no_mangle]72#[no_mangle]73#[allow(clippy::box_default)]73pub extern "C" fn jsonnet_make() -> *mut State {74pub extern "C" fn jsonnet_make() -> *mut State {74 let state = State::default();75 let state = State::default();75 state.settings_mut().import_resolver = Box::new(FileImportResolver::default());76 state.settings_mut().import_resolver = Box::new(FileImportResolver::default());crates/jrsonnet-cli/src/stdlib.rsdiffbeforeafterboth44 if out.len() != 2 {44 if out.len() != 2 {45 return Err("bad ext-file syntax".to_owned());45 return Err("bad ext-file syntax".to_owned());46 }46 }47 let file = read_to_string(&out[1]);47 let file = read_to_string(out[1]);48 match file {48 match file {49 Ok(content) => Ok(Self {49 Ok(content) => Ok(Self {50 name: out[0].into(),50 name: out[0].into(),crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth100 #[error("duplicate local var: {0}")]100 #[error("duplicate local var: {0}")]101 DuplicateLocalVar(IStr),101 DuplicateLocalVar(IStr),102102103 #[error("type mismatch: expected {}, got {2} {0}", .1.iter().map(|e| format!("{}", e)).collect::<Vec<_>>().join(", "))]103 #[error("type mismatch: expected {}, got {2} {0}", .1.iter().map(|e| format!("{e}")).collect::<Vec<_>>().join(", "))]104 TypeMismatch(&'static str, Vec<ValType>, ValType),104 TypeMismatch(&'static str, Vec<ValType>, ValType),105 #[error("no such field: {}{}", format_empty_str(.0), format_found(.1, "field"))]105 #[error("no such field: {}{}", format_empty_str(.0), format_found(.1, "field"))]106 NoSuchField(IStr, Vec<IStr>),106 NoSuchField(IStr, Vec<IStr>),113 BindingParameterASecondTime(IStr),113 BindingParameterASecondTime(IStr),114 #[error("too many args, function has {0}{}", format_signature(.1))]114 #[error("too many args, function has {0}{}", format_signature(.1))]115 TooManyArgsFunctionHas(usize, FunctionSignature),115 TooManyArgsFunctionHas(usize, FunctionSignature),116 #[error("function argument is not passed: {}{}", .0.as_ref().map(|n| n.as_str()).unwrap_or("<unnamed>"), format_signature(.1))]116 #[error("function argument is not passed: {}{}", .0.as_ref().map_or("<unnamed>", IStr::as_str), format_signature(.1))]117 FunctionParameterNotBoundInCall(Option<IStr>, FunctionSignature),117 FunctionParameterNotBoundInCall(Option<IStr>, FunctionSignature),118118119 #[error("external variable is not defined: {0}")]119 #[error("external variable is not defined: {0}")]249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {250 writeln!(f, "{}", self.0 .0)?;250 writeln!(f, "{}", self.0 .0)?;251 for el in &self.0 .1 .0 {251 for el in &self.0 .1 .0 {252 writeln!(f, "\t{:?}", el)?;252 writeln!(f, "\t{el:?}")?;253 }253 }254 Ok(())254 Ok(())255 }255 }crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth436 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(s, ctx, v)?)?,436 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(s, ctx, v)?)?,437 Var(name) => s.push(437 Var(name) => s.push(438 CallLocation::new(loc),438 CallLocation::new(loc),439 || format!("variable <{}> access", name),439 || format!("variable <{name}> access"),440 || ctx.binding(name.clone())?.evaluate(s.clone()),440 || ctx.binding(name.clone())?.evaluate(s.clone()),441 )?,441 )?,442 Index(value, index) => {442 Index(value, index) => {446 ) {446 ) {447 (Val::Obj(v), Val::Str(key)) => s.push(447 (Val::Obj(v), Val::Str(key)) => s.push(448 CallLocation::new(loc),448 CallLocation::new(loc),449 || format!("field <{}> access", key),449 || format!("field <{key}> access"),450 || match v.get(s.clone(), key.clone()) {450 || match v.get(s.clone(), key.clone()) {451 Ok(Some(v)) => Ok(v),451 Ok(Some(v)) => Ok(v),452 #[cfg(not(feature = "friendly-errors"))]452 #[cfg(not(feature = "friendly-errors"))]611 if let Some(value) = expr {611 if let Some(value) = expr {612 Ok(Some(s.push(612 Ok(Some(s.push(613 loc,613 loc,614 || format!("slice {}", desc),614 || format!("slice {desc}"),615 || T::from_untyped(evaluate(s.clone(), ctx.clone(), value)?, s.clone()),615 || T::from_untyped(evaluate(s.clone(), ctx.clone(), value)?, s.clone()),616 )?))616 )?))617 } else {617 } else {crates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth30 (Str(a), Num(b)) => Str(format!("{a}{b}").into()),30 (Str(a), Num(b)) => Str(format!("{a}{b}").into()),313132 (Str(a), o) | (o, Str(a)) if a.is_empty() => Val::Str(o.clone().to_string(s)?),32 (Str(a), o) | (o, Str(a)) if a.is_empty() => Val::Str(o.clone().to_string(s)?),33 (Str(a), o) => Str(format!("{}{}", a, o.clone().to_string(s)?).into()),33 (Str(a), o) => Str(format!("{a}{}", o.clone().to_string(s)?).into()),34 (o, Str(a)) => Str(format!("{}{}", o.clone().to_string(s)?, a).into()),34 (o, Str(a)) => Str(format!("{}{a}", o.clone().to_string(s)?).into()),353536 (Obj(v1), Obj(v2)) => Obj(v2.extend_from(v1.clone())),36 (Obj(v1), Obj(v2)) => Obj(v2.extend_from(v1.clone())),37 (Arr(a), Arr(b)) => {37 (Arr(a), Arr(b)) => {crates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth108 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,108 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,109 ) -> Result<()> {109 ) -> Result<()> {110 for (idx, el) in self.iter().enumerate() {110 for (idx, el) in self.iter().enumerate() {111 handler(idx, Thunk::evaluated(el.clone()))?111 handler(idx, Thunk::evaluated(el.clone()))?;112 }112 }113 Ok(())113 Ok(())114 }114 }crates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth179 // FIXME: O(n) for arg existence check179 // FIXME: O(n) for arg existence check180 let id = params180 let id = params181 .iter()181 .iter()182 .position(|p| {182 .position(|p| p.name.as_ref().map_or(false, |v| v as &str == name as &str))183 p.name184 .as_ref()185 .map(|v| &v as &str == name as &str)186 .unwrap_or(false)187 })188 .ok_or_else(|| UnknownFunctionParameter((name as &str).to_owned()))?;183 .ok_or_else(|| UnknownFunctionParameter((name as &str).to_owned()))?;189 if replace(&mut passed_args[id], Some(arg)).is_some() {184 if replace(&mut passed_args[id], Some(arg)).is_some() {190 throw!(BindingParameterASecondTime(name.clone()));185 throw!(BindingParameterASecondTime(name.clone()));209 if param204 if param210 .name205 .name211 .as_ref()206 .as_ref()212 .map(|v| &v as &str == name as &str)207 .map_or(false, |v| v as &str == name as &str)213 .unwrap_or(false)214 {208 {215 found = true;209 found = true;216 }210 }crates/jrsonnet-evaluator/src/import.rsdiffbeforeafterboth125 Ok(SourcePath::new(SourceFile::new(125 Ok(SourcePath::new(SourceFile::new(126 path.canonicalize()126 path.canonicalize().map_err(|e| ImportIo(e.to_string()))?,127 .map_err(|e| ImportIo(e.to_string()))?128 .to_owned(),129 )))127 )))130 } else if meta.is_dir() {128 } else if meta.is_dir() {131 Ok(SourcePath::new(SourceDirectory::new(129 Ok(SourcePath::new(SourceDirectory::new(132 path.canonicalize()130 path.canonicalize().map_err(|e| ImportIo(e.to_string()))?,133 .map_err(|e| ImportIo(e.to_string()))?134 .to_owned(),135 )))131 )))136 } else {132 } else {137 unreachable!("this can't be a symlink")133 unreachable!("this can't be a symlink")crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth16 Self::Null => Val::Null,16 Self::Null => Val::Null,17 Self::Bool(v) => Val::Bool(v),17 Self::Bool(v) => Val::Bool(v),18 Self::Number(n) => Val::Num(n.as_f64().ok_or_else(|| {18 Self::Number(n) => Val::Num(n.as_f64().ok_or_else(|| {19 RuntimeError(format!("json number can't be represented as jsonnet: {}", n).into())19 RuntimeError(format!("json number can't be represented as jsonnet: {n}").into())20 })?),20 })?),21 Self::String(s) => Val::Str((&s as &str).into()),21 Self::String(s) => Val::Str((&s as &str).into()),22 Self::Array(a) => {22 Self::Array(a) => {crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth594 .insert(name, TlaArg::String(value));594 .insert(name, TlaArg::String(value));595 }595 }596 pub fn add_tla_code(&self, name: IStr, code: &str) -> Result<()> {596 pub fn add_tla_code(&self, name: IStr, code: &str) -> Result<()> {597 let source_name = format!("<top-level-arg:{}>", name);597 let source_name = format!("<top-level-arg:{name}>");598 let source = Source::new_virtual(source_name.into(), code.into());598 let source = Source::new_virtual(source_name.into(), code.into());599 let parsed = jrsonnet_parser::parse(599 let parsed = jrsonnet_parser::parse(600 code,600 code,crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth156 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {156 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {157 if let Some(super_obj) = self.0.sup.as_ref() {157 if let Some(super_obj) = self.0.sup.as_ref() {158 if f.alternate() {158 if f.alternate() {159 write!(f, "{:#?}", super_obj)?;159 write!(f, "{super_obj:#?}")?;160 } else {160 } else {161 write!(f, "{:?}", super_obj)?;161 write!(f, "{super_obj:?}")?;162 }162 }163 write!(f, " + ")?;163 write!(f, " + ")?;164 }164 }395 })?;395 })?;396 self.0.value_cache.borrow_mut().insert(396 self.0.value_cache.borrow_mut().insert(397 key,397 key,398 match &value {398 value399 .as_ref()399 Some(v) => CacheValue::Cached(v.clone()),400 .map_or(CacheValue::NotFound, |v| CacheValue::Cached(v.clone())),400 None => CacheValue::NotFound,401 },402 );401 );403 Ok(value)402 Ok(value)404 }403 }crates/jrsonnet-evaluator/src/stdlib/format.rsdiffbeforeafterboth45 let mut i = 1;45 let mut i = 1;46 while i < bytes.len() {46 while i < bytes.len() {47 if bytes[i] == b')' {47 if bytes[i] == b')' {48 return Ok((&str[1..i as usize], &str[i as usize + 1..]));48 return Ok((&str[1..i], &str[i + 1..]));49 }49 }50 i += 1;50 i += 1;51 }51 }310 nums310 nums311 };311 };312 let neg = iv < 0.0;312 let neg = iv < 0.0;313 #[allow(clippy::bool_to_int_with_if)]313 let zp = padding.saturating_sub(if neg || blank || sign { 1 } else { 0 });314 let zp = padding.saturating_sub(if neg || blank || sign { 1 } else { 0 });314 let zp2 = zp315 let zp2 = zp315 .max(precision)316 .max(precision)406 ensure_pt: bool,407 ensure_pt: bool,407 trailing: bool,408 trailing: bool,408) {409) {410 #[allow(clippy::bool_to_int_with_if)]409 let dot_size = if precision == 0 && !ensure_pt { 0 } else { 1 };411 let dot_size = if precision == 0 && !ensure_pt { 0 } else { 1 };410 padding = padding.saturating_sub(dot_size + precision);412 padding = padding.saturating_sub(dot_size + precision);411 render_decimal(out, n.floor(), padding, 0, blank, sign);413 render_decimal(out, n.floor(), padding, 0, blank, sign);478 precision: Option<usize>,480 precision: Option<usize>,479) -> Result<()> {481) -> Result<()> {480 let clfags = &code.cflags;482 let clfags = &code.cflags;481 let (fpprec, iprec) = match precision {483 let (fpprec, iprec) = precision.map_or((6, 0), |v| (v, v));482 Some(v) => (v, v),483 None => (6, 0),484 };485 let padding = if clfags.zero && !clfags.left {484 let padding = if clfags.zero && !clfags.left {486 width485 width487 } else {486 } else {587 }586 }588 ConvTypeV::Char => match value.clone() {587 ConvTypeV::Char => match value.clone() {589 Val::Num(n) => tmp_out588 Val::Num(n) => tmp_out.push(590 .push(std::char::from_u32(n as u32).ok_or(InvalidUnicodeCodepointGot(n as u32))?),589 std::char::from_u32(n as u32)590 .ok_or_else(|| InvalidUnicodeCodepointGot(n as u32))?,591 ),591 Val::Str(s) => {592 Val::Str(s) => {592 if s.chars().count() != 1 {593 if s.chars().count() != 1 {crates/jrsonnet-evaluator/src/stdlib/manifest.rsdiffbeforeafterboth49 }49 }50 Val::Null => buf.push_str("null"),50 Val::Null => buf.push_str("null"),51 Val::Str(s) => escape_string_json_buf(s, buf),51 Val::Str(s) => escape_string_json_buf(s, buf),52 Val::Num(n) => write!(buf, "{}", n).unwrap(),52 Val::Num(n) => write!(buf, "{n}").unwrap(),53 Val::Arr(items) => {53 Val::Arr(items) => {54 buf.push('[');54 buf.push('[');55 if !items.is_empty() {55 if !items.is_empty() {crates/jrsonnet-evaluator/src/stdlib/mod.rsdiffbeforeafterboth12pub fn std_format(s: State, str: IStr, vals: Val) -> Result<String> {12pub fn std_format(s: State, str: IStr, vals: Val) -> Result<String> {13 s.push(13 s.push(14 CallLocation::native(),14 CallLocation::native(),15 || format!("std.format of {}", str),15 || format!("std.format of {str}"),16 || {16 || {17 Ok(match vals {17 Ok(match vals {18 Val::Arr(vals) => format_arr(s.clone(), &str, &vals.evaluated(s.clone())?)?,18 Val::Arr(vals) => format_arr(s.clone(), &str, &vals.evaluated(s.clone())?)?,crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth16}16}171718impl PathResolver {18impl PathResolver {19 /// Will return Self::Relative(cwd), or Self::Absolute on cwd failure19 /// Will return `Self::Relative(cwd)`, or `Self::Absolute` on cwd failure20 pub fn new_cwd_fallback() -> Self {20 pub fn new_cwd_fallback() -> Self {21 match std::env::current_dir() {21 std::env::current_dir().map_or(Self::Absolute, Self::Relative)22 Ok(v) => Self::Relative(v),23 Err(_) => Self::Absolute,24 }25 }22 }26 pub fn resolve(&self, from: &Path) -> String {23 pub fn resolve(&self, from: &Path) -> String {27 match self {24 match self {97 use std::fmt::Write;94 use std::fmt::Write;989599 writeln!(out)?;96 writeln!(out)?;100 let mut n = match path.source_path().path() {97 let mut n = path.source_path().path().map_or_else(98 || path.source_path().to_string(),101 Some(r) => self.resolver.resolve(r),99 |r| self.resolver.resolve(r),102 None => path.source_path().to_string(),103 };100 );104 let mut offset = error.location.offset;101 let mut offset = error.location.offset;105 let is_eof = if offset >= path.code().len() {102 let is_eof = if offset >= path.code().len() {106 offset = path.code().len().saturating_sub(1);103 offset = path.code().len().saturating_sub(1);119116120 write!(n, ":").unwrap();117 write!(n, ":").unwrap();121 print_code_location(&mut n, &location, &location).unwrap();118 print_code_location(&mut n, &location, &location).unwrap();122 write!(out, "{:<p$}{}", "", n, p = self.padding,)?;119 write!(out, "{:<p$}{n}", "", p = self.padding)?;123 }120 }124 let file_names = error121 let file_names = error125 .trace()122 .trace()185 let desc = &item.desc;182 let desc = &item.desc;186 if let Some(source) = &item.location {183 if let Some(source) = &item.location {187 let start_end = source.0.map_source_locations(&[source.1, source.2]);184 let start_end = source.0.map_source_locations(&[source.1, source.2]);188 let resolved_path = match source.0.source_path().path() {185 let resolved_path = source.0.source_path().path().map_or_else(189 Some(r) => r.display().to_string(),186 || source.0.source_path().to_string(),190 None => source.0.source_path().to_string(),187 |r| r.display().to_string(),191 };188 );192189193 write!(190 write!(194 out,191 out,195 " at {} ({}:{}:{})",192 " at {} ({}:{}:{})",196 desc, resolved_path, start_end[0].line, start_end[0].column,193 desc, resolved_path, start_end[0].line, start_end[0].column,197 )?;194 )?;198 } else {195 } else {199 write!(out, " during {}", desc)?;196 write!(out, " during {desc}")?;200 }197 }201 }198 }202 Ok(())199 Ok(())252 desc,249 desc,253 )?;250 )?;254 } else {251 } else {255 write!(out, "{}", desc)?;252 write!(out, "{desc}")?;256 }253 }257 }254 }258 Ok(())255 Ok(())280 .take(end.line_end_offset - end.line_start_offset)277 .take(end.line_end_offset - end.line_start_offset)281 .collect();278 .collect();282279283 let origin = match origin.source_path().path() {280 let origin = origin.source_path().path().map_or_else(281 || origin.source_path().to_string(),284 Some(r) => self.resolver.resolve(r),282 |r| self.resolver.resolve(r),285 None => origin.source_path().to_string(),286 };283 );287 let snippet = Snippet {284 let snippet = Snippet {288 opt: FormatOptions {285 opt: FormatOptions {289 color: true,286 color: true,308 };305 };309306310 let dl = DisplayList::from(snippet);307 let dl = DisplayList::from(snippet);311 write!(out, "{}", dl)?;308 write!(out, "{dl}")?;312309313 Ok(())310 Ok(())314 }311 }crates/jrsonnet-evaluator/src/typed/mod.rsdiffbeforeafterboth21 UnionFailed(ComplexValType, TypeLocErrorList),21 UnionFailed(ComplexValType, TypeLocErrorList),22 #[error(22 #[error(23 "number out of bounds: {0} not in {}..{}",23 "number out of bounds: {0} not in {}..{}",24 .1.map(|v|v.to_string()).unwrap_or_else(|| "".to_owned()),24 .1.map(|v|v.to_string()).unwrap_or_default(),25 .2.map(|v|v.to_string()).unwrap_or_else(|| "".to_owned()),25 .2.map(|v|v.to_string()).unwrap_or_default(),26 )]26 )]27 BoundsFailed(f64, Option<f64>, Option<f64>),27 BoundsFailed(f64, Option<f64>, Option<f64>),28}28}65 writeln!(f)?;65 writeln!(f)?;66 }66 }67 out.clear();67 out.clear();68 write!(out, "{}", err)?;68 write!(out, "{err}")?;696970 for (i, line) in out.lines().enumerate() {70 for (i, line) in out.lines().enumerate() {71 if line.trim().is_empty() {71 if line.trim().is_empty() {77 writeln!(f)?;77 writeln!(f)?;78 write!(f, " ")?;78 write!(f, " ")?;79 }79 }80 write!(f, "{}", line)?;80 write!(f, "{line}")?;81 }81 }82 }82 }83 Ok(())83 Ok(())125impl Display for ValuePathItem {125impl Display for ValuePathItem {126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {127 match self {127 match self {128 Self::Field(name) => write!(f, ".{:?}", name)?,128 Self::Field(name) => write!(f, ".{name:?}")?,129 Self::Index(idx) => write!(f, "[{}]", idx)?,129 Self::Index(idx) => write!(f, "[{idx}]")?,130 }130 }131 Ok(())131 Ok(())132 }132 }138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {139 write!(f, "self")?;139 write!(f, "self")?;140 for elem in self.0.iter().rev() {140 for elem in self.0.iter().rev() {141 write!(f, "{}", elem)?;141 write!(f, "{elem}")?;142 }142 }143 Ok(())143 Ok(())144 }144 }171 for (i, item) in a.iter(s.clone()).enumerate() {171 for (i, item) in a.iter(s.clone()).enumerate() {172 push_type_description(172 push_type_description(173 s.clone(),173 s.clone(),174 || format!("array index {}", i),174 || format!("array index {i}"),175 || ValuePathItem::Index(i as u64),175 || ValuePathItem::Index(i as u64),176 || elem_type.check(s.clone(), &item.clone()?),176 || elem_type.check(s.clone(), &item.clone()?),177 )?;177 )?;185 for (i, item) in a.iter(s.clone()).enumerate() {185 for (i, item) in a.iter(s.clone()).enumerate() {186 push_type_description(186 push_type_description(187 s.clone(),187 s.clone(),188 || format!("array index {}", i),188 || format!("array index {i}"),189 || ValuePathItem::Index(i as u64),189 || ValuePathItem::Index(i as u64),190 || elem_type.check(s.clone(), &item.clone()?),190 || elem_type.check(s.clone(), &item.clone()?),191 )?;191 )?;200 if let Some(got_v) = obj.get(s.clone(), (*k).into())? {200 if let Some(got_v) = obj.get(s.clone(), (*k).into())? {201 push_type_description(201 push_type_description(202 s.clone(),202 s.clone(),203 || format!("property {}", k),203 || format!("property {k}"),204 || ValuePathItem::Field((*k).into()),204 || ValuePathItem::Field((*k).into()),205 || v.check(s.clone(), &got_v),205 || v.check(s.clone(), &got_v),206 )?;206 )?;crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth292 if index >= v.to() {292 if index >= v.to() {293 return Ok(None);293 return Ok(None);294 }294 }295 v.inner.get(s, index as usize)295 v.inner.get(s, index)296 }296 }297 }297 }298 }298 }332 if index >= s.to() {332 if index >= s.to() {333 return None;333 return None;334 }334 }335 s.inner.get_lazy(index as usize)335 s.inner.get_lazy(index)336 }336 }337 }337 }338 }338 }531 }531 }532}532}533533534#[cfg(target_pointer_width = "64")]534// Broken between stable and nightly, as there is new layout size optimization535static_assertions::assert_eq_size!(Val, [u8; 32]);535// #[cfg(target_pointer_width = "64")]536// static_assertions::assert_eq_size!(Val, [u8; 24]);536537537impl Val {538impl Val {538 pub const fn as_bool(&self) -> Option<bool> {539 pub const fn as_bool(&self) -> Option<bool> {crates/jrsonnet-stdlib/src/encoding.rsdiffbeforeafterboth282829#[builtin]29#[builtin]30pub fn builtin_base64_decode_bytes(input: IStr) -> Result<IBytes> {30pub fn builtin_base64_decode_bytes(input: IStr) -> Result<IBytes> {31 Ok(base64::decode(&input.as_bytes())31 Ok(base64::decode(input.as_bytes())32 .map_err(|_| RuntimeError("bad base64".into()))?32 .map_err(|_| RuntimeError("bad base64".into()))?33 .as_slice()33 .as_slice()34 .into())34 .into())35}35}363637#[builtin]37#[builtin]38pub fn builtin_base64_decode(input: IStr) -> Result<String> {38pub fn builtin_base64_decode(input: IStr) -> Result<String> {39 let bytes = base64::decode(&input.as_bytes()).map_err(|_| RuntimeError("bad base64".into()))?;39 let bytes = base64::decode(input.as_bytes()).map_err(|_| RuntimeError("bad base64".into()))?;40 Ok(String::from_utf8(bytes).map_err(|_| RuntimeError("bad utf8".into()))?)40 Ok(String::from_utf8(bytes).map_err(|_| RuntimeError("bad utf8".into()))?)41}41}4242crates/jrsonnet-stdlib/src/hash.rsdiffbeforeafterboth223#[builtin]3#[builtin]4pub fn builtin_md5(str: IStr) -> Result<String> {4pub fn builtin_md5(str: IStr) -> Result<String> {5 Ok(format!("{:x}", md5::compute(&str.as_bytes())))5 Ok(format!("{:x}", md5::compute(str.as_bytes())))6}6}77crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth366366367#[builtin]367#[builtin]368fn builtin_substr(str: IStr, from: usize, len: usize) -> Result<String> {368fn builtin_substr(str: IStr, from: usize, len: usize) -> Result<String> {369 Ok(str.chars().skip(from as usize).take(len as usize).collect())369 Ok(str.chars().skip(from).take(len).collect())370}370}371371372#[builtin(fields(372#[builtin(fields(380 .ext_vars380 .ext_vars381 .get(&x)381 .get(&x)382 .cloned()382 .cloned()383 .ok_or(UndefinedExternalVariable(x))?383 .ok_or_else(|| UndefinedExternalVariable(x))?384 .evaluate_arg(s.clone(), ctx, true)?384 .evaluate_arg(s.clone(), ctx, true)?385 .evaluate(s)?))385 .evaluate(s)?))386}386}402402403#[builtin]403#[builtin]404fn builtin_char(n: u32) -> Result<char> {404fn builtin_char(n: u32) -> Result<char> {405 Ok(std::char::from_u32(n as u32).ok_or(InvalidUnicodeCodepointGot(n as u32))?)405 Ok(std::char::from_u32(n).ok_or_else(|| InvalidUnicodeCodepointGot(n))?)406}406}407407408#[builtin(fields(408#[builtin(fields(