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

difftreelog

fix align std.format output with standard jsonnet changes

mykzwksoYaroslav Bolyukin2026-02-08parent: #c368769.patch.diff
in: master

4 files changed

modifiedcrates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth
225 if v2.get() < 0.0 {225 if v2.get() < 0.0 {
226 bail!("shift by negative exponent")226 bail!("shift by negative exponent")
227 }227 }
228 let base = v1.truncate_for_bitwise()?;
228 let exp = ((v2.get() as i64) & 63) as u32;229 let exp = v2.truncate_for_bitwise()? % 64;
230
231 if exp >= 1 && base >= (1i64 << (63 - exp as u32)) {
232 bail!("left shift would overflow")
233 }
229 Val::try_num((v1.get() as i64).wrapping_shl(exp) as f64)?234 Val::try_num(base.wrapping_shl(exp as u32) as f64)?
230 }235 }
231 (Num(v1), Rhs, Num(v2)) => {236 (Num(v1), Rhs, Num(v2)) => {
232 if v2.get() < 0.0 {237 if v2.get() < 0.0 {
233 bail!("shift by negative exponent")238 bail!("shift by negative exponent")
234 }239 }
235 let exp = ((v2.get() as i64) & 63) as u32;240 let exp = ((v2.get() as i64) & 63) as u32;
236 Val::try_num((v1.get() as i64).wrapping_shr(exp) as f64)?241 Val::try_num(v1.truncate_for_bitwise()?.wrapping_shr(exp) as f64)?
237 }242 }
238243
239 // Bigint X Bigint244 // Bigint X Bigint
modifiedcrates/jrsonnet-evaluator/src/stdlib/format.rsdiffbeforeafterboth
137#[derive(Debug, PartialEq, Eq)]137#[derive(Debug, PartialEq, Eq)]
138pub enum Width {138pub enum Width {
139 Star,139 Star,
140 Fixed(usize),140 Fixed(u16),
141}141}
142pub fn try_parse_field_width(str: &str) -> ParseResult<'_, Width> {142pub fn try_parse_field_width(str: &str) -> ParseResult<'_, Width> {
143 if str.is_empty() {143 if str.is_empty() {
147 if bytes[0] == b'*' {147 if bytes[0] == b'*' {
148 return Ok((Width::Star, &str[1..]));148 return Ok((Width::Star, &str[1..]));
149 }149 }
150 let mut out: usize = 0;150 let mut out: u16 = 0;
151 let mut digits = 0;151 let mut digits = 0;
152 while let Some(digit) = (bytes[digits] as char).to_digit(10) {152 while let Some(digit) = (bytes[digits] as char).to_digit(10) {
153 out *= 10;153 out *= 10;
154 out += digit as usize;154 out += digit as u16;
155 digits += 1;155 digits += 1;
156 if digits == bytes.len() {156 if digits == bytes.len() {
157 return Err(TruncatedFormatCode);157 return Err(TruncatedFormatCode);
299#[inline]299#[inline]
300pub fn render_integer(300pub fn render_integer(
301 out: &mut String,301 out: &mut String,
302 neg: bool,
302 iv: f64,303 iv: f64,
303 padding: usize,304 padding: u16,
304 precision: usize,305 precision: u16,
305 blank: bool,306 blank: bool,
306 sign: bool,307 sign: bool,
307 radix: i64,308 radix: i64,
308 prefix: &str,309 zero_prefix: &str,
310 prefix_in_padding: bool,
309 caps: bool,311 caps: bool,
310) {312) {
313 debug_assert!(iv >= 0.0, "render_integer receives sign using arg");
311 let iv = iv.floor() as i64;314 let iv = iv.floor() as i64;
312 // Digit char indexes in reverse order, i.e315 // Digit char indexes in reverse order, i.e
313 // for radix = 16 and n = 12f: [15, 2, 1]316 // for radix = 16 and n = 12f: [15, 2, 1]
322 }325 }
323 nums326 nums
324 };327 };
325 let neg = iv < 0;
326 #[allow(clippy::bool_to_int_with_if)]328 #[allow(clippy::bool_to_int_with_if)]
327 let zp = padding.saturating_sub(if neg || blank || sign { 1 } else { 0 });329 let zp = padding.saturating_sub(if neg || blank || sign { 1 } else { 0 });
330
331 let pref_len = zero_prefix.len() as u16;
328 let zp2 = zp332 let zp2 = zp
333 .saturating_sub(if !prefix_in_padding { pref_len } else { 0 })
329 .max(precision)334 .max(precision)
330 .saturating_sub(prefix.len() + digits.len());335 .saturating_sub(if prefix_in_padding { pref_len } else { 0 } + digits.len() as u16);
331336
332 if neg {337 if neg {
333 out.push('-');338 out.push('-');
337 out.push(' ');342 out.push(' ');
338 }343 }
339344
340 out.reserve(zp2);345 out.reserve(zp2 as usize);
346 if iv != 0 {
347 out.push_str(zero_prefix);
348 }
341 for _ in 0..zp2 {349 for _ in 0..zp2 {
342 out.push('0');350 out.push('0');
343 }351 }
344 out.push_str(prefix);
345352
346 for digit in digits.into_iter().rev() {353 for digit in digits.into_iter().rev() {
347 let ch = NUMBERS[digit as usize] as char;354 let ch = NUMBERS[digit as usize] as char;
351358
352pub fn render_decimal(359pub fn render_decimal(
353 out: &mut String,360 out: &mut String,
361 neg: bool,
354 iv: f64,362 iv: f64,
355 padding: usize,363 padding: u16,
356 precision: usize,364 precision: u16,
357 blank: bool,365 blank: bool,
358 sign: bool,366 sign: bool,
359) {367) {
360 render_integer(out, iv, padding, precision, blank, sign, 10, "", false);368 render_integer(
369 out, neg, iv, padding, precision, blank, sign, 10, "", false, false,
370 );
361}371}
362pub fn render_octal(372pub fn render_octal(
363 out: &mut String,373 out: &mut String,
374 neg: bool,
364 iv: f64,375 iv: f64,
365 padding: usize,376 padding: u16,
366 precision: usize,377 precision: u16,
367 alt: bool,378 alt: bool,
368 blank: bool,379 blank: bool,
369 sign: bool,380 sign: bool,
370) {381) {
371 render_integer(382 render_integer(
372 out,383 out,
384 neg,
373 iv,385 iv,
374 padding,386 padding,
375 precision,387 precision,
376 blank,388 blank,
377 sign,389 sign,
378 8,390 8,
379 if alt && iv != 0.0 { "0" } else { "" },391 if alt && iv != 0.0 { "0" } else { "" },
392 true,
380 false,393 false,
381 );394 );
382}395}
385pub fn render_hexadecimal(398pub fn render_hexadecimal(
386 out: &mut String,399 out: &mut String,
387 iv: f64,400 iv: f64,
388 padding: usize,401 padding: u16,
389 precision: usize,402 precision: u16,
390 alt: bool,403 alt: bool,
391 blank: bool,404 blank: bool,
392 sign: bool,405 sign: bool,
393 caps: bool,406 caps: bool,
394) {407) {
395 render_integer(408 render_integer(
396 out,409 out,
397 iv,410 iv < 0.0,
411 iv.abs(),
398 padding,412 padding,
399 precision,413 precision,
400 blank,414 blank,
405 (true, false) => "0x",419 (true, false) => "0x",
406 (false, _) => "",420 (false, _) => "",
407 },421 },
422 false,
408 caps,423 caps,
409 );424 );
410}425}
413pub fn render_float(428pub fn render_float(
414 out: &mut String,429 out: &mut String,
415 n: f64,430 n: f64,
416 mut padding: usize,431 mut padding: u16,
417 precision: usize,432 precision: u16,
418 blank: bool,433 blank: bool,
419 sign: bool,434 sign: bool,
420 ensure_pt: bool,435 ensure_pt: bool,
421 trailing: bool,436 trailing: bool,
422) {437) {
438 // Represent the rounded number as an integer * 1/10**prec.
439 // Note that it can also be equal to 10**prec and we'll need to carry
440 // over to the wholes. We operate on the absolute numbers, so that we
441 // don't have trouble with the rounding direction.
442 let denominator = 10.0f64.powi(precision as i32);
443 let numerator = n.abs() * denominator + 0.5;
444 let whole = (numerator / denominator).floor();
445 let frac = numerator.floor() % denominator;
446
423 #[allow(clippy::bool_to_int_with_if)]447 #[allow(clippy::bool_to_int_with_if)]
424 let dot_size = if precision == 0 && !ensure_pt { 0 } else { 1 };448 let dot_size = if precision == 0 && !ensure_pt { 0 } else { 1 };
425 padding = padding.saturating_sub(dot_size + precision);449 padding = padding.saturating_sub(dot_size + precision);
426 render_decimal(out, n.floor(), padding, 0, blank, sign);450 render_decimal(out, n < 0.0, whole, padding, 0, blank, sign);
427 if precision == 0 {451 if precision == 0 {
428 if ensure_pt {452 if ensure_pt {
429 out.push('.');453 out.push('.');
430 }454 }
431 return;455 return;
432 }456 }
433 let frac = n
434 .fract()
435 .mul_add(10.0_f64.powf(precision as f64), 0.5)
436 .floor();
437 if trailing || frac > 0.0 {457 if trailing || frac > 0.0 {
438 out.push('.');458 out.push('.');
439 let mut frac_str = String::new();459 let mut frac_str = String::new();
440 render_decimal(&mut frac_str, frac, precision, 0, false, false);460 render_decimal(&mut frac_str, false, frac, precision, 0, false, false);
441 let mut trim = frac_str.len();461 let mut trim = frac_str.len();
442 if !trailing {462 if !trailing {
443 for b in frac_str.as_bytes().iter().rev() {463 for b in frac_str.as_bytes().iter().rev() {
458pub fn render_float_sci(478pub fn render_float_sci(
459 out: &mut String,479 out: &mut String,
460 n: f64,480 n: f64,
461 mut padding: usize,481 mut padding: u16,
462 precision: usize,482 precision: u16,
463 blank: bool,483 blank: bool,
464 sign: bool,484 sign: bool,
465 ensure_pt: bool,485 ensure_pt: bool,
466 trailing: bool,486 trailing: bool,
467 caps: bool,487 caps: bool,
468) {488) {
469 let exponent = n.log10().floor();489 let exponent = if n == 0.0 {
490 0.0
491 } else {
492 n.abs().log10().floor()
493 };
494
470 let mantissa = if exponent as i16 == -324 {495 let mantissa = if exponent as i16 == -324 {
471 n * 10.0 / 10.0_f64.powf(exponent + 1.0)496 n * 10.0 / 10.0_f64.powf(exponent + 1.0)
472 } else {497 } else {
473 n / 10.0_f64.powf(exponent)498 n / 10.0_f64.powf(exponent)
474 };499 };
475 let mut exponent_str = String::new();500 let mut exponent_str = String::new();
476 render_decimal(&mut exponent_str, exponent, 3, 0, false, true);501 render_decimal(
502 &mut exponent_str,
503 exponent < 0.0,
504 exponent.abs(),
505 3,
506 0,
507 false,
508 true,
509 );
477510
478 // +1 for e511 // +1 for e
479 padding = padding.saturating_sub(exponent_str.len() + 1);512 padding = padding.saturating_sub(exponent_str.len() as u16 + 1);
480513
481 render_float(514 render_float(
482 out, mantissa, padding, precision, blank, sign, ensure_pt, trailing,515 out, mantissa, padding, precision, blank, sign, ensure_pt, trailing,
490 out: &mut String,523 out: &mut String,
491 value: &Val,524 value: &Val,
492 code: &Code<'_>,525 code: &Code<'_>,
493 width: usize,526 width: u16,
494 precision: Option<usize>,527 precision: Option<u16>,
495) -> Result<()> {528) -> Result<()> {
496 let clfags = &code.cflags;529 let clfags = &code.cflags;
497 let (fpprec, iprec) = precision.map_or((6, 0), |v| (v, v));530 let (fpprec, iprec) = precision.map_or((6, 0), |v| (v, v));
510 let value = f64::from_untyped(value.clone())?;543 let value = f64::from_untyped(value.clone())?;
511 render_decimal(544 render_decimal(
512 &mut tmp_out,545 &mut tmp_out,
513 value,546 value <= -1.0,
547 value.abs(),
514 padding,548 padding,
515 iprec,549 iprec,
516 clfags.blank,550 clfags.blank,
521 let value = f64::from_untyped(value.clone())?;555 let value = f64::from_untyped(value.clone())?;
522 render_octal(556 render_octal(
523 &mut tmp_out,557 &mut tmp_out,
524 value,558 value <= -1.0,
559 value.abs(),
525 padding,560 padding,
526 iprec,561 iprec,
527 clfags.alt,562 clfags.alt,
589 code.caps,624 code.caps,
590 );625 );
591 } else {626 } else {
592 let digits_before_pt = 1.max(exponent as usize + 1);627 let digits_before_pt = 1.max(exponent as u16 + 1);
593 render_float(628 render_float(
594 &mut tmp_out,629 &mut tmp_out,
595 value,630 value,
628 ConvTypeV::Percent => tmp_out.push('%'),663 ConvTypeV::Percent => tmp_out.push('%'),
629 };664 };
630665
631 let padding = width.saturating_sub(tmp_out.len());666 let padding = width.saturating_sub(tmp_out.len() as u16);
632667
633 if !clfags.left {668 if !clfags.left {
634 for _ in 0..padding {669 for _ in 0..padding {
663 }698 }
664 let value = &values[0];699 let value = &values[0];
665 values = &values[1..];700 values = &values[1..];
666 usize::from_untyped(value.clone())?701 u16::from_untyped(value.clone())?
667 }702 }
668 Width::Fixed(n) => n,703 Width::Fixed(n) => n,
669 };704 };
674 }709 }
675 let value = &values[0];710 let value = &values[0];
676 values = &values[1..];711 values = &values[1..];
677 Some(usize::from_untyped(value.clone())?)712 Some(u16::from_untyped(value.clone())?)
678 }713 }
679 Some(Width::Fixed(n)) => Some(n),714 Some(Width::Fixed(n)) => Some(n),
680 None => None,715 None => None,
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
120 }120 }
121}121}
122122
123pub const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS + 1)) - 1) as f64;123pub const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS)) - 1) as f64;
124pub const MIN_SAFE_INTEGER: f64 = -MAX_SAFE_INTEGER;124pub const MIN_SAFE_INTEGER: f64 = (-((1i64 << (f64::MANTISSA_DIGITS)) - 1)) as f64;
125125
126macro_rules! impl_int {126macro_rules! impl_int {
127 ($($ty:ty)*) => {$(127 ($($ty:ty)*) => {$(
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
22 function::FuncVal,22 function::FuncVal,
23 gc::WithCapacityExt as _,23 gc::WithCapacityExt as _,
24 manifest::{ManifestFormat, ToStringFormat},24 manifest::{ManifestFormat, ToStringFormat},
25 typed::BoundedUsize,25 typed::{BoundedUsize, MAX_SAFE_INTEGER, MIN_SAFE_INTEGER},
26 ObjValue, Result, Unbound, WeakObjValue,26 ObjValue, Result, Unbound, WeakObjValue,
27};27};
2828
418 pub const fn get(&self) -> f64 {418 pub const fn get(&self) -> f64 {
419 self.0419 self.0
420 }420 }
421 pub(crate) fn truncate_for_bitwise(&self) -> Result<i64> {
422 if self.0 < MIN_SAFE_INTEGER || self.0 > dbg!(MAX_SAFE_INTEGER) {
423 bail!("numberic value outside of safe integer range for bitwise operation");
424 }
425 Ok(self.0 as i64)
426 }
421}427}
422impl PartialEq for NumValue {428impl PartialEq for NumValue {
423 fn eq(&self, other: &Self) -> bool {429 fn eq(&self, other: &Self) -> bool {
490 type Error = ConvertNumValueError;496 type Error = ConvertNumValueError;
491 #[inline]497 #[inline]
492 fn try_from(value: $ty) -> Result<Self, ConvertNumValueError> {498 fn try_from(value: $ty) -> Result<Self, ConvertNumValueError> {
493 use crate::typed::conversions::{MIN_SAFE_INTEGER, MAX_SAFE_INTEGER};
494 let value = value as f64;499 let value = value as f64;
495 if value < MIN_SAFE_INTEGER {500 if value < MIN_SAFE_INTEGER {
496 return Err(ConvertNumValueError::Underflow)501 return Err(ConvertNumValueError::Underflow)