1 use super::*;
2
3 use crate::Flags;
4
5 #[test]
6 #[cfg(not(miri))] // Very slow in miri
roundtrip()7 fn roundtrip() {
8 for a in 0u8..=255 {
9 for b in 0u8..=255 {
10 let f = TestFlags::from_bits_retain(a | b);
11
12 assert_eq!(f, f.iter().collect::<TestFlags>());
13 assert_eq!(
14 TestFlags::from_bits_truncate(f.bits()),
15 f.iter_names().map(|(_, f)| f).collect::<TestFlags>()
16 );
17
18 let f = TestExternal::from_bits_retain(a | b);
19
20 assert_eq!(f, f.iter().collect::<TestExternal>());
21 }
22 }
23 }
24
25 mod collect {
26 use super::*;
27
28 #[test]
cases()29 fn cases() {
30 assert_eq!(0, [].into_iter().collect::<TestFlags>().bits());
31
32 assert_eq!(1, [TestFlags::A,].into_iter().collect::<TestFlags>().bits());
33
34 assert_eq!(
35 1 | 1 << 1 | 1 << 2,
36 [TestFlags::A, TestFlags::B | TestFlags::C,]
37 .into_iter()
38 .collect::<TestFlags>()
39 .bits()
40 );
41
42 assert_eq!(
43 1 | 1 << 3,
44 [
45 TestFlags::from_bits_retain(1 << 3),
46 TestFlags::empty(),
47 TestFlags::A,
48 ]
49 .into_iter()
50 .collect::<TestFlags>()
51 .bits()
52 );
53
54 assert_eq!(
55 1 << 5 | 1 << 7,
56 [
57 TestExternal::empty(),
58 TestExternal::from_bits_retain(1 << 5),
59 TestExternal::from_bits_retain(1 << 7),
60 ]
61 .into_iter()
62 .collect::<TestExternal>()
63 .bits()
64 );
65 }
66 }
67
68 mod iter {
69 use super::*;
70
71 #[test]
cases()72 fn cases() {
73 case(&[], TestFlags::empty(), TestFlags::iter);
74
75 case(&[1], TestFlags::A, TestFlags::iter);
76 case(&[1, 1 << 1], TestFlags::A | TestFlags::B, TestFlags::iter);
77 case(
78 &[1, 1 << 1, 1 << 3],
79 TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
80 TestFlags::iter,
81 );
82
83 case(&[1, 1 << 1, 1 << 2], TestFlags::ABC, TestFlags::iter);
84 case(
85 &[1, 1 << 1, 1 << 2, 1 << 3],
86 TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
87 TestFlags::iter,
88 );
89
90 case(
91 &[1 | 1 << 1 | 1 << 2],
92 TestFlagsInvert::ABC,
93 TestFlagsInvert::iter,
94 );
95
96 case(&[], TestZero::ZERO, TestZero::iter);
97
98 case(
99 &[1, 1 << 1, 1 << 2, 0b1111_1000],
100 TestExternal::all(),
101 TestExternal::iter,
102 );
103 }
104
105 #[track_caller]
case<T: Flags + std::fmt::Debug + IntoIterator<Item = T> + Copy>( expected: &[T::Bits], value: T, inherent: impl FnOnce(&T) -> crate::iter::Iter<T>, ) where T::Bits: std::fmt::Debug + PartialEq,106 fn case<T: Flags + std::fmt::Debug + IntoIterator<Item = T> + Copy>(
107 expected: &[T::Bits],
108 value: T,
109 inherent: impl FnOnce(&T) -> crate::iter::Iter<T>,
110 ) where
111 T::Bits: std::fmt::Debug + PartialEq,
112 {
113 assert_eq!(
114 expected,
115 inherent(&value).map(|f| f.bits()).collect::<Vec<_>>(),
116 "{:?}.iter()",
117 value
118 );
119 assert_eq!(
120 expected,
121 Flags::iter(&value).map(|f| f.bits()).collect::<Vec<_>>(),
122 "Flags::iter({:?})",
123 value
124 );
125 assert_eq!(
126 expected,
127 value.into_iter().map(|f| f.bits()).collect::<Vec<_>>(),
128 "{:?}.into_iter()",
129 value
130 );
131 }
132 }
133
134 mod iter_names {
135 use super::*;
136
137 #[test]
cases()138 fn cases() {
139 case(&[], TestFlags::empty(), TestFlags::iter_names);
140
141 case(&[("A", 1)], TestFlags::A, TestFlags::iter_names);
142 case(
143 &[("A", 1), ("B", 1 << 1)],
144 TestFlags::A | TestFlags::B,
145 TestFlags::iter_names,
146 );
147 case(
148 &[("A", 1), ("B", 1 << 1)],
149 TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
150 TestFlags::iter_names,
151 );
152
153 case(
154 &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
155 TestFlags::ABC,
156 TestFlags::iter_names,
157 );
158 case(
159 &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
160 TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
161 TestFlags::iter_names,
162 );
163
164 case(
165 &[("ABC", 1 | 1 << 1 | 1 << 2)],
166 TestFlagsInvert::ABC,
167 TestFlagsInvert::iter_names,
168 );
169
170 case(&[], TestZero::ZERO, TestZero::iter_names);
171
172 case(
173 &[("A", 1)],
174 TestOverlappingFull::A,
175 TestOverlappingFull::iter_names,
176 );
177 case(
178 &[("A", 1), ("D", 1 << 1)],
179 TestOverlappingFull::A | TestOverlappingFull::D,
180 TestOverlappingFull::iter_names,
181 );
182 }
183
184 #[track_caller]
case<T: Flags + std::fmt::Debug>( expected: &[(&'static str, T::Bits)], value: T, inherent: impl FnOnce(&T) -> crate::iter::IterNames<T>, ) where T::Bits: std::fmt::Debug + PartialEq,185 fn case<T: Flags + std::fmt::Debug>(
186 expected: &[(&'static str, T::Bits)],
187 value: T,
188 inherent: impl FnOnce(&T) -> crate::iter::IterNames<T>,
189 ) where
190 T::Bits: std::fmt::Debug + PartialEq,
191 {
192 assert_eq!(
193 expected,
194 inherent(&value)
195 .map(|(n, f)| (n, f.bits()))
196 .collect::<Vec<_>>(),
197 "{:?}.iter_names()",
198 value
199 );
200 assert_eq!(
201 expected,
202 Flags::iter_names(&value)
203 .map(|(n, f)| (n, f.bits()))
204 .collect::<Vec<_>>(),
205 "Flags::iter_names({:?})",
206 value
207 );
208 }
209 }
210