1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use core::fmt::{Binary, Display, Formatter, LowerExp, LowerHex, Octal, Pointer, Result, UpperExp, UpperHex};
use core::ops::Bound;
use crate::{Domain, GenericRange};
macro_rules! format_range_with {
($($t:ident),+) => {
$(
impl<T: $t + Domain> $t for GenericRange<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
if self.is_singleton() {
f.write_str("{")?;
match (&self.start, &self.end) {
(Bound::Included(v), Bound::Excluded(_))
| (Bound::Excluded(_), Bound::Included(v))
| (Bound::Included(v), Bound::Included(_)) => {
(*v).fmt(f)
},
(Bound::Excluded(v), Bound::Excluded(_)) => {
let succ = (*v).successor().expect("open singleton has no successor");
(succ).fmt(f)
},
(Bound::Unbounded, _) |(_, Bound::Unbounded) => unreachable!("singleton is unbounded"),
}?;
f.write_str("}")
} else {
match &self.start {
Bound::Included(v) => {
f.write_str("[")?;
(*v).fmt(f)
}
Bound::Excluded(v) => {
f.write_str("(")?;
(*v).fmt(f)
}
Bound::Unbounded => f.write_str("(-inf"),
}?;
f.write_str(",")?;
if !f.sign_minus() {
f.write_str(" ")?;
}
match &self.end {
Bound::Included(v) => {
(*v).fmt(f)?;
f.write_str("]")
}
Bound::Excluded(v) => {
(*v).fmt(f)?;
f.write_str(")")
}
Bound::Unbounded => f.write_str("+inf)"),
}
}
}
}
)*
}
}
format_range_with!(Binary, Display, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex);
#[cfg(test)]
mod tests {
use alloc::format;
use core::ops::Bound;
use crate::GenericRange;
#[test]
fn display() {
assert_eq!(format!("{}", GenericRange::from(1..2)), "{1}");
assert_eq!(format!("{}", GenericRange::from(1..=2)), "[1, 2]");
assert_eq!(format!("{}", GenericRange::from(42..)), "[42, 2147483647]");
assert_eq!(format!("{}", GenericRange::from(..2)), "[-2147483648, 2)");
assert_eq!(format!("{}", GenericRange::from(..=2)), "[-2147483648, 2]");
let generic: GenericRange<usize> = GenericRange::from(..);
assert_eq!(format!("{}", generic), "[0, 18446744073709551615]");
assert_eq!(
format!("{}", GenericRange::from((Bound::Excluded(1), Bound::Excluded(2)))),
"(1, 2)"
);
assert_eq!(
format!("{}", GenericRange::from((Bound::Excluded(3), Bound::Excluded(5)))),
"{4}"
);
assert_eq!(
format!("{}", GenericRange::from((Bound::Excluded(1), Bound::Included(2)))),
"{2}"
);
assert_eq!(
format!("{}", GenericRange::from((Bound::Excluded(1), Bound::Unbounded))),
"(1, 2147483647]"
);
assert_eq!(format!("{:03}", GenericRange::from(1..2)), "{001}");
assert_eq!(format!("{:02X}", GenericRange::from(1..=10)), "[01, 0A]");
assert_eq!(format!("{:-#}", GenericRange::from(42..=100)), "[42,100]");
}
}