difftreelog
fix align std.format output with standard jsonnet changes
in: master
4 files changed
crates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth225 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;230231 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 }238243239 // Bigint X Bigint244 // Bigint X Bigintcrates/jrsonnet-evaluator/src/stdlib/format.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/stdlib/format.rs
+++ b/crates/jrsonnet-evaluator/src/stdlib/format.rs
@@ -137,7 +137,7 @@
#[derive(Debug, PartialEq, Eq)]
pub enum Width {
Star,
- Fixed(usize),
+ Fixed(u16),
}
pub fn try_parse_field_width(str: &str) -> ParseResult<'_, Width> {
if str.is_empty() {
@@ -147,11 +147,11 @@
if bytes[0] == b'*' {
return Ok((Width::Star, &str[1..]));
}
- let mut out: usize = 0;
+ let mut out: u16 = 0;
let mut digits = 0;
while let Some(digit) = (bytes[digits] as char).to_digit(10) {
out *= 10;
- out += digit as usize;
+ out += digit as u16;
digits += 1;
if digits == bytes.len() {
return Err(TruncatedFormatCode);
@@ -299,15 +299,18 @@
#[inline]
pub fn render_integer(
out: &mut String,
+ neg: bool,
iv: f64,
- padding: usize,
- precision: usize,
+ padding: u16,
+ precision: u16,
blank: bool,
sign: bool,
radix: i64,
- prefix: &str,
+ zero_prefix: &str,
+ prefix_in_padding: bool,
caps: bool,
) {
+ debug_assert!(iv >= 0.0, "render_integer receives sign using arg");
let iv = iv.floor() as i64;
// Digit char indexes in reverse order, i.e
// for radix = 16 and n = 12f: [15, 2, 1]
@@ -322,12 +325,14 @@
}
nums
};
- let neg = iv < 0;
#[allow(clippy::bool_to_int_with_if)]
let zp = padding.saturating_sub(if neg || blank || sign { 1 } else { 0 });
+
+ let pref_len = zero_prefix.len() as u16;
let zp2 = zp
+ .saturating_sub(if !prefix_in_padding { pref_len } else { 0 })
.max(precision)
- .saturating_sub(prefix.len() + digits.len());
+ .saturating_sub(if prefix_in_padding { pref_len } else { 0 } + digits.len() as u16);
if neg {
out.push('-');
@@ -337,11 +342,13 @@
out.push(' ');
}
- out.reserve(zp2);
+ out.reserve(zp2 as usize);
+ if iv != 0 {
+ out.push_str(zero_prefix);
+ }
for _ in 0..zp2 {
out.push('0');
}
- out.push_str(prefix);
for digit in digits.into_iter().rev() {
let ch = NUMBERS[digit as usize] as char;
@@ -351,25 +358,30 @@
pub fn render_decimal(
out: &mut String,
+ neg: bool,
iv: f64,
- padding: usize,
- precision: usize,
+ padding: u16,
+ precision: u16,
blank: bool,
sign: bool,
) {
- render_integer(out, iv, padding, precision, blank, sign, 10, "", false);
+ render_integer(
+ out, neg, iv, padding, precision, blank, sign, 10, "", false, false,
+ );
}
pub fn render_octal(
out: &mut String,
+ neg: bool,
iv: f64,
- padding: usize,
- precision: usize,
+ padding: u16,
+ precision: u16,
alt: bool,
blank: bool,
sign: bool,
) {
render_integer(
out,
+ neg,
iv,
padding,
precision,
@@ -377,6 +389,7 @@
sign,
8,
if alt && iv != 0.0 { "0" } else { "" },
+ true,
false,
);
}
@@ -385,8 +398,8 @@
pub fn render_hexadecimal(
out: &mut String,
iv: f64,
- padding: usize,
- precision: usize,
+ padding: u16,
+ precision: u16,
alt: bool,
blank: bool,
sign: bool,
@@ -394,7 +407,8 @@
) {
render_integer(
out,
- iv,
+ iv < 0.0,
+ iv.abs(),
padding,
precision,
blank,
@@ -405,6 +419,7 @@
(true, false) => "0x",
(false, _) => "",
},
+ false,
caps,
);
}
@@ -413,31 +428,36 @@
pub fn render_float(
out: &mut String,
n: f64,
- mut padding: usize,
- precision: usize,
+ mut padding: u16,
+ precision: u16,
blank: bool,
sign: bool,
ensure_pt: bool,
trailing: bool,
) {
+ // Represent the rounded number as an integer * 1/10**prec.
+ // Note that it can also be equal to 10**prec and we'll need to carry
+ // over to the wholes. We operate on the absolute numbers, so that we
+ // don't have trouble with the rounding direction.
+ let denominator = 10.0f64.powi(precision as i32);
+ let numerator = n.abs() * denominator + 0.5;
+ let whole = (numerator / denominator).floor();
+ let frac = numerator.floor() % denominator;
+
#[allow(clippy::bool_to_int_with_if)]
let dot_size = if precision == 0 && !ensure_pt { 0 } else { 1 };
padding = padding.saturating_sub(dot_size + precision);
- render_decimal(out, n.floor(), padding, 0, blank, sign);
+ render_decimal(out, n < 0.0, whole, padding, 0, blank, sign);
if precision == 0 {
if ensure_pt {
out.push('.');
}
return;
}
- let frac = n
- .fract()
- .mul_add(10.0_f64.powf(precision as f64), 0.5)
- .floor();
if trailing || frac > 0.0 {
out.push('.');
let mut frac_str = String::new();
- render_decimal(&mut frac_str, frac, precision, 0, false, false);
+ render_decimal(&mut frac_str, false, frac, precision, 0, false, false);
let mut trim = frac_str.len();
if !trailing {
for b in frac_str.as_bytes().iter().rev() {
@@ -458,25 +478,38 @@
pub fn render_float_sci(
out: &mut String,
n: f64,
- mut padding: usize,
- precision: usize,
+ mut padding: u16,
+ precision: u16,
blank: bool,
sign: bool,
ensure_pt: bool,
trailing: bool,
caps: bool,
) {
- let exponent = n.log10().floor();
+ let exponent = if n == 0.0 {
+ 0.0
+ } else {
+ n.abs().log10().floor()
+ };
+
let mantissa = if exponent as i16 == -324 {
n * 10.0 / 10.0_f64.powf(exponent + 1.0)
} else {
n / 10.0_f64.powf(exponent)
};
let mut exponent_str = String::new();
- render_decimal(&mut exponent_str, exponent, 3, 0, false, true);
+ render_decimal(
+ &mut exponent_str,
+ exponent < 0.0,
+ exponent.abs(),
+ 3,
+ 0,
+ false,
+ true,
+ );
// +1 for e
- padding = padding.saturating_sub(exponent_str.len() + 1);
+ padding = padding.saturating_sub(exponent_str.len() as u16 + 1);
render_float(
out, mantissa, padding, precision, blank, sign, ensure_pt, trailing,
@@ -490,8 +523,8 @@
out: &mut String,
value: &Val,
code: &Code<'_>,
- width: usize,
- precision: Option<usize>,
+ width: u16,
+ precision: Option<u16>,
) -> Result<()> {
let clfags = &code.cflags;
let (fpprec, iprec) = precision.map_or((6, 0), |v| (v, v));
@@ -510,7 +543,8 @@
let value = f64::from_untyped(value.clone())?;
render_decimal(
&mut tmp_out,
- value,
+ value <= -1.0,
+ value.abs(),
padding,
iprec,
clfags.blank,
@@ -521,7 +555,8 @@
let value = f64::from_untyped(value.clone())?;
render_octal(
&mut tmp_out,
- value,
+ value <= -1.0,
+ value.abs(),
padding,
iprec,
clfags.alt,
@@ -589,7 +624,7 @@
code.caps,
);
} else {
- let digits_before_pt = 1.max(exponent as usize + 1);
+ let digits_before_pt = 1.max(exponent as u16 + 1);
render_float(
&mut tmp_out,
value,
@@ -628,7 +663,7 @@
ConvTypeV::Percent => tmp_out.push('%'),
};
- let padding = width.saturating_sub(tmp_out.len());
+ let padding = width.saturating_sub(tmp_out.len() as u16);
if !clfags.left {
for _ in 0..padding {
@@ -663,7 +698,7 @@
}
let value = &values[0];
values = &values[1..];
- usize::from_untyped(value.clone())?
+ u16::from_untyped(value.clone())?
}
Width::Fixed(n) => n,
};
@@ -674,7 +709,7 @@
}
let value = &values[0];
values = &values[1..];
- Some(usize::from_untyped(value.clone())?)
+ Some(u16::from_untyped(value.clone())?)
}
Some(Width::Fixed(n)) => Some(n),
None => None,
crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed/conversions.rs
+++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs
@@ -120,8 +120,8 @@
}
}
-pub const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS + 1)) - 1) as f64;
-pub const MIN_SAFE_INTEGER: f64 = -MAX_SAFE_INTEGER;
+pub const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS)) - 1) as f64;
+pub const MIN_SAFE_INTEGER: f64 = (-((1i64 << (f64::MANTISSA_DIGITS)) - 1)) as f64;
macro_rules! impl_int {
($($ty:ty)*) => {$(
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -22,7 +22,7 @@
function::FuncVal,
gc::WithCapacityExt as _,
manifest::{ManifestFormat, ToStringFormat},
- typed::BoundedUsize,
+ typed::{BoundedUsize, MAX_SAFE_INTEGER, MIN_SAFE_INTEGER},
ObjValue, Result, Unbound, WeakObjValue,
};
@@ -418,6 +418,12 @@
pub const fn get(&self) -> f64 {
self.0
}
+ pub(crate) fn truncate_for_bitwise(&self) -> Result<i64> {
+ if self.0 < MIN_SAFE_INTEGER || self.0 > dbg!(MAX_SAFE_INTEGER) {
+ bail!("numberic value outside of safe integer range for bitwise operation");
+ }
+ Ok(self.0 as i64)
+ }
}
impl PartialEq for NumValue {
fn eq(&self, other: &Self) -> bool {
@@ -490,7 +496,6 @@
type Error = ConvertNumValueError;
#[inline]
fn try_from(value: $ty) -> Result<Self, ConvertNumValueError> {
- use crate::typed::conversions::{MIN_SAFE_INTEGER, MAX_SAFE_INTEGER};
let value = value as f64;
if value < MIN_SAFE_INTEGER {
return Err(ConvertNumValueError::Underflow)