fix nuon conversions of range values (#14687)

# Description
Currently the step size of range values are discarded when converting to
nuon. This PR fixes that and makes `to nuon | from nuon` round trips
work.

# User-Facing Changes
`to nuon` conversion of `range` values now include the step size

# Tests + Formatting
Added some additional tests to cover inclusive/exclusive integer/float
and step size cases.
This commit is contained in:
Bahex
2025-01-07 23:29:39 +03:00
committed by GitHub
parent 8e41a308cd
commit 16e174be7e
5 changed files with 82 additions and 73 deletions

View File

@ -0,0 +1,16 @@
use std::fmt::Display;
/// A f64 wrapper that formats whole numbers with a decimal point.
pub struct ObviousFloat(pub f64);
impl Display for ObviousFloat {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let val = self.0;
// This serialises these as 'nan', 'inf' and '-inf', respectively.
if val.round() == val && val.is_finite() {
write!(f, "{}.0", val)
} else {
write!(f, "{}", val)
}
}
}

View File

@ -8,6 +8,7 @@ mod range;
#[cfg(test)]
mod test_derive;
pub mod format;
pub mod record;
pub use custom_value::CustomValue;
pub use duration::*;

View File

@ -183,12 +183,14 @@ mod int_range {
impl Display for IntRange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// what about self.step?
let start = self.start;
write!(f, "{}..", self.start)?;
if self.step != 1 {
write!(f, "{}..", self.start + self.step)?;
}
match self.end {
Bound::Included(end) => write!(f, "{start}..{end}"),
Bound::Excluded(end) => write!(f, "{start}..<{end}"),
Bound::Unbounded => write!(f, "{start}.."),
Bound::Included(end) => write!(f, "{end}"),
Bound::Excluded(end) => write!(f, "<{end}"),
Bound::Unbounded => Ok(()),
}
}
}
@ -228,7 +230,10 @@ mod int_range {
}
mod float_range {
use crate::{ast::RangeInclusion, IntRange, Range, ShellError, Signals, Span, Value};
use crate::{
ast::RangeInclusion, format::ObviousFloat, IntRange, Range, ShellError, Signals, Span,
Value,
};
use serde::{Deserialize, Serialize};
use std::{cmp::Ordering, fmt::Display, ops::Bound};
@ -434,12 +439,14 @@ mod float_range {
impl Display for FloatRange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// what about self.step?
let start = self.start;
write!(f, "{}..", ObviousFloat(self.start))?;
if self.step != 1f64 {
write!(f, "{}..", ObviousFloat(self.start + self.step))?;
}
match self.end {
Bound::Included(end) => write!(f, "{start}..{end}"),
Bound::Excluded(end) => write!(f, "{start}..<{end}"),
Bound::Unbounded => write!(f, "{start}.."),
Bound::Included(end) => write!(f, "{}", ObviousFloat(end)),
Bound::Excluded(end) => write!(f, "<{}", ObviousFloat(end)),
Bound::Unbounded => Ok(()),
}
}
}