use core::fmt::{Binary, Display, Formatter, LowerExp, LowerHex, Octal, Pointer, Result, UpperExp, UpperHex};
use core::ops::Bound;
use crate::{Domain, Ranges};
macro_rules! format_ranges_with {
($($t:ident),+) => {
$(
/// Non-Debug formatting uses interval notation and formats the bound values
/// according to the given formatting arguments.
///
/// # Note
/// Unless disabled by using the `-` formatting argument, a whitespace will be printed
/// after the bound separator.
/// Because there is currently no use for `-`, it will have no effect on the underlying
/// bound values. This might change if requested or core/std makes use of it.
/// # Examples
/// Single entries. These are formatted like a single `GenericRange`.
/// ```
/// use ranges::Ranges;
///
/// assert_eq!(format!("{}", Ranges::from(1..2)), "{1}");
/// assert_eq!(format!("{}", Ranges::from(1..=2)), "[1, 2]");
/// assert_eq!(format!("{}", Ranges::from(42..)), "[42, 2147483647]");
/// assert_eq!(format!("{:03}", Ranges::from(1..2)), "{001}");
/// assert_eq!(format!("{:02X}", Ranges::from(1..=10)), "[01, 0A]");
/// assert_eq!(format!("{:-#}", Ranges::from(42..=100)), "[42,100]");
/// ```
/// Multiple entries. `∅` is used for an empty set and `∪` is used to concatenate
/// disjoint entries.
/// ```
/// use ranges::Ranges;
///
/// let mut ranges = Ranges::from(..6);
/// ranges.insert(7..=7);
/// ranges.insert(9..=9);
/// ranges.insert(15..);
/// assert_eq!(
/// format!("{}", ranges),
/// "[-2147483648, 6) \u{222a} {7, 9} \u{222a} [15, 2147483647]"
/// );
/// ```
#[allow(clippy::panic_in_result_fn)]
impl<T: $t + Domain> $t for Ranges<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let amount = self.ranges.len();
match amount {
0 => f.write_str("\u{2205}"), // ∅
1 => self.ranges.first().expect("single-element vec has no .first()").fmt(f),
_ => {
let mut singleton_last = false;
for (i, range) in self.ranges.iter().enumerate() {
if range.is_singleton() {
if singleton_last {
f.write_str(",")?;
if !f.sign_minus() {
f.write_str(" ")?;
}
} else {
f.write_str("{")?;
}
match (&range.start, &range.end) {
(&Bound::Included(ref v), &Bound::Excluded(_))
| (&Bound::Excluded(_), &Bound::Included(ref v))
| (&Bound::Included(ref v), &Bound::Included(_)) => {
(*v).fmt(f)
},
(&Bound::Excluded(ref v), &Bound::Excluded(_)) => {
let succ = v.successor().expect("open singleton has no successor");
succ.fmt(f)
},
(&Bound::Unbounded, _) |(_, &Bound::Unbounded) => unreachable!("singleton is unbounded"),
}?;
singleton_last = true;
} else {
if singleton_last {
f.write_str("}")?;
f.write_str(" \u{222a} ")?; // ∪
}
range.fmt(f)?;
#[allow(clippy::integer_arithmetic)]
if i != amount - 1 {
f.write_str(" \u{222a} ")?; // ∪
singleton_last = false;
}
}
}
Ok(())
},
}
}
}
)+
}
}
format_ranges_with!(Binary, Display, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex);
#[cfg(test)]
mod tests {
use alloc::format;
use core::ops::Bound;
use crate::Ranges;
#[test]
fn display() {
assert_eq!(format!("{}", Ranges::from(1..2)), "{1}");
assert_eq!(format!("{}", Ranges::from(1..=2)), "[1, 2]");
assert_eq!(format!("{}", Ranges::from(1..)), "[1, 2147483647]");
assert_eq!(format!("{}", Ranges::from(..2)), "[-2147483648, 2)");
assert_eq!(format!("{}", Ranges::from(..=2)), "[-2147483648, 2]");
let full: Ranges<usize> = Ranges::full();
assert_eq!(format!("{}", full), "[0, 18446744073709551615]");
assert_eq!(
format!("{}", Ranges::from((Bound::Excluded(1), Bound::Excluded(2)))),
"\u{2205}"
);
assert_eq!(
format!("{}", Ranges::from((Bound::Excluded(1), Bound::Included(2)))),
"{2}"
);
assert_eq!(
format!("{}", Ranges::from((Bound::Excluded(1), Bound::Unbounded))),
"(1, 2147483647]"
);
assert_eq!(format!("{:03}", Ranges::from(1..2)), "{001}");
assert_eq!(format!("{:02X}", Ranges::from(1..=10)), "[01, 0A]");
assert_eq!(format!("{:-#}", Ranges::from(42..=100)), "[42,100]");
}
#[test]
fn empty() {
assert_eq!(format!("{}", Ranges::<usize>::new()), "\u{2205}");
}
#[test]
fn multiple() {
let mut ranges = Ranges::from(..6);
ranges.insert(7..=7);
ranges.insert(9..=9);
ranges.insert(15..);
assert_eq!(
format!("{}", ranges),
"[-2147483648, 6) \u{222a} {7, 9} \u{222a} [15, 2147483647]"
);
assert_eq!(
format!("{:-}", ranges),
"[-2147483648,6) \u{222a} {7,9} \u{222a} [15,2147483647]"
);
}
}