1 use super::*;
2 
3 use crate::{parser::*, Flags};
4 
5 #[test]
6 #[cfg(not(miri))] // Very slow in miri
roundtrip()7 fn roundtrip() {
8     let mut s = String::new();
9 
10     for a in 0u8..=255 {
11         for b in 0u8..=255 {
12             let f = TestFlags::from_bits_retain(a | b);
13 
14             s.clear();
15             to_writer(&f, &mut s).unwrap();
16 
17             assert_eq!(f, from_str::<TestFlags>(&s).unwrap());
18         }
19     }
20 }
21 
22 #[test]
23 #[cfg(not(miri))] // Very slow in miri
roundtrip_truncate()24 fn roundtrip_truncate() {
25     let mut s = String::new();
26 
27     for a in 0u8..=255 {
28         for b in 0u8..=255 {
29             let f = TestFlags::from_bits_retain(a | b);
30 
31             s.clear();
32             to_writer_truncate(&f, &mut s).unwrap();
33 
34             assert_eq!(
35                 TestFlags::from_bits_truncate(f.bits()),
36                 from_str_truncate::<TestFlags>(&s).unwrap()
37             );
38         }
39     }
40 }
41 
42 #[test]
43 #[cfg(not(miri))] // Very slow in miri
roundtrip_strict()44 fn roundtrip_strict() {
45     let mut s = String::new();
46 
47     for a in 0u8..=255 {
48         for b in 0u8..=255 {
49             let f = TestFlags::from_bits_retain(a | b);
50 
51             s.clear();
52             to_writer_strict(&f, &mut s).unwrap();
53 
54             let mut strict = TestFlags::empty();
55             for (_, flag) in f.iter_names() {
56                 strict |= flag;
57             }
58             let f = strict;
59 
60             if let Ok(s) = from_str_strict::<TestFlags>(&s) {
61                 assert_eq!(f, s);
62             }
63         }
64     }
65 }
66 
67 mod from_str {
68     use super::*;
69 
70     #[test]
valid()71     fn valid() {
72         assert_eq!(0, from_str::<TestFlags>("").unwrap().bits());
73 
74         assert_eq!(1, from_str::<TestFlags>("A").unwrap().bits());
75         assert_eq!(1, from_str::<TestFlags>(" A ").unwrap().bits());
76         assert_eq!(
77             1 | 1 << 1 | 1 << 2,
78             from_str::<TestFlags>("A | B | C").unwrap().bits()
79         );
80         assert_eq!(
81             1 | 1 << 1 | 1 << 2,
82             from_str::<TestFlags>("A\n|\tB\r\n|   C ").unwrap().bits()
83         );
84         assert_eq!(
85             1 | 1 << 1 | 1 << 2,
86             from_str::<TestFlags>("A|B|C").unwrap().bits()
87         );
88 
89         assert_eq!(1 << 3, from_str::<TestFlags>("0x8").unwrap().bits());
90         assert_eq!(1 | 1 << 3, from_str::<TestFlags>("A | 0x8").unwrap().bits());
91         assert_eq!(
92             1 | 1 << 1 | 1 << 3,
93             from_str::<TestFlags>("0x1 | 0x8 | B").unwrap().bits()
94         );
95 
96         assert_eq!(
97             1 | 1 << 1,
98             from_str::<TestUnicode>("一 | 二").unwrap().bits()
99         );
100     }
101 
102     #[test]
invalid()103     fn invalid() {
104         assert!(from_str::<TestFlags>("a")
105             .unwrap_err()
106             .to_string()
107             .starts_with("unrecognized named flag"));
108         assert!(from_str::<TestFlags>("A & B")
109             .unwrap_err()
110             .to_string()
111             .starts_with("unrecognized named flag"));
112 
113         assert!(from_str::<TestFlags>("0xg")
114             .unwrap_err()
115             .to_string()
116             .starts_with("invalid hex flag"));
117         assert!(from_str::<TestFlags>("0xffffffffffff")
118             .unwrap_err()
119             .to_string()
120             .starts_with("invalid hex flag"));
121     }
122 }
123 
124 mod to_writer {
125     use super::*;
126 
127     #[test]
cases()128     fn cases() {
129         assert_eq!("", write(TestFlags::empty()));
130         assert_eq!("A", write(TestFlags::A));
131         assert_eq!("A | B | C", write(TestFlags::all()));
132         assert_eq!("0x8", write(TestFlags::from_bits_retain(1 << 3)));
133         assert_eq!(
134             "A | 0x8",
135             write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
136         );
137 
138         assert_eq!("", write(TestZero::ZERO));
139 
140         assert_eq!("ABC", write(TestFlagsInvert::all()));
141 
142         assert_eq!("0x1", write(TestOverlapping::from_bits_retain(1)));
143 
144         assert_eq!("A", write(TestOverlappingFull::C));
145         assert_eq!(
146             "A | D",
147             write(TestOverlappingFull::C | TestOverlappingFull::D)
148         );
149     }
150 
write<F: Flags>(value: F) -> String where F::Bits: crate::parser::WriteHex,151     fn write<F: Flags>(value: F) -> String
152     where
153         F::Bits: crate::parser::WriteHex,
154     {
155         let mut s = String::new();
156 
157         to_writer(&value, &mut s).unwrap();
158         s
159     }
160 }
161 
162 mod from_str_truncate {
163     use super::*;
164 
165     #[test]
valid()166     fn valid() {
167         assert_eq!(0, from_str_truncate::<TestFlags>("").unwrap().bits());
168 
169         assert_eq!(1, from_str_truncate::<TestFlags>("A").unwrap().bits());
170         assert_eq!(1, from_str_truncate::<TestFlags>(" A ").unwrap().bits());
171         assert_eq!(
172             1 | 1 << 1 | 1 << 2,
173             from_str_truncate::<TestFlags>("A | B | C").unwrap().bits()
174         );
175         assert_eq!(
176             1 | 1 << 1 | 1 << 2,
177             from_str_truncate::<TestFlags>("A\n|\tB\r\n|   C ")
178                 .unwrap()
179                 .bits()
180         );
181         assert_eq!(
182             1 | 1 << 1 | 1 << 2,
183             from_str_truncate::<TestFlags>("A|B|C").unwrap().bits()
184         );
185 
186         assert_eq!(0, from_str_truncate::<TestFlags>("0x8").unwrap().bits());
187         assert_eq!(1, from_str_truncate::<TestFlags>("A | 0x8").unwrap().bits());
188         assert_eq!(
189             1 | 1 << 1,
190             from_str_truncate::<TestFlags>("0x1 | 0x8 | B")
191                 .unwrap()
192                 .bits()
193         );
194 
195         assert_eq!(
196             1 | 1 << 1,
197             from_str_truncate::<TestUnicode>("一 | 二").unwrap().bits()
198         );
199     }
200 }
201 
202 mod to_writer_truncate {
203     use super::*;
204 
205     #[test]
cases()206     fn cases() {
207         assert_eq!("", write(TestFlags::empty()));
208         assert_eq!("A", write(TestFlags::A));
209         assert_eq!("A | B | C", write(TestFlags::all()));
210         assert_eq!("", write(TestFlags::from_bits_retain(1 << 3)));
211         assert_eq!(
212             "A",
213             write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
214         );
215 
216         assert_eq!("", write(TestZero::ZERO));
217 
218         assert_eq!("ABC", write(TestFlagsInvert::all()));
219 
220         assert_eq!("0x1", write(TestOverlapping::from_bits_retain(1)));
221 
222         assert_eq!("A", write(TestOverlappingFull::C));
223         assert_eq!(
224             "A | D",
225             write(TestOverlappingFull::C | TestOverlappingFull::D)
226         );
227     }
228 
write<F: Flags>(value: F) -> String where F::Bits: crate::parser::WriteHex,229     fn write<F: Flags>(value: F) -> String
230     where
231         F::Bits: crate::parser::WriteHex,
232     {
233         let mut s = String::new();
234 
235         to_writer_truncate(&value, &mut s).unwrap();
236         s
237     }
238 }
239 
240 mod from_str_strict {
241     use super::*;
242 
243     #[test]
valid()244     fn valid() {
245         assert_eq!(0, from_str_strict::<TestFlags>("").unwrap().bits());
246 
247         assert_eq!(1, from_str_strict::<TestFlags>("A").unwrap().bits());
248         assert_eq!(1, from_str_strict::<TestFlags>(" A ").unwrap().bits());
249         assert_eq!(
250             1 | 1 << 1 | 1 << 2,
251             from_str_strict::<TestFlags>("A | B | C").unwrap().bits()
252         );
253         assert_eq!(
254             1 | 1 << 1 | 1 << 2,
255             from_str_strict::<TestFlags>("A\n|\tB\r\n|   C ")
256                 .unwrap()
257                 .bits()
258         );
259         assert_eq!(
260             1 | 1 << 1 | 1 << 2,
261             from_str_strict::<TestFlags>("A|B|C").unwrap().bits()
262         );
263 
264         assert_eq!(
265             1 | 1 << 1,
266             from_str_strict::<TestUnicode>("一 | 二").unwrap().bits()
267         );
268     }
269 
270     #[test]
invalid()271     fn invalid() {
272         assert!(from_str_strict::<TestFlags>("a")
273             .unwrap_err()
274             .to_string()
275             .starts_with("unrecognized named flag"));
276         assert!(from_str_strict::<TestFlags>("A & B")
277             .unwrap_err()
278             .to_string()
279             .starts_with("unrecognized named flag"));
280 
281         assert!(from_str_strict::<TestFlags>("0x1")
282             .unwrap_err()
283             .to_string()
284             .starts_with("invalid hex flag"));
285         assert!(from_str_strict::<TestFlags>("0xg")
286             .unwrap_err()
287             .to_string()
288             .starts_with("invalid hex flag"));
289         assert!(from_str_strict::<TestFlags>("0xffffffffffff")
290             .unwrap_err()
291             .to_string()
292             .starts_with("invalid hex flag"));
293     }
294 }
295 
296 mod to_writer_strict {
297     use super::*;
298 
299     #[test]
cases()300     fn cases() {
301         assert_eq!("", write(TestFlags::empty()));
302         assert_eq!("A", write(TestFlags::A));
303         assert_eq!("A | B | C", write(TestFlags::all()));
304         assert_eq!("", write(TestFlags::from_bits_retain(1 << 3)));
305         assert_eq!(
306             "A",
307             write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
308         );
309 
310         assert_eq!("", write(TestZero::ZERO));
311 
312         assert_eq!("ABC", write(TestFlagsInvert::all()));
313 
314         assert_eq!("", write(TestOverlapping::from_bits_retain(1)));
315 
316         assert_eq!("A", write(TestOverlappingFull::C));
317         assert_eq!(
318             "A | D",
319             write(TestOverlappingFull::C | TestOverlappingFull::D)
320         );
321     }
322 
write<F: Flags>(value: F) -> String where F::Bits: crate::parser::WriteHex,323     fn write<F: Flags>(value: F) -> String
324     where
325         F::Bits: crate::parser::WriteHex,
326     {
327         let mut s = String::new();
328 
329         to_writer_strict(&value, &mut s).unwrap();
330         s
331     }
332 }
333