git.delta.rocks / jrsonnet / refs/commits / 11643ec5f009

difftreelog

style switch clippy to pedantic

Yaroslav Bolyukin2022-04-22parent: #b4a4398.patch.diff
in: master

25 files changed

modifiedcrates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth
86 }86 }
87}87}
8888
89#[allow(clippy::struct_excessive_bools)]
89#[derive(Default, Debug)]90#[derive(Default, Debug)]
90pub struct CFlags {91pub struct CFlags {
91 pub alt: bool,92 pub alt: bool,
270 return Ok(out);271 return Ok(out);
271 }272 }
272 str = &str[offset + 1..];273 str = &str[offset + 1..];
273 let (code, nstr) = parse_code(str)?;274 let code;
274 str = nstr;275 (code, str) = parse_code(str)?;
275 bytes = str.as_bytes();276 bytes = str.as_bytes();
276 offset = 0;277 offset = 0;
277278
278 out.push(Element::Code(code))279 out.push(Element::Code(code));
279 }280 }
280}281}
281282
313 .saturating_sub(prefix.len() + digits.len());314 .saturating_sub(prefix.len() + digits.len());
314315
315 if neg {316 if neg {
316 out.push('-')317 out.push('-');
317 } else if sign {318 } else if sign {
318 out.push('+');319 out.push('+');
319 } else if blank {320 } else if blank {
340 blank: bool,341 blank: bool,
341 sign: bool,342 sign: bool,
342) {343) {
343 render_integer(out, iv, padding, precision, blank, sign, 10, "", false)344 render_integer(out, iv, padding, precision, blank, sign, 10, "", false);
344}345}
345pub fn render_octal(346pub fn render_octal(
346 out: &mut String,347 out: &mut String,
361 8,362 8,
362 if alt && iv != 0 { "0" } else { "" },363 if alt && iv != 0 { "0" } else { "" },
363 false,364 false,
364 )365 );
365}366}
367
368#[allow(clippy::fn_params_excessive_bools)]
366pub fn render_hexadecimal(369pub fn render_hexadecimal(
367 out: &mut String,370 out: &mut String,
368 iv: i64,371 iv: i64,
387 (false, _) => "",390 (false, _) => "",
388 },391 },
389 caps,392 caps,
390 )393 );
391}394}
392395
396#[allow(clippy::fn_params_excessive_bools)]
393pub fn render_float(397pub fn render_float(
394 out: &mut String,398 out: &mut String,
395 n: f64,399 n: f64,
431 }435 }
432}436}
433437
438#[allow(clippy::fn_params_excessive_bools)]
434pub fn render_float_sci(439pub fn render_float_sci(
435 out: &mut String,440 out: &mut String,
436 n: f64,441 n: f64,
461 out.push_str(&exponent_str);466 out.push_str(&exponent_str);
462}467}
463468
469#[allow(clippy::too_many_lines)]
464pub fn format_code(470pub fn format_code(
465 s: State,471 s: State,
466 out: &mut String,472 out: &mut String,
modifiedcrates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth
158 '\r' => buf.push_str("\\r"),158 '\r' => buf.push_str("\\r"),
159 '\t' => buf.push_str("\\t"),159 '\t' => buf.push_str("\\t"),
160 c if c < 32 as char || (c >= 127 as char && c <= 159 as char) => {160 c if c < 32 as char || (c >= 127 as char && c <= 159 as char) => {
161 write!(buf, "\\u{:04x}", c as u32).unwrap()161 write!(buf, "\\u{:04x}", c as u32).unwrap();
162 }162 }
163 c => buf.push(c),163 c => buf.push(c),
164 }164 }
194 pub preserve_order: bool,194 pub preserve_order: bool,
195}195}
196196
197/// From https://github.com/chyh1990/yaml-rust/blob/da52a68615f2ecdd6b7e4567019f280c433c1521/src/emitter.rs#L289197/// From <https://github.com/chyh1990/yaml-rust/blob/da52a68615f2ecdd6b7e4567019f280c433c1521/src/emitter.rs#L289>
198/// With added date check198/// With added date check
199fn yaml_needs_quotes(string: &str) -> bool {199fn yaml_needs_quotes(string: &str) -> bool {
200 fn need_quotes_spaces(string: &str) -> bool {200 fn need_quotes_spaces(string: &str) -> bool {
228 Ok(out)228 Ok(out)
229}229}
230
231#[allow(clippy::too_many_lines)]
230fn manifest_yaml_ex_buf(232fn manifest_yaml_ex_buf(
231 s: State,233 s: State,
232 val: &Val,234 val: &Val,
238 match val {240 match val {
239 Val::Bool(v) => {241 Val::Bool(v) => {
240 if *v {242 if *v {
241 buf.push_str("true")243 buf.push_str("true");
242 } else {244 } else {
243 buf.push_str("false")245 buf.push_str("false");
244 }246 }
245 }247 }
246 Val::Null => buf.push_str("null"),248 Val::Null => buf.push_str("null"),
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
1// All builtins should return results
2#![allow(clippy::unnecessary_wraps)]
3
1use std::collections::HashMap;4use std::collections::HashMap;
25
173fn builtin_make_array(s: State, sz: usize, func: FuncVal) -> Result<VecVal> {176fn builtin_make_array(s: State, sz: usize, func: FuncVal) -> Result<VecVal> {
174 let mut out = Vec::with_capacity(sz);177 let mut out = Vec::with_capacity(sz);
175 for i in 0..sz {178 for i in 0..sz {
176 out.push(func.evaluate_simple(s.clone(), &[i as f64].as_slice())?)179 out.push(func.evaluate_simple(s.clone(), &[i as f64].as_slice())?);
177 }180 }
178 Ok(VecVal(Cc::new(out)))181 Ok(VecVal(Cc::new(out)))
179}182}
420 match func.evaluate_simple(s.clone(), &[Any(el)].as_slice())? {423 match func.evaluate_simple(s.clone(), &[Any(el)].as_slice())? {
421 Val::Arr(o) => {424 Val::Arr(o) => {
422 for oe in o.iter(s.clone()) {425 for oe in o.iter(s.clone()) {
423 out.push(oe?)426 out.push(oe?);
424 }427 }
425 }428 }
426 _ => throw!(RuntimeError(429 _ => throw!(RuntimeError(
707#[jrsonnet_macros::builtin]710#[jrsonnet_macros::builtin]
708fn builtin_count(s: State, arr: Vec<Any>, v: Any) -> Result<usize> {711fn builtin_count(s: State, arr: Vec<Any>, v: Any) -> Result<usize> {
709 let mut count = 0;712 let mut count = 0;
710 for item in arr.iter() {713 for item in &arr {
711 if equals(s.clone(), &item.0, &v.0)? {714 if equals(s.clone(), &item.0, &v.0)? {
712 count += 1;715 count += 1;
713 }716 }
modifiedcrates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth
53 match (i, sort_type) {53 match (i, sort_type) {
54 (Val::Str(_), SortKeyType::Unknown) => sort_type = SortKeyType::String,54 (Val::Str(_), SortKeyType::Unknown) => sort_type = SortKeyType::String,
55 (Val::Num(_), SortKeyType::Unknown) => sort_type = SortKeyType::Number,55 (Val::Num(_), SortKeyType::Unknown) => sort_type = SortKeyType::Number,
56 (Val::Str(_), SortKeyType::String) => {}56 (Val::Str(_), SortKeyType::String) | (Val::Num(_), SortKeyType::Number) => {}
57 (Val::Str(_), _) => throw!(SortError::SortElementsShouldHaveEqualType),
58 (Val::Num(_), SortKeyType::Number) => {}
59 (Val::Num(_), _) => throw!(SortError::SortElementsShouldHaveEqualType),57 (Val::Str(_) | Val::Num(_), _) => {
58 throw!(SortError::SortElementsShouldHaveEqualType)
59 }
60 _ => throw!(SortError::SortKeyShouldBeStringOrNumber),60 _ => throw!(SortError::SortKeyShouldBeStringOrNumber),
61 }61 }
62 }62 }
91 Ok(Cc::new(vk.into_iter().map(|v| v.0).collect()))91 Ok(Cc::new(vk.into_iter().map(|v| v.0).collect()))
92 } else {92 } else {
93 // Fast path, identity key getter93 // Fast path, identity key getter
94 let mut mvalues = (*values).clone();94 let mut values = (*values).clone();
95 let sort_type = get_sort_type(&mut mvalues, |k| k)?;95 let sort_type = get_sort_type(&mut values, |k| k)?;
96 match sort_type {96 match sort_type {
97 SortKeyType::Number => mvalues.sort_unstable_by_key(|v| match v {97 SortKeyType::Number => values.sort_unstable_by_key(|v| match v {
98 Val::Num(n) => NonNaNf64(*n),98 Val::Num(n) => NonNaNf64(*n),
99 _ => unreachable!(),99 _ => unreachable!(),
100 }),100 }),
101 SortKeyType::String => mvalues.sort_unstable_by_key(|v| match v {101 SortKeyType::String => values.sort_unstable_by_key(|v| match v {
102 Val::Str(s) => s.clone(),102 Val::Str(s) => s.clone(),
103 _ => unreachable!(),103 _ => unreachable!(),
104 }),104 }),
105 SortKeyType::Unknown => unreachable!(),105 SortKeyType::Unknown => unreachable!(),
106 };106 };
107 Ok(Cc::new(mvalues))107 Ok(Cc::new(values))
108 }108 }
109}109}
110110
modifiedcrates/jrsonnet-evaluator/src/builtin/stdlib.rsdiffbeforeafterboth
24}24}
2525
26pub fn get_parsed_stdlib() -> LocExpr {26pub fn get_parsed_stdlib() -> LocExpr {
27 PARSED_STDLIB.with(|t| t.clone())27 PARSED_STDLIB.with(Clone::clone)
28}28}
2929
modifiedcrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
79 pub fn contains_binding(&self, name: IStr) -> bool {79 pub fn contains_binding(&self, name: IStr) -> bool {
80 self.0.bindings.contains_key(&name)80 self.0.bindings.contains_key(&name)
81 }81 }
82 #[must_use]
82 pub fn into_future(self, ctx: FutureWrapper<Self>) -> Self {83 pub fn into_future(self, ctx: FutureWrapper<Self>) -> Self {
83 {84 {
84 ctx.0.borrow_mut().replace(self);85 ctx.0.borrow_mut().replace(self);
85 }86 }
86 ctx.unwrap()87 ctx.unwrap()
87 }88 }
8889
90 #[must_use]
89 pub fn with_var(self, name: IStr, value: Val) -> Self {91 pub fn with_var(self, name: IStr, value: Val) -> Self {
90 let mut new_bindings = GcHashMap::with_capacity(1);92 let mut new_bindings = GcHashMap::with_capacity(1);
91 new_bindings.insert(name, LazyVal::new_resolved(value));93 new_bindings.insert(name, LazyVal::new_resolved(value));
92 self.extend(new_bindings, None, None, None)94 self.extend(new_bindings, None, None, None)
93 }95 }
9496
97 #[must_use]
95 pub fn with_this_super(self, new_this: ObjValue, new_super_obj: Option<ObjValue>) -> Self {98 pub fn with_this_super(self, new_this: ObjValue, new_super_obj: Option<ObjValue>) -> Self {
96 self.extend(GcHashMap::new(), None, Some(new_this), new_super_obj)99 self.extend(GcHashMap::new(), None, Some(new_this), new_super_obj)
97 }100 }
98101
102 #[must_use]
99 pub fn extend(103 pub fn extend(
100 self,104 self,
101 new_bindings: GcHashMap<IStr, LazyVal>,105 new_bindings: GcHashMap<IStr, LazyVal>,
119 bindings,123 bindings,
120 }))124 }))
121 }125 }
126 #[must_use]
122 pub fn extend_bound(self, new_bindings: GcHashMap<IStr, LazyVal>) -> Self {127 pub fn extend_bound(self, new_bindings: GcHashMap<IStr, LazyVal>) -> Self {
123 let new_this = self.0.this.clone();128 let new_this = self.0.this.clone();
124 let new_super_obj = self.0.super_obj.clone();129 let new_super_obj = self.0.super_obj.clone();
135 let this = new_this.or_else(|| self.0.this.clone());140 let this = new_this.or_else(|| self.0.this.clone());
136 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());141 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());
137 let mut new = GcHashMap::with_capacity(new_bindings.len());142 let mut new = GcHashMap::with_capacity(new_bindings.len());
138 for (k, v) in new_bindings.0.into_iter() {143 for (k, v) in new_bindings.0 {
139 new.insert(k, v.evaluate(s.clone(), this.clone(), super_obj.clone())?);144 new.insert(k, v.evaluate(s.clone(), this.clone(), super_obj.clone())?);
140 }145 }
141 Ok(self.extend(new, new_dollar, this, super_obj))146 Ok(self.extend(new, new_dollar, this, super_obj))
modifiedcrates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth
8 pub fn new() -> Self {8 pub fn new() -> Self {
9 Self(Cc::new(RefCell::new(None)))9 Self(Cc::new(RefCell::new(None)))
10 }10 }
11 /// # Panics
12 /// If wrapper is filled already
11 pub fn fill(self, value: T) {13 pub fn fill(self, value: T) {
12 assert!(self.0.borrow().is_none(), "wrapper is filled already");14 assert!(self.0.borrow().is_none(), "wrapper is filled already");
13 self.0.borrow_mut().replace(value);15 self.0.borrow_mut().replace(value);
14 }16 }
15}17}
16impl<T: Clone + Trace + 'static> FutureWrapper<T> {18impl<T: Clone + Trace + 'static> FutureWrapper<T> {
19 /// # Panics
20 /// If wrapper is not yet filled
17 pub fn unwrap(&self) -> T {21 pub fn unwrap(&self) -> T {
18 self.0.borrow().as_ref().cloned().unwrap()22 self.0.borrow().as_ref().cloned().unwrap()
19 }23 }
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
96 #[error(96 #[error(
97 "syntax error: expected {}, got {:?}",97 "syntax error: expected {}, got {:?}",
98 .error.expected,98 .error.expected,
99 .source_code.chars().nth(error.location.offset).map(|c| c.to_string()).unwrap_or_else(|| "EOF".into())99 .source_code.chars().nth(error.location.offset)
100 .map_or_else(|| "EOF".into(), |c| c.to_string())
100 )]101 )]
101 ImportSyntaxError {102 ImportSyntaxError {
102 #[skip_trace]103 #[skip_trace]
190impl Debug for LocError {191impl Debug for LocError {
191 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
192 writeln!(f, "{}", self.0 .0)?;193 writeln!(f, "{}", self.0 .0)?;
193 for el in self.0 .1 .0.iter() {194 for el in &self.0 .1 .0 {
194 writeln!(f, "\t{:?}", el)?;195 writeln!(f, "\t{:?}", el)?;
195 }196 }
196 Ok(())197 Ok(())
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
23pub fn evaluate_binding_in_future(b: &BindSpec, fctx: FutureWrapper<Context>) -> LazyVal {23pub fn evaluate_binding_in_future(b: &BindSpec, fctx: FutureWrapper<Context>) -> LazyVal {
24 let b = b.clone();24 let b = b.clone();
25 if let Some(params) = &b.params {25 if let Some(params) = &b.params {
26 let params = params.clone();
27
28 #[derive(Trace)]26 #[derive(Trace)]
29 struct LazyMethodBinding {27 struct LazyMethodBinding {
43 }41 }
44 }42 }
43
44 let params = params.clone();
4545
46 LazyVal::new(TraceBox(Box::new(LazyMethodBinding {46 LazyVal::new(TraceBox(Box::new(LazyMethodBinding {
47 fctx,47 fctx,
69 }69 }
70}70}
7171
72#[allow(clippy::too_many_lines)]
72pub fn evaluate_binding(b: &BindSpec, cctx: ContextCreator) -> (IStr, LazyBinding) {73pub fn evaluate_binding(b: &BindSpec, cctx: ContextCreator) -> (IStr, LazyBinding) {
73 let b = b.clone();74 let b = b.clone();
74 if let Some(params) = &b.params {75 if let Some(params) = &b.params {
75 let params = params.clone();
76
77 #[derive(Trace)]76 #[derive(Trace)]
78 struct BindableMethodLazyVal {77 struct BindableMethodLazyVal {
121 }120 }
122 }121 }
122
123 let params = params.clone();
123124
124 (125 (
125 b.name.clone(),126 b.name.clone(),
227 None => callback(ctx)?,228 None => callback(ctx)?,
228 Some(CompSpec::IfSpec(IfSpecData(cond))) => {229 Some(CompSpec::IfSpec(IfSpecData(cond))) => {
229 if bool::from_untyped(evaluate(s.clone(), ctx.clone(), cond)?, s.clone())? {230 if bool::from_untyped(evaluate(s.clone(), ctx.clone(), cond)?, s.clone())? {
230 evaluate_comp(s, ctx, &specs[1..], callback)?231 evaluate_comp(s, ctx, &specs[1..], callback)?;
231 }232 }
232 }233 }
233 Some(CompSpec::ForSpec(ForSpecData(var, expr))) => {234 Some(CompSpec::ForSpec(ForSpecData(var, expr))) => {
239 ctx.clone().with_var(var.clone(), item?.clone()),240 ctx.clone().with_var(var.clone(), item?.clone()),
240 &specs[1..],241 &specs[1..],
241 callback,242 callback,
242 )?243 )?;
243 }244 }
244 }245 }
245 _ => throw!(InComprehensionCanOnlyIterateOverArray),246 _ => throw!(InComprehensionCanOnlyIterateOverArray),
249 Ok(())250 Ok(())
250}251}
251252
253#[allow(clippy::too_many_lines)]
252pub fn evaluate_member_list_object(s: State, ctx: Context, members: &[Member]) -> Result<ObjValue> {254pub fn evaluate_member_list_object(s: State, ctx: Context, members: &[Member]) -> Result<ObjValue> {
253 let new_bindings = FutureWrapper::new();255 let new_bindings = FutureWrapper::new();
254 let future_this = FutureWrapper::new();256 let future_this = FutureWrapper::new();
278 visibility,280 visibility,
279 value,281 value,
280 }) => {282 }) => {
281 let name = evaluate_field_name(s.clone(), ctx.clone(), name)?;
282 if name.is_none() {
283 continue;
284 }
285 let name = name.unwrap();
286
287 #[derive(Trace)]283 #[derive(Trace)]
288 struct ObjMemberBinding {284 struct ObjMemberBinding {
306 }302 }
307 }303 }
304
305 let name = evaluate_field_name(s.clone(), ctx.clone(), name)?;
306 let name = if let Some(name) = name {
307 name
308 } else {
309 continue;
310 };
311
308 builder312 builder
309 .member(name.clone())313 .member(name.clone())
325 value,329 value,
326 ..330 ..
327 }) => {331 }) => {
328 let name = evaluate_field_name(s.clone(), ctx.clone(), name)?;
329 if name.is_none() {
330 continue;
331 }
332 let name = name.unwrap();
333 #[derive(Trace)]332 #[derive(Trace)]
334 struct ObjMemberBinding {333 struct ObjMemberBinding {
335 cctx: ContextCreator,334 cctx: ContextCreator,
353 }352 }
354 }353 }
354
355 let name = if let Some(name) = evaluate_field_name(s.clone(), ctx.clone(), name)? {
356 name
357 } else {
358 continue;
359 };
360
355 builder361 builder
356 .member(name.clone())362 .member(name.clone())
505 throw!(AssertionFailed(511 throw!(AssertionFailed(
506 evaluate(s.clone(), ctx, msg)?.to_string(s.clone())?512 evaluate(s.clone(), ctx, msg)?.to_string(s.clone())?
507 ));513 ));
508 } else {514 }
509 throw!(AssertionFailed(Val::Null.to_string(s.clone())?));515 throw!(AssertionFailed(Val::Null.to_string(s.clone())?));
510 }
511 },516 },
512 )?517 )?;
513 }518 }
514 Ok(())519 Ok(())
515}520}
516521
517pub fn evaluate_named(s: State, ctx: Context, lexpr: &LocExpr, name: IStr) -> Result<Val> {522pub fn evaluate_named(s: State, ctx: Context, expr: &LocExpr, name: IStr) -> Result<Val> {
518 use Expr::*;523 use Expr::*;
519 let LocExpr(expr, _loc) = lexpr;524 let LocExpr(raw_expr, _loc) = expr;
520 Ok(match &**expr {525 Ok(match &**raw_expr {
521 Function(params, body) => evaluate_method(ctx, name, params.clone(), body.clone()),526 Function(params, body) => evaluate_method(ctx, name, params.clone(), body.clone()),
522 _ => evaluate(s, ctx, lexpr)?,527 _ => evaluate(s, ctx, expr)?,
523 })528 })
524}529}
525530
531#[allow(clippy::too_many_lines)]
526pub fn evaluate(s: State, ctx: Context, expr: &LocExpr) -> Result<Val> {532pub fn evaluate(s: State, ctx: Context, expr: &LocExpr) -> Result<Val> {
527 use Expr::*;533 use Expr::*;
528 let LocExpr(expr, loc) = expr;534 let LocExpr(expr, loc) = expr;
535 ctx.super_obj()541 ctx.super_obj().clone().ok_or(NoSuperFound)?.with_this(
536 .clone()
537 .ok_or(NoSuperFound)?
538 .with_this(ctx.this().clone().unwrap()),542 ctx.this()
543 .clone()
544 .expect("if super exists - then this should to"),
545 ),
539 ),546 ),
540 Literal(LiteralType::Dollar) => {547 Literal(LiteralType::Dollar) => {
699 }706 }
700 }707 }
701 Slice(value, desc) => {708 Slice(value, desc) => {
702 let indexable = evaluate(s.clone(), ctx.clone(), value)?;
703 let loc = CallLocation::new(loc);
704
705 fn parse_idx<T: Typed>(709 fn parse_idx<T: Typed>(
706 loc: CallLocation,710 loc: CallLocation,
720 }724 }
721 }725 }
726
727 let indexable = evaluate(s.clone(), ctx.clone(), value)?;
728 let loc = CallLocation::new(loc);
722729
723 let start = parse_idx(loc, s.clone(), &ctx, &desc.start, "start")?;730 let start = parse_idx(loc, s.clone(), &ctx, &desc.start, "start")?;
724 let end = parse_idx(loc, s.clone(), &ctx, &desc.end, "end")?;731 let end = parse_idx(loc, s.clone(), &ctx, &desc.end, "end")?;
modifiedcrates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth
1use std::cmp::Ordering;
2
1use jrsonnet_parser::{BinaryOpType, LocExpr, UnaryOpType};3use jrsonnet_parser::{BinaryOpType, LocExpr, UnaryOpType};
24
11 Ok(match (op, b) {13 Ok(match (op, b) {
12 (Not, Bool(v)) => Bool(!v),14 (Not, Bool(v)) => Bool(!v),
13 (Minus, Num(n)) => Num(-*n),15 (Minus, Num(n)) => Num(-*n),
14 (BitNot, Num(n)) => Num(!(*n as i32) as f64),16 (BitNot, Num(n)) => Num(f64::from(!(*n as i32))),
15 (op, o) => throw!(UnaryOperatorDoesNotOperateOnType(op, o.value_type())),17 (op, o) => throw!(UnaryOperatorDoesNotOperateOnType(op, o.value_type())),
16 })18 })
17}19}
22 (Str(v1), Str(v2)) => Str(((**v1).to_owned() + v2).into()),24 (Str(v1), Str(v2)) => Str(((**v1).to_owned() + v2).into()),
2325
24 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)26 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)
25 (Num(n), Str(o)) => Str(format!("{}{}", n, o).into()),27 (Num(a), Str(b)) => Str(format!("{a}{b}").into()),
26 (Str(o), Num(n)) => Str(format!("{}{}", o, n).into()),28 (Str(a), Num(b)) => Str(format!("{a}{b}").into()),
2729
28 (Str(a), o) => Str(format!("{}{}", a, o.clone().to_string(s)?).into()),30 (Str(a), o) => Str(format!("{}{}", a, o.clone().to_string(s)?).into()),
29 (o, Str(a)) => Str(format!("{}{}", o.clone().to_string(s)?, a).into()),31 (o, Str(a)) => Str(format!("{}{}", o.clone().to_string(s)?, a).into()),
47pub fn evaluate_mod_op(s: State, a: &Val, b: &Val) -> Result<Val> {49pub fn evaluate_mod_op(s: State, a: &Val, b: &Val) -> Result<Val> {
48 use Val::*;50 use Val::*;
49 match (a, b) {51 match (a, b) {
50 (Num(a), Num(b)) => Ok(Num(a % b)),52 (Num(a), Num(b)) => {
53 if *b == 0.0 {
54 throw!(DivisionByZero)
55 }
56 Ok(Num(a % b))
57 }
51 (Str(str), vals) => {58 (Str(str), vals) => {
52 String::into_untyped(std_format(s.clone(), str.clone(), vals.clone())?, s)59 String::into_untyped(std_format(s.clone(), str.clone(), vals.clone())?, s)
53 }60 }
75 })82 })
76}83}
84
85pub fn evaluate_compare_op(s: State, a: &Val, op: BinaryOpType, b: &Val) -> Result<Ordering> {
86 use Val::*;
87 Ok(match (a, b) {
88 (Str(a), Str(b)) => a.cmp(b),
89 (Num(a), Num(b)) => a.partial_cmp(b).expect("jsonnet numbers are non NaN"),
90 (Arr(a), Arr(b)) => {
91 let ai = a.iter(s.clone());
92 let bi = b.iter(s.clone());
93
94 for (a, b) in ai.zip(bi) {
95 let ord = evaluate_compare_op(s.clone(), &a?, op, &b?)?;
96 if !ord.is_eq() {
97 return Ok(ord);
98 }
99 }
100
101 a.len().cmp(&b.len())
102 }
103 (_, _) => throw!(BinaryOperatorDoesNotOperateOnValues(
104 op,
105 a.value_type(),
106 b.value_type()
107 )),
108 })
109}
77110
78pub fn evaluate_binary_op_normal(s: State, a: &Val, op: BinaryOpType, b: &Val) -> Result<Val> {111pub fn evaluate_binary_op_normal(s: State, a: &Val, op: BinaryOpType, b: &Val) -> Result<Val> {
79 use BinaryOpType::*;112 use BinaryOpType::*;
84 (a, Eq, b) => Bool(equals(s, a, b)?),117 (a, Eq, b) => Bool(equals(s, a, b)?),
85 (a, Neq, b) => Bool(!equals(s, a, b)?),118 (a, Neq, b) => Bool(!equals(s, a, b)?),
119
120 (a, Lt, b) => Bool(evaluate_compare_op(s, a, Lt, b)?.is_lt()),
121 (a, Gt, b) => Bool(evaluate_compare_op(s, a, Gt, b)?.is_gt()),
122 (a, Lte, b) => Bool(evaluate_compare_op(s, a, Lte, b)?.is_le()),
123 (a, Gte, b) => Bool(evaluate_compare_op(s, a, Gte, b)?.is_ge()),
86124
87 (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone(), true)),125 (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone(), true)),
88 (a, Mod, b) => evaluate_mod_op(s, a, b)?,126 (a, Mod, b) => evaluate_mod_op(s, a, b)?,
93 (Bool(a), And, Bool(b)) => Bool(*a && *b),131 (Bool(a), And, Bool(b)) => Bool(*a && *b),
94 (Bool(a), Or, Bool(b)) => Bool(*a || *b),132 (Bool(a), Or, Bool(b)) => Bool(*a || *b),
95
96 // Str X Str
97 (Str(v1), Lt, Str(v2)) => Bool(v1 < v2),
98 (Str(v1), Gt, Str(v2)) => Bool(v1 > v2),
99 (Str(v1), Lte, Str(v2)) => Bool(v1 <= v2),
100 (Str(v1), Gte, Str(v2)) => Bool(v1 >= v2),
101133
102 // Num X Num134 // Num X Num
103 (Num(v1), Mul, Num(v2)) => Val::new_checked_num(v1 * v2)?,135 (Num(v1), Mul, Num(v2)) => Val::new_checked_num(v1 * v2)?,
104 (Num(v1), Div, Num(v2)) => {136 (Num(v1), Div, Num(v2)) => {
105 if *v2 <= f64::EPSILON {137 if *v2 == 0.0 {
106 throw!(DivisionByZero)138 throw!(DivisionByZero)
107 }139 }
108 Val::new_checked_num(v1 / v2)?140 Val::new_checked_num(v1 / v2)?
109 }141 }
110142
111 (Num(v1), Sub, Num(v2)) => Val::new_checked_num(v1 - v2)?,143 (Num(v1), Sub, Num(v2)) => Val::new_checked_num(v1 - v2)?,
112
113 (Num(v1), Lt, Num(v2)) => Bool(v1 < v2),
114 (Num(v1), Gt, Num(v2)) => Bool(v1 > v2),
115 (Num(v1), Lte, Num(v2)) => Bool(v1 <= v2),
116 (Num(v1), Gte, Num(v2)) => Bool(v1 >= v2),
117144
118 (Num(v1), BitAnd, Num(v2)) => Num(((*v1 as i32) & (*v2 as i32)) as f64),145 (Num(v1), BitAnd, Num(v2)) => Num(f64::from((*v1 as i32) & (*v2 as i32))),
119 (Num(v1), BitOr, Num(v2)) => Num(((*v1 as i32) | (*v2 as i32)) as f64),146 (Num(v1), BitOr, Num(v2)) => Num(f64::from((*v1 as i32) | (*v2 as i32))),
120 (Num(v1), BitXor, Num(v2)) => Num(((*v1 as i32) ^ (*v2 as i32)) as f64),147 (Num(v1), BitXor, Num(v2)) => Num(f64::from((*v1 as i32) ^ (*v2 as i32))),
121 (Num(v1), Lhs, Num(v2)) => {148 (Num(v1), Lhs, Num(v2)) => {
122 if *v2 < 0.0 {149 if *v2 < 0.0 {
123 throw!(RuntimeError("shift by negative exponent".into()))150 throw!(RuntimeError("shift by negative exponent".into()))
124 }151 }
125 Num(((*v1 as i32) << (*v2 as i32)) as f64)152 Num(f64::from((*v1 as i32) << (*v2 as i32)))
126 }153 }
127 (Num(v1), Rhs, Num(v2)) => {154 (Num(v1), Rhs, Num(v2)) => {
128 if *v2 < 0.0 {155 if *v2 < 0.0 {
129 throw!(RuntimeError("shift by negative exponent".into()))156 throw!(RuntimeError("shift by negative exponent".into()))
130 }157 }
131 Num(((*v1 as i32) >> (*v2 as i32)) as f64)158 Num(f64::from((*v1 as i32) >> (*v2 as i32)))
132 }159 }
133160
134 _ => throw!(BinaryOperatorDoesNotOperateOnValues(161 _ => throw!(BinaryOperatorDoesNotOperateOnValues(
modifiedcrates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth
145 tailstrict: bool,145 tailstrict: bool,
146 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,146 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,
147 ) -> Result<()> {147 ) -> Result<()> {
148 for (name, arg) in self.named.iter() {148 for (name, arg) in &self.named {
149 handler(149 handler(
150 name,150 name,
151 if tailstrict {151 if tailstrict {
162 }162 }
163163
164 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {164 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {
165 for (name, _) in self.named.iter() {165 for (name, _) in &self.named {
166 handler(name)166 handler(name);
167 }167 }
168 }168 }
169}169}
231 }231 }
232}232}
233233
234impl<A: ArgLike> ArgsLike for HashMap<IStr, A> {234impl<A: ArgLike, S> ArgsLike for HashMap<IStr, A, S> {
235 fn unnamed_len(&self) -> usize {235 fn unnamed_len(&self) -> usize {
236 0236 0
237 }237 }
325 }325 }
326326
327 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {327 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {
328 (*self).named_names(handler)328 (*self).named_names(handler);
329 }329 }
330}330}
331331
381 if passed_args.contains_key(&param.0.clone()) {381 if passed_args.contains_key(&param.0.clone()) {
382 continue;382 continue;
383 }383 }
384 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {
385 ctx: fctx.clone(),
386 name: param.0.clone(),
387 value: param.1.clone().unwrap(),
388 })));
389384
390 defaults.insert(385 defaults.insert(
391 param.0.clone(),386 param.0.clone(),
392 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {387 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {
393 ctx: fctx.clone(),388 ctx: fctx.clone(),
394 name: param.0.clone(),389 name: param.0.clone(),
395 value: param.1.clone().unwrap(),390 value: param.1.clone().expect("default exists"),
396 }))),391 }))),
397 );392 );
398 filled_args += 1;393 filled_args += 1;
447 // const INST: &'static Self;442 // const INST: &'static Self;
448}443}
449444
450/// You shouldn't probally use this function, use jrsonnet_macros::builtin instead445/// You shouldn't probally use this function, use `jrsonnet_macros::builtin` instead
451///446///
452/// ## Parameters447/// ## Parameters
453/// * `ctx`: used for passed argument expressions' execution and for body execution (if `body_ctx` is not set)448/// * `ctx`: used for passed argument expressions' execution and for body execution (if `body_ctx` is not set)
518/// Creates Context, which has all argument default values applied513/// Creates Context, which has all argument default values applied
519/// and with unbound values causing error to be returned514/// and with unbound values causing error to be returned
520pub fn parse_default_function_call(body_ctx: Context, params: &ParamsDesc) -> Context {515pub fn parse_default_function_call(body_ctx: Context, params: &ParamsDesc) -> Context {
521 let fctx = Context::new_future();
522
523 let mut bindings = GcHashMap::new();
524
525 #[derive(Trace)]516 #[derive(Trace)]
526 struct DependsOnUnbound(IStr);517 struct DependsOnUnbound(IStr);
530 }521 }
531 }522 }
523
524 let fctx = Context::new_future();
525
526 let mut bindings = GcHashMap::new();
532527
533 for param in params.iter() {528 for param in params.iter() {
534 if let Some(v) = &param.1 {529 if let Some(v) = &param.1 {
modifiedcrates/jrsonnet-evaluator/src/gc.rsdiffbeforeafterboth
1/// Macros to help deal with Gc1/// Macros to help deal with Gc
2use std::{2use std::{
3 borrow::{Borrow, BorrowMut},3 borrow::{Borrow, BorrowMut},
4 collections::{HashMap, HashSet},
4 hash::BuildHasherDefault,5 hash::BuildHasherDefault,
5 ops::{Deref, DerefMut},6 ops::{Deref, DerefMut},
6};7};
1415
15impl<T: ?Sized + Trace> Trace for TraceBox<T> {16impl<T: ?Sized + Trace> Trace for TraceBox<T> {
16 fn trace(&self, tracer: &mut Tracer) {17 fn trace(&self, tracer: &mut Tracer) {
17 self.0.trace(tracer)18 self.0.trace(tracer);
18 }19 }
1920
20 fn is_type_tracked() -> bool {21 fn is_type_tracked() -> bool {
70pub struct GcHashSet<V>(pub FxHashSet<V>);71pub struct GcHashSet<V>(pub FxHashSet<V>);
71impl<V> GcHashSet<V> {72impl<V> GcHashSet<V> {
72 pub fn new() -> Self {73 pub fn new() -> Self {
73 Self(Default::default())74 Self(HashSet::default())
74 }75 }
75 pub fn with_capacity(capacity: usize) -> Self {76 pub fn with_capacity(capacity: usize) -> Self {
76 Self(FxHashSet::with_capacity_and_hasher(77 Self(FxHashSet::with_capacity_and_hasher(
111pub struct GcHashMap<K, V>(pub FxHashMap<K, V>);112pub struct GcHashMap<K, V>(pub FxHashMap<K, V>);
112impl<K, V> GcHashMap<K, V> {113impl<K, V> GcHashMap<K, V> {
113 pub fn new() -> Self {114 pub fn new() -> Self {
114 Self(Default::default())115 Self(HashMap::default())
115 }116 }
116 pub fn with_capacity(capacity: usize) -> Self {117 pub fn with_capacity(capacity: usize) -> Self {
117 Self(FxHashMap::with_capacity_and_hasher(118 Self(FxHashMap::with_capacity_and_hasher(
modifiedcrates/jrsonnet-evaluator/src/import.rsdiffbeforeafterboth
79 if direct.exists() {79 if direct.exists() {
80 Ok(direct.into())80 Ok(direct.into())
81 } else {81 } else {
82 for library_path in self.library_paths.iter() {82 for library_path in &self.library_paths {
83 let mut cloned = library_path.clone();83 let mut cloned = library_path.clone();
84 cloned.push(path);84 cloned.push(path);
85 if cloned.exists() {85 if cloned.exists() {
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
1#![warn(clippy::all, clippy::nursery)]1#![warn(clippy::all, clippy::nursery, clippy::pedantic)]
2#![allow(2#![allow(
3 macro_expanded_macro_exports_accessed_by_absolute_paths,3 macro_expanded_macro_exports_accessed_by_absolute_paths,
4 clippy::ptr_arg4 clippy::ptr_arg,
5 // Too verbose
6 clippy::must_use_candidate,
7 // A lot of functions pass around errors thrown by code
8 clippy::missing_errors_doc,
9 // A lot of pointers have interior Rc
10 clippy::needless_pass_by_value,
11 // Its fine
12 clippy::wildcard_imports,
13 clippy::enum_glob_use,
14 clippy::module_name_repetitions,
15 // TODO: fix individual issues, however this works as intended almost everywhere
16 clippy::cast_precision_loss,
17 clippy::cast_possible_wrap,
18 clippy::cast_possible_truncation,
19 clippy::cast_sign_loss,
5)]20)]
621
7// For jrsonnet-macros22// For jrsonnet-macros
105 Self {120 Self {
106 max_stack: 200,121 max_stack: 200,
107 max_trace: 20,122 max_trace: 20,
108 globals: Default::default(),123 globals: HashMap::default(),
109 ext_vars: Default::default(),124 ext_vars: HashMap::default(),
110 ext_natives: Default::default(),125 ext_natives: HashMap::default(),
111 tla_vars: Default::default(),126 tla_vars: HashMap::default(),
112 import_resolver: Box::new(DummyImportResolver),127 import_resolver: Box::new(DummyImportResolver),
113 manifest_format: ManifestFormat::Json {128 manifest_format: ManifestFormat::Json {
114 padding: 4,129 padding: 4,
161 if self.0.is_empty() {176 if self.0.is_empty() {
162 return result;177 return result;
163 }178 }
164 for item in self.0.iter() {179 for item in &self.0 {
165 if item.loc.belongs_to(loc) {180 if item.loc.belongs_to(loc) {
166 let mut collected = item.collected.borrow_mut();181 let mut collected = item.collected.borrow_mut();
167 let (depth, vals) = collected.entry(stack_generation).or_default();182 let (depth, vals) = collected.entry(stack_generation).or_default();
198 )213 )
199 .map_err(|error| ImportSyntaxError {214 .map_err(|error| ImportSyntaxError {
200 error: Box::new(error),215 error: Box::new(error),
201 path: path.to_owned(),216 path: path.clone(),
202 source_code: source_code.clone(),217 source_code: source_code.clone(),
203 })?;218 })?;
204 self.add_parsed_file(path, source_code, parsed.clone())?;219 self.add_parsed_file(path, source_code, parsed.clone())?;
210 self.data_mut()225 self.data_mut()
211 .files226 .files
212 .get_mut(name)227 .get_mut(name)
213 .unwrap()228 .expect("file not found")
214 .evaluated229 .evaluated
215 .take();230 .take();
216 }231 }
246 line: usize,261 line: usize,
247 column: usize,262 column: usize,
248 ) -> Option<usize> {263 ) -> Option<usize> {
249 location_to_offset(&self.get_source(file).unwrap(), line, column)264 location_to_offset(
265 &self.get_source(file).expect("file not found"),
266 line,
267 column,
268 )
312 STDLIB_STR.to_owned().into(),331 STDLIB_STR.to_owned().into(),
313 builtin::get_parsed_stdlib(),332 builtin::get_parsed_stdlib(),
314 )333 )
315 .unwrap();334 .expect("stdlib is correct");
316 let val = self.evaluate_loaded_file_raw(&std_path).unwrap();335 let val = self
336 .evaluate_loaded_file_raw(&std_path)
337 .expect("stdlib is correct");
317 self.settings_mut().globals.insert("std".into(), val);338 self.settings_mut().globals.insert("std".into(), val);
318 self339 self
319 }340 }
342 // Error creation uses data, so i drop guard here363 // Error creation uses data, so i drop guard here
343 drop(data);364 drop(data);
344 throw!(StackOverflow);365 throw!(StackOverflow);
345 } else {366 }
346 *stack_depth += 1;367 *stack_depth += 1;
347 }
348 }368 }
349 let result = f();369 let result = f();
350 {370 {
376 // Error creation uses data, so i drop guard here396 // Error creation uses data, so i drop guard here
377 drop(data);397 drop(data);
378 throw!(StackOverflow);398 throw!(StackOverflow);
379 } else {399 }
380 *stack_depth += 1;400 *stack_depth += 1;
381 }
382 }401 }
383 let mut result = f();402 let mut result = f();
384 {403 {
411 // Error creation uses data, so i drop guard here430 // Error creation uses data, so i drop guard here
412 drop(data);431 drop(data);
413 throw!(StackOverflow);432 throw!(StackOverflow);
414 } else {433 }
415 *stack_depth += 1;434 *stack_depth += 1;
416 }
417 }435 }
418 let result = f();436 let result = f();
419 {437 {
431 result449 result
432 }450 }
433451
452 /// # Panics
453 /// In case of formatting failure
434 pub fn stringify_err(&self, e: &LocError) -> String {454 pub fn stringify_err(&self, e: &LocError) -> String {
435 let mut out = String::new();455 let mut out = String::new();
436 self.settings()456 self.settings()
1234 assert_eval!(r#"std.assertEqual(std.count(["a", "b", "a"], "a"), 2)"#);1254 assert_eval!(r#"std.assertEqual(std.count(["a", "b", "a"], "a"), 2)"#);
1235 }1255 }
1236
1237 mod derive_typed {
1238 use std::path::PathBuf;
1239
1240 use crate::{typed::Typed, State};
1241
1242 #[derive(PartialEq, Debug, Typed)]
1243 struct MyTyped {
1244 a: u32,
1245 #[typed(rename = "b")]
1246 c: String,
1247 }
1248
1249 #[test]
1250 fn test() {
1251 let es = State::default();
1252 let val = eval!("{a: 14, b: 'Hello, world!'}");
1253 let typed = MyTyped::try_from(val).unwrap();
1254
1255 assert_eq!(
1256 typed,
1257 MyTyped {
1258 a: 14,
1259 c: "Hello, world!".to_string()
1260 }
1261 );
1262 es.settings_mut()
1263 .globals
1264 .insert("mytyped".into(), typed.try_into().unwrap());
1265
1266 let v = es
1267 .evaluate_snippet_raw(
1268 PathBuf::from("raw.jsonnet").into(),
1269 "
1270 mytyped == {a: 14, b: 'Hello, world!'}
1271 "
1272 .into(),
1273 )
1274 .unwrap()
1275 .as_bool()
1276 .unwrap();
1277 assert!(v)
1278 }
1279 }
1280}1256}
12811257
modifiedcrates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth
34 .034 .0
35 .parent35 .parent
36 .as_ref()36 .as_ref()
37 .map(|p| p.contains_key(key))37 .map_or(false, |p| p.contains_key(key))
38 .unwrap_or(false)
39 }38 }
40}39}
4140
modifiedcrates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth
37 fn call(&self, s: State, ctx: Context, loc: CallLocation, args: &dyn ArgsLike) -> Result<Val> {37 fn call(&self, s: State, ctx: Context, loc: CallLocation, args: &dyn ArgsLike) -> Result<Val> {
38 let args = parse_builtin_call(s.clone(), ctx, &self.params, args, true)?;38 let args = parse_builtin_call(s.clone(), ctx, &self.params, args, true)?;
39 let mut out_args = Vec::with_capacity(self.params.len());39 let mut out_args = Vec::with_capacity(self.params.len());
40 for p in self.params.iter() {40 for p in &self.params {
41 out_args.push(args[&p.name].evaluate(s.clone())?);41 out_args.push(args[&p.name].evaluate(s.clone())?);
42 }42 }
43 self.handler.call(s, loc.0.map(|l| l.0.clone()), &out_args)43 self.handler.call(s, loc.0.map(|l| l.0.clone()), &out_args)
modifiedcrates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth
2 cell::RefCell,2 cell::RefCell,
3 fmt::Debug,3 fmt::Debug,
4 hash::{Hash, Hasher},4 hash::{Hash, Hasher},
5 ptr::addr_of,
5};6};
67
7use gcmodule::{Cc, Trace, Weak};8use gcmodule::{Cc, Trace, Weak};
2021
21#[cfg(not(feature = "exp-preserve-order"))]22#[cfg(not(feature = "exp-preserve-order"))]
22mod ordering {23mod ordering {
24 #![allow(
25 // This module works as stub for preserve-order feature
26 clippy::unused_self,
27 )]
28
23 use gcmodule::Trace;29 use gcmodule::Trace;
2430
8995
90use ordering::*;96use ordering::*;
9197
98#[allow(clippy::module_name_repetitions)]
92#[derive(Debug, Trace)]99#[derive(Debug, Trace)]
93pub struct ObjMember {100pub struct ObjMember {
94 pub add: bool,101 pub add: bool,
113 Errored(LocError),120 Errored(LocError),
114}121}
115122
123#[allow(clippy::module_name_repetitions)]
116#[derive(Trace)]124#[derive(Trace)]
117#[force_tracking]125#[force_tracking]
118pub struct ObjValueInternals {126pub struct ObjValueInternals {
136impl Eq for WeakObjValue {}144impl Eq for WeakObjValue {}
137impl Hash for WeakObjValue {145impl Hash for WeakObjValue {
138 fn hash<H: Hasher>(&self, hasher: &mut H) {146 fn hash<H: Hasher>(&self, hasher: &mut H) {
139 hasher.write_usize(weak_raw(self.0.clone()) as usize)147 hasher.write_usize(weak_raw(self.0.clone()) as usize);
140 }148 }
141}149}
142150
151#[allow(clippy::module_name_repetitions)]
143#[derive(Clone, Trace)]152#[derive(Clone, Trace)]
144pub struct ObjValue(pub(crate) Cc<ObjValueInternals>);153pub struct ObjValue(pub(crate) Cc<ObjValueInternals>);
145impl Debug for ObjValue {154impl Debug for ObjValue {
178 pub fn new_empty() -> Self {187 pub fn new_empty() -> Self {
179 Self::new(None, Cc::new(GcHashMap::new()), Cc::new(Vec::new()))188 Self::new(None, Cc::new(GcHashMap::new()), Cc::new(Vec::new()))
180 }189 }
190 #[must_use]
181 pub fn extend_from(&self, super_obj: Self) -> Self {191 pub fn extend_from(&self, super_obj: Self) -> Self {
182 match &self.0.super_obj {192 match &self.0.super_obj {
183 None => Self::new(193 None => Self::new(
201 ObjMemberBuilder::new(ExtendBuilder(self), name, FieldIndex::default())211 ObjMemberBuilder::new(ExtendBuilder(self), name, FieldIndex::default())
202 }212 }
213
214 #[must_use]
203 pub fn with_this(&self, this_obj: Self) -> Self {215 pub fn with_this(&self, this_obj: Self) -> Self {
204 Self(Cc::new(ObjValueInternals {216 Self(Cc::new(ObjValueInternals {
205 super_obj: self.0.super_obj.clone(),217 super_obj: self.0.super_obj.clone(),
222 if !self.0.this_entries.is_empty() {234 if !self.0.this_entries.is_empty() {
223 return false;235 return false;
224 }236 }
225 self.0237 self.0.super_obj.as_ref().map_or(true, Self::is_empty)
226 .super_obj
227 .as_ref()
228 .map(|s| s.is_empty())
229 .unwrap_or(true)
230 }238 }
231239
232 /// Run callback for every field found in object240 /// Run callback for every field found in object
254 let new_sort_key = FieldSortKey::new(depth, member.original_index);262 let new_sort_key = FieldSortKey::new(depth, member.original_index);
255 match member.visibility {263 match member.visibility {
256 Visibility::Normal => {264 Visibility::Normal => {
257 let entry = out.entry(name.to_owned());265 let entry = out.entry(name.clone());
258 let v = entry.or_insert((true, new_sort_key));266 let v = entry.or_insert((true, new_sort_key));
259 v.1 = new_sort_key;267 v.1 = new_sort_key;
260 }268 }
261 Visibility::Hidden => {269 Visibility::Hidden => {
262 out.insert(name.to_owned(), (false, new_sort_key));270 out.insert(name.clone(), (false, new_sort_key));
263 }271 }
264 Visibility::Unhide => {272 Visibility::Unhide => {
265 out.insert(name.to_owned(), (true, new_sort_key));273 out.insert(name.clone(), (true, new_sort_key));
266 }274 }
267 };275 };
268 false276 false
356 }364 }
357 pub fn has_field(&self, name: IStr) -> bool {365 pub fn has_field(&self, name: IStr) -> bool {
358 self.field_visibility(name)366 self.field_visibility(name)
359 .map(|v| v.is_visible())367 .map_or(false, |v| v.is_visible())
360 .unwrap_or(false)
361 }368 }
362369
363 pub fn get(&self, s: State, key: IStr) -> Result<Option<Val>> {370 pub fn get(&self, s: State, key: IStr) -> Result<Option<Val>> {
459impl Eq for ObjValue {}466impl Eq for ObjValue {}
460impl Hash for ObjValue {467impl Hash for ObjValue {
461 fn hash<H: Hasher>(&self, hasher: &mut H) {468 fn hash<H: Hasher>(&self, hasher: &mut H) {
462 hasher.write_usize(&*self.0 as *const _ as usize)469 hasher.write_usize(addr_of!(*self.0) as usize);
463 }470 }
464}471}
465472
473#[allow(clippy::module_name_repetitions)]
466pub struct ObjValueBuilder {474pub struct ObjValueBuilder {
467 super_obj: Option<ObjValue>,475 super_obj: Option<ObjValue>,
468 map: GcHashMap<IStr, ObjMember>,476 map: GcHashMap<IStr, ObjMember>,
510 }518 }
511}519}
512520
521#[allow(clippy::module_name_repetitions)]
513#[must_use = "value not added unless binding() was called"]522#[must_use = "value not added unless binding() was called"]
514pub struct ObjMemberBuilder<Kind> {523pub struct ObjMemberBuilder<Kind> {
515 kind: Kind,524 kind: Kind,
583 CallLocation(location.as_ref()),592 CallLocation(location.as_ref()),
584 || format!("field <{}> initializtion", name.clone()),593 || format!("field <{}> initializtion", name.clone()),
585 || throw!(DuplicateFieldName(name.clone())),594 || throw!(DuplicateFieldName(name.clone())),
586 )?595 )?;
587 }596 }
588 Ok(())597 Ok(())
589 }598 }
592pub struct ExtendBuilder<'v>(&'v mut ObjValue);601pub struct ExtendBuilder<'v>(&'v mut ObjValue);
593impl<'v> ObjMemberBuilder<ExtendBuilder<'v>> {602impl<'v> ObjMemberBuilder<ExtendBuilder<'v>> {
594 pub fn value(self, value: Val) {603 pub fn value(self, value: Val) {
595 self.binding(LazyBinding::Bound(LazyVal::new_resolved(value)))604 self.binding(LazyBinding::Bound(LazyVal::new_resolved(value)));
596 }605 }
597 pub fn bindable(self, bindable: TraceBox<dyn Bindable>) {606 pub fn bindable(self, bindable: TraceBox<dyn Bindable>) {
598 self.binding(LazyBinding::Bindable(Cc::new(bindable)))607 self.binding(LazyBinding::Bindable(Cc::new(bindable)));
599 }608 }
600 pub fn binding(self, binding: LazyBinding) {609 pub fn binding(self, binding: LazyBinding) {
601 let (receiver, name, member) = self.build_member(binding);610 let (receiver, name, member) = self.build_member(binding);
602 let new = receiver.0.clone();611 let new = receiver.0.clone();
603 *receiver.0 = new.extend_with_raw_member(name, member)612 *receiver.0 = new.extend_with_raw_member(name, member);
604 }613 }
605}614}
606615
modifiedcrates/jrsonnet-evaluator/src/trace/location.rsdiffbeforeafterboth
1#[allow(clippy::module_name_repetitions)]
1#[derive(Clone, PartialEq, Debug)]2#[derive(Clone, PartialEq, Debug)]
2pub struct CodeLocation {3pub struct CodeLocation {
3 pub offset: usize,4 pub offset: usize,
9 pub line_end_offset: usize,10 pub line_end_offset: usize,
10}11}
1112
13#[allow(clippy::module_name_repetitions)]
12pub fn location_to_offset(mut file: &str, mut line: usize, column: usize) -> Option<usize> {14pub fn location_to_offset(mut file: &str, mut line: usize, column: usize) -> Option<usize> {
13 let mut offset = 0;15 let mut offset = 0;
14 while line > 1 {16 while line > 1 {
21 Some(offset)23 Some(offset)
22}24}
2325
26#[allow(clippy::module_name_repetitions)]
24pub fn offset_to_location(file: &str, offsets: &[usize]) -> Vec<CodeLocation> {27pub fn offset_to_location(file: &str, offsets: &[usize]) -> Vec<CodeLocation> {
25 if offsets.is_empty() {28 if offsets.is_empty() {
26 return vec![];29 return vec![];
27 }30 }
28 let mut line = 1;31 let mut line = 1;
29 let mut column = 1;32 let mut column = 1;
30 let max_offset = *offsets.iter().max().unwrap();33 let max_offset = *offsets.iter().max().expect("offsets is not empty");
3134
32 let mut offset_map = offsets35 let mut offset_map = offsets
33 .iter()36 .iter()
modifiedcrates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth
19impl PathResolver {19impl PathResolver {
20 pub fn resolve(&self, from: &Path) -> String {20 pub fn resolve(&self, from: &Path) -> String {
21 match self {21 match self {
22 Self::FileName => from.file_name().unwrap().to_string_lossy().into_owned(),22 Self::FileName => from
23 .file_name()
24 .expect("file name exists")
25 .to_string_lossy()
26 .into_owned(),
23 Self::Absolute => from.to_string_lossy().into_owned(),27 Self::Absolute => from.to_string_lossy().into_owned(),
26 return from.to_string_lossy().into_owned();30 return from.to_string_lossy().into_owned();
27 }31 }
28 pathdiff::diff_paths(from, base)32 pathdiff::diff_paths(from, base)
29 .unwrap()33 .expect("base is absolute")
30 .to_string_lossy()34 .to_string_lossy()
31 .into_owned()35 .into_owned()
32 }36 }
35}39}
3640
37/// Implements pretty-printing of traces41/// Implements pretty-printing of traces
42#[allow(clippy::module_name_repetitions)]
38pub trait TraceFormat {43pub trait TraceFormat {
39 fn write_trace(44 fn write_trace(
40 &self,45 &self,
88 error,93 error,
89 } = error.error()94 } = error.error()
90 {95 {
91 writeln!(out)?;
92 use std::fmt::Write;96 use std::fmt::Write;
97
98 writeln!(out)?;
93 let mut n = self.resolver.resolve(path);99 let mut n = self.resolver.resolve(path);
94 let mut offset = error.location.offset;100 let mut offset = error.location.offset;
95 let is_eof = if offset >= source_code.len() {101 let is_eof = if offset >= source_code.len() {
134 let align = file_names140 let align = file_names
135 .iter()141 .iter()
136 .flatten()142 .flatten()
137 .map(|e| e.len())143 .map(String::len)
138 .max()144 .max()
139 .unwrap_or(0);145 .unwrap_or(0);
140 for (el, file) in error.trace().0.iter().zip(file_names) {146 for (el, file) in error.trace().0.iter().zip(file_names) {
166 error: &LocError,172 error: &LocError,
167 ) -> Result<(), std::fmt::Error> {173 ) -> Result<(), std::fmt::Error> {
168 write!(out, "{}", error.error())?;174 write!(out, "{}", error.error())?;
169 for item in error.trace().0.iter() {175 for item in &error.trace().0 {
170 writeln!(out)?;176 writeln!(out)?;
171 let desc = &item.desc;177 let desc = &item.desc;
172 if let Some(source) = &item.location {178 if let Some(source) = &item.location {
227 )?;233 )?;
228 }234 }
229 let trace = &error.trace();235 let trace = &error.trace();
230 for item in trace.0.iter() {236 for item in &trace.0 {
231 writeln!(out)?;237 writeln!(out)?;
232 let desc = &item.desc;238 let desc = &item.desc;
233 if let Some(source) = &item.location {239 if let Some(source) = &item.location {
273 let snippet = Snippet {279 let snippet = Snippet {
274 opt: FormatOptions {280 opt: FormatOptions {
275 color: true,281 color: true,
276 ..Default::default()282 ..FormatOptions::default()
277 },283 },
278 title: None,284 title: None,
279 footer: vec![],285 footer: vec![],
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
38 <Self as Typed>::TYPE.check(s, &value)?;38 <Self as Typed>::TYPE.check(s, &value)?;
39 match value {39 match value {
40 Val::Num(n) => {40 Val::Num(n) => {
41 #[allow(clippy::float_cmp)]
41 if n.trunc() != n {42 if n.trunc() != n {
42 throw!(RuntimeError(43 throw!(RuntimeError(
43 format!(44 format!(
95 <Self as Typed>::TYPE.check(s, &value)?;96 <Self as Typed>::TYPE.check(s, &value)?;
96 match value {97 match value {
97 Val::Num(n) => {98 Val::Num(n) => {
99 #[allow(clippy::float_cmp)]
98 if n.trunc() != n {100 if n.trunc() != n {
99 throw!(RuntimeError(101 throw!(RuntimeError(
100 format!(102 format!(
160impl Typed for usize {162impl Typed for usize {
161 // It is possible to store 54 bits of precision in f64, but leaving u32::MAX here for compatibility163 // It is possible to store 54 bits of precision in f64, but leaving u32::MAX here for compatibility
162 const TYPE: &'static ComplexValType =164 const TYPE: &'static ComplexValType =
163 &ComplexValType::BoundedNumber(Some(0.0), Some(4294967295.0));165 &ComplexValType::BoundedNumber(Some(0.0), Some(u32::MAX as f64));
164166
165 fn into_untyped(value: Self, _: State) -> Result<Val> {167 fn into_untyped(value: Self, _: State) -> Result<Val> {
166 if value > u32::MAX as Self {168 if value > u32::MAX as Self {
173 <Self as Typed>::TYPE.check(s, &value)?;175 <Self as Typed>::TYPE.check(s, &value)?;
174 match value {176 match value {
175 Val::Num(n) => {177 Val::Num(n) => {
178 #[allow(clippy::float_cmp)]
176 if n.trunc() != n {179 if n.trunc() != n {
177 throw!(RuntimeError(180 throw!(RuntimeError(
178 "cannot convert number with fractional part to usize".into()181 "cannot convert number with fractional part to usize".into()
263}266}
264267
265/// To be used in Vec<Any>268/// To be used in Vec<Any>
266/// Regular Val can't be used here, because it has wrong TryFrom::Error type269/// Regular Val can't be used here, because it has wrong `TryFrom::Error` type
267#[derive(Clone)]270#[derive(Clone)]
268pub struct Any(pub Val);271pub struct Any(pub Val);
269272
279 }282 }
280}283}
281284
282/// Specialization, provides faster TryFrom<VecVal> for Val285/// Specialization, provides faster `TryFrom<VecVal>` for Val
283pub struct VecVal(pub Cc<Vec<Val>>);286pub struct VecVal(pub Cc<Vec<Val>>);
284287
285impl Typed for VecVal {288impl Typed for VecVal {
310 }313 }
311314
312 fn from_untyped(value: Val, s: State) -> Result<Self> {315 fn from_untyped(value: Val, s: State) -> Result<Self> {
313 match value {316 if let Val::Arr(ArrValue::Bytes(bytes)) = value {
314 Val::Arr(ArrValue::Bytes(bytes)) => Ok(Self(bytes)),317 return Ok(Self(bytes));
315 _ => {318 }
316 <Self as Typed>::TYPE.check(s.clone(), &value)?;319 <Self as Typed>::TYPE.check(s.clone(), &value)?;
317 match value {320 match value {
318 Val::Arr(a) => {321 Val::Arr(a) => {
325 }328 }
326 _ => unreachable!(),329 _ => unreachable!(),
327 }330 }
328 }
329 }
330 }331 }
331}332}
332333
modifiedcrates/jrsonnet-evaluator/src/typed/mod.rsdiffbeforeafterboth
71 if line.trim().is_empty() {71 if line.trim().is_empty() {
72 continue;72 continue;
73 }73 }
74 if i != 0 {74 if i == 0 {
75 writeln!(f)?;
76 write!(f, " ")?;75 write!(f, " - ")?;
77 } else {76 } else {
77 writeln!(f)?;
78 write!(f, " - ")?;78 write!(f, " ")?;
79 }79 }
80 write!(f, "{}", line)?;80 write!(f, "{}", line)?;
81 }81 }
94 Ok(_) => Ok(()),94 Ok(_) => Ok(()),
95 Err(mut e) => {95 Err(mut e) => {
96 if let Error::TypeError(e) = &mut e.error_mut() {96 if let Error::TypeError(e) = &mut e.error_mut() {
97 (e.1).0.push(path())97 (e.1).0.push(path());
98 }98 }
99 Err(e)99 Err(e)
100 }100 }
145}145}
146146
147impl CheckType for ComplexValType {147impl CheckType for ComplexValType {
148 #[allow(clippy::too_many_lines)]
148 fn check(&self, s: State, value: &Val) -> Result<()> {149 fn check(&self, s: State, value: &Val) -> Result<()> {
149 match self {150 match self {
150 Self::Any => Ok(()),151 Self::Any => Ok(()),
202 || format!("property {}", k),203 || format!("property {}", k),
203 || ValuePathItem::Field((*k).into()),204 || ValuePathItem::Field((*k).into()),
204 || v.check(s.clone(), &got_v),205 || v.check(s.clone(), &got_v),
205 )?206 )?;
206 } else {207 } else {
207 return Err(208 return Err(
208 TypeError::MissingProperty((*k).into(), self.clone()).into()209 TypeError::MissingProperty((*k).into(), self.clone()).into()
245 }246 }
246 Self::Sum(types) => {247 Self::Sum(types) => {
247 for ty in types.iter() {248 for ty in types.iter() {
248 ty.check(s.clone(), value)?249 ty.check(s.clone(), value)?;
249 }250 }
250 Ok(())251 Ok(())
251 }252 }
252 Self::SumRef(types) => {253 Self::SumRef(types) => {
253 for ty in types.iter() {254 for ty in types.iter() {
254 ty.check(s.clone(), value)?255 ty.check(s.clone(), value)?;
255 }256 }
256 Ok(())257 Ok(())
257 }258 }
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
32 Pending,32 Pending,
33}33}
3434
35#[allow(clippy::module_name_repetitions)]
35#[derive(Clone, Trace)]36#[derive(Clone, Trace)]
36pub struct LazyVal(Cc<RefCell<LazyValInternals>>);37pub struct LazyVal(Cc<RefCell<LazyValInternals>>);
37impl LazyVal {38impl LazyVal {
50 LazyValInternals::Computed(v) => return Ok(v.clone()),51 LazyValInternals::Computed(v) => return Ok(v.clone()),
51 LazyValInternals::Errored(e) => return Err(e.clone()),52 LazyValInternals::Errored(e) => return Err(e.clone()),
52 LazyValInternals::Pending => return Err(InfiniteRecursionDetected.into()),53 LazyValInternals::Pending => return Err(InfiniteRecursionDetected.into()),
53 _ => (),54 LazyValInternals::Waiting(..) => (),
54 };55 };
55 let value = if let LazyValInternals::Waiting(value) =56 let value = if let LazyValInternals::Waiting(value) =
56 std::mem::replace(&mut *self.0.borrow_mut(), LazyValInternals::Pending)57 std::mem::replace(&mut *self.0.borrow_mut(), LazyValInternals::Pending)
114 }115 }
115}116}
116117
118#[allow(clippy::module_name_repetitions)]
117#[derive(Trace, Clone)]119#[derive(Trace, Clone)]
118pub enum FuncVal {120pub enum FuncVal {
119 /// Plain function implemented in jsonnet121 /// Plain function implemented in jsonnet
225 let rem = diff % self.step();227 let rem = diff % self.step();
226 let div = diff / self.step();228 let div = diff / self.step();
227229
228 if rem != 0 {230 if rem == 0 {
229 div + 1231 div
230 } else {232 } else {
231 div233 div + 1
232 }234 }
233 }235 }
234}236}
249 Self::Eager(Cc::new(Vec::new()))251 Self::Eager(Cc::new(Vec::new()))
250 }252 }
253
254 /// # Panics
255 /// If a > b
251 pub fn new_range(a: i32, b: i32) -> Self {256 pub fn new_range(a: i32, b: i32) -> Self {
252 assert!(a <= b);257 assert!(a <= b);
253 Self::Range(a, b)258 Self::Range(a, b)
254 }259 }
255260
261 /// # Panics
262 /// If passed numbers are incorrect
263 #[must_use]
256 pub fn slice(self, from: Option<usize>, to: Option<usize>, step: Option<usize>) -> Self {264 pub fn slice(self, from: Option<usize>, to: Option<usize>, step: Option<usize>) -> Self {
257 let len = self.len();265 let len = self.len();
258 let from = from.unwrap_or(0);266 let from = from.unwrap_or(0);
289 match self {297 match self {
290 Self::Bytes(i) => i298 Self::Bytes(i) => i
291 .get(index)299 .get(index)
292 .map_or(Ok(None), |v| Ok(Some(Val::Num(*v as f64)))),300 .map_or(Ok(None), |v| Ok(Some(Val::Num(f64::from(*v))))),
293 Self::Lazy(vec) => {301 Self::Lazy(vec) => {
294 if let Some(v) = vec.get(index) {302 if let Some(v) = vec.get(index) {
295 Ok(Some(v.evaluate(s)?))303 Ok(Some(v.evaluate(s)?))
333 match self {341 match self {
334 Self::Bytes(i) => i342 Self::Bytes(i) => i
335 .get(index)343 .get(index)
336 .map(|b| LazyVal::new_resolved(Val::Num(*b as f64))),344 .map(|b| LazyVal::new_resolved(Val::Num(f64::from(*b)))),
337 Self::Lazy(vec) => vec.get(index).cloned(),345 Self::Lazy(vec) => vec.get(index).cloned(),
338 Self::Eager(vec) => vec.get(index).cloned().map(LazyVal::new_resolved),346 Self::Eager(vec) => vec.get(index).cloned().map(LazyVal::new_resolved),
339 Self::Extended(v) => {347 Self::Extended(v) => {
374 Self::Bytes(i) => {382 Self::Bytes(i) => {
375 let mut out = Vec::with_capacity(i.len());383 let mut out = Vec::with_capacity(i.len());
376 for v in i.iter() {384 for v in i.iter() {
377 out.push(Val::Num(*v as f64));385 out.push(Val::Num(f64::from(*v)));
378 }386 }
379 Cc::new(out)387 Cc::new(out)
380 }388 }
396 Self::Range(a, b) => {404 Self::Range(a, b) => {
397 let mut out = Vec::with_capacity(self.len());405 let mut out = Vec::with_capacity(self.len());
398 for i in *a..*b {406 for i in *a..*b {
399 out.push(Val::Num(i as f64));407 out.push(Val::Num(f64::from(i)));
400 }408 }
401 Cc::new(out)409 Cc::new(out)
402 }410 }
414 .take(v.to() - v.from())422 .take(v.to() - v.from())
415 .step_by(v.step())423 .step_by(v.step())
416 {424 {
417 out.push(v.evaluate(s.clone())?)425 out.push(v.evaluate(s.clone())?);
418 }426 }
419 Cc::new(out)427 Cc::new(out)
420 }428 }
423431
424 pub fn iter(&self, s: State) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {432 pub fn iter(&self, s: State) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {
425 (0..self.len()).map(move |idx| match self {433 (0..self.len()).map(move |idx| match self {
426 Self::Bytes(b) => Ok(Val::Num(b[idx] as f64)),434 Self::Bytes(b) => Ok(Val::Num(f64::from(b[idx]))),
427 Self::Lazy(l) => l[idx].evaluate(s.clone()),435 Self::Lazy(l) => l[idx].evaluate(s.clone()),
428 Self::Eager(e) => Ok(e[idx].clone()),436 Self::Eager(e) => Ok(e[idx].clone()),
429 Self::Extended(_) => self.get(s.clone(), idx).map(|e| e.unwrap()),
430 Self::Range(..) => self.get(s.clone(), idx).map(|e| e.unwrap()),437 Self::Extended(..) | Self::Range(..) | Self::Reversed(..) | Self::Slice(..) => {
431 Self::Reversed(..) => self.get(s.clone(), idx).map(|e| e.unwrap()),
432 Self::Slice(..) => self.get(s.clone(), idx).map(|e| e.unwrap()),438 self.get(s.clone(), idx).map(|e| e.expect("idx < len"))
439 }
433 })440 })
434 }441 }
435442
436 pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {443 pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {
437 (0..self.len()).map(move |idx| match self {444 (0..self.len()).map(move |idx| match self {
438 Self::Bytes(b) => LazyVal::new_resolved(Val::Num(b[idx] as f64)),445 Self::Bytes(b) => LazyVal::new_resolved(Val::Num(f64::from(b[idx]))),
439 Self::Lazy(l) => l[idx].clone(),446 Self::Lazy(l) => l[idx].clone(),
440 Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),447 Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),
441 Self::Extended(_) => self.get_lazy(idx).unwrap(),
442 Self::Range(..) => self.get_lazy(idx).unwrap(),448 Self::Slice(..) | Self::Extended(..) | Self::Range(..) | Self::Reversed(..) => {
443 Self::Reversed(..) => self.get_lazy(idx).unwrap(),
444 Self::Slice(..) => self.get_lazy(idx).unwrap(),449 self.get_lazy(idx).expect("idx < len")
450 }
445 })451 })
446 }452 }
447453
454 #[must_use]
448 pub fn reversed(self) -> Self {455 pub fn reversed(self) -> Self {
449 Self::Reversed(Box::new(self))456 Self::Reversed(Box::new(self))
450 }457 }
493 }500 }
494}501}
495502
503#[allow(clippy::module_name_repetitions)]
496pub enum IndexableVal {504pub enum IndexableVal {
497 Str(IStr),505 Str(IStr),
498 Arr(ArrValue),506 Arr(ArrValue),
708 preserve_order,716 preserve_order,
709 },717 },
710 )718 )
711 .map(|s| s.into())719 .map(Into::into)
712 }720 }
713721
714 /// Calls `std.manifestJson`722 /// Calls `std.manifestJson`
730 preserve_order,738 preserve_order,
731 },739 },
732 )740 )
733 .map(|s| s.into())741 .map(Into::into)
734 }742 }
735743
736 pub fn to_yaml(744 pub fn to_yaml(
751 preserve_order,759 preserve_order,
752 },760 },
753 )761 )
754 .map(|s| s.into())762 .map(Into::into)
755 }763 }
756 pub fn into_indexable(self) -> Result<IndexableVal> {764 pub fn into_indexable(self) -> Result<IndexableVal> {
757 Ok(match self {765 Ok(match self {
824 for field in fields {832 for field in fields {
825 if !equals(833 if !equals(
826 s.clone(),834 s.clone(),
827 &a.get(s.clone(), field.clone())?.unwrap(),835 &a.get(s.clone(), field.clone())?.expect("field exists"),
828 &b.get(s.clone(), field)?.unwrap(),836 &b.get(s.clone(), field)?.expect("field exists"),
829 )? {837 )? {
830 return Ok(false);838 return Ok(false);
831 }839 }
modifiedcrates/jrsonnet-evaluator/tests/common.rsdiffbeforeafterboth
11 }};11 }};
12}12}
13
14#[macro_export]
15macro_rules! ensure {
16 ($v:expr $(,)?) => {
17 if !$v {
18 ::jrsonnet_evaluator::throw_runtime!("assertion failed: {}", stringify!($v))
19 }
20 };
21}
1322
14#[macro_export]23#[macro_export]
15macro_rules! ensure_val_eq {24macro_rules! ensure_val_eq {
addedcrates/jrsonnet-evaluator/tests/sanity.rsdiffbeforeafterboth

no changes

modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
157 });157 });
158 }158 }
159159
160 match &ty as &Type {160 match ty as &Type {
161 Type::Reference(r) if type_is_path(&r.elem, &name).is_some() => return Ok(Self::This),161 Type::Reference(r) if type_is_path(&r.elem, name).is_some() => return Ok(Self::This),
162 _ => {}162 _ => {}
163 }163 }
164164
465 "strategy should be set when flattening Option",465 "strategy should be set when flattening Option",
466 ));466 ));
467 }467 }
468 } else {468 } else if attr.flatten_ok {
469 if attr.flatten_ok {
470 return Err(Error::new(469 return Err(Error::new(
471 field.span(),470 field.span(),
472 "flatten(ok) is only useable on optional fields",471 "flatten(ok) is only useable on optional fields",
473 ));472 ));
474 }473 }
475 }474
476 Ok(Self {475 Ok(Self {
477 attr,476 attr,
478 ident,477 ident,