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