/rust/registry/src/index.crates.io-6f17d22bba15001f/wyz-0.5.1/src/fmt.rs
Line | Count | Source (jump to first uncovered line) |
1 | | /*! Format forwarding |
2 | | |
3 | | This module provides wrapper types for each formatting trait other than `Debug` |
4 | | which, when `Debug`-formatted, forward to the original trait instead of `Debug`. |
5 | | |
6 | | Each wrapper type is a tuple struct so that it can be used as a named |
7 | | constructor, such as in `.map(FmtDisplay)`. In addition, a blanket trait adds |
8 | | extension methods `.fmt_<trait_name>>()` to provide the corresponding wrap. |
9 | | |
10 | | Any modifiers in the format template string or struct modifier are passed |
11 | | through to the desired trait implementation unchanged. The only effect of the |
12 | | forwarding types in this module is to change the `?` template character to one |
13 | | of the other trait signifiers. |
14 | | !*/ |
15 | | |
16 | | use core::{ |
17 | | fmt::{ |
18 | | self, |
19 | | Binary, |
20 | | Debug, |
21 | | Display, |
22 | | Formatter, |
23 | | LowerExp, |
24 | | LowerHex, |
25 | | Octal, |
26 | | Pointer, |
27 | | UpperExp, |
28 | | UpperHex, |
29 | | }, |
30 | | ops::{ |
31 | | Deref, |
32 | | DerefMut, |
33 | | }, |
34 | | }; |
35 | | |
36 | | /// Wraps any value with a format-forward to `Debug`. |
37 | | #[cfg(not(tarpaulin_include))] |
38 | | pub trait FmtForward: Sized { |
39 | | /// Causes `self` to use its `Binary` implementation when `Debug`-formatted. |
40 | | #[inline(always)] |
41 | | fn fmt_binary(self) -> FmtBinary<Self> |
42 | | where Self: Binary { |
43 | | FmtBinary(self) |
44 | | } |
45 | | |
46 | | /// Causes `self` to use its `Display` implementation when |
47 | | /// `Debug`-formatted. |
48 | | #[inline(always)] |
49 | | fn fmt_display(self) -> FmtDisplay<Self> |
50 | | where Self: Display { |
51 | | FmtDisplay(self) |
52 | | } |
53 | | |
54 | | /// Causes `self` to use its `LowerExp` implementation when |
55 | | /// `Debug`-formatted. |
56 | | #[inline(always)] |
57 | | fn fmt_lower_exp(self) -> FmtLowerExp<Self> |
58 | | where Self: LowerExp { |
59 | | FmtLowerExp(self) |
60 | | } |
61 | | |
62 | | /// Causes `self` to use its `LowerHex` implementation when |
63 | | /// `Debug`-formatted. |
64 | | #[inline(always)] |
65 | | fn fmt_lower_hex(self) -> FmtLowerHex<Self> |
66 | | where Self: LowerHex { |
67 | | FmtLowerHex(self) |
68 | | } |
69 | | |
70 | | /// Causes `self` to use its `Octal` implementation when `Debug`-formatted. |
71 | | #[inline(always)] |
72 | | fn fmt_octal(self) -> FmtOctal<Self> |
73 | | where Self: Octal { |
74 | | FmtOctal(self) |
75 | | } |
76 | | |
77 | | /// Causes `self` to use its `Pointer` implementation when |
78 | | /// `Debug`-formatted. |
79 | | #[inline(always)] |
80 | 0 | fn fmt_pointer(self) -> FmtPointer<Self> |
81 | 0 | where Self: Pointer { |
82 | 0 | FmtPointer(self) |
83 | 0 | } |
84 | | |
85 | | /// Causes `self` to use its `UpperExp` implementation when |
86 | | /// `Debug`-formatted. |
87 | | #[inline(always)] |
88 | | fn fmt_upper_exp(self) -> FmtUpperExp<Self> |
89 | | where Self: UpperExp { |
90 | | FmtUpperExp(self) |
91 | | } |
92 | | |
93 | | /// Causes `self` to use its `UpperHex` implementation when |
94 | | /// `Debug`-formatted. |
95 | | #[inline(always)] |
96 | | fn fmt_upper_hex(self) -> FmtUpperHex<Self> |
97 | | where Self: UpperHex { |
98 | | FmtUpperHex(self) |
99 | | } |
100 | | |
101 | | /// Formats each item in a sequence. |
102 | | /// |
103 | | /// This wrapper structure conditionally implements all of the formatting |
104 | | /// traits when `self` can be viewed as an iterator whose *items* implement |
105 | | /// them. It iterates over `&self` and prints each item according to the |
106 | | /// formatting specifier provided. |
107 | | #[inline(always)] |
108 | | fn fmt_list(self) -> FmtList<Self> |
109 | | where for<'a> &'a Self: IntoIterator { |
110 | | FmtList(self) |
111 | | } |
112 | | } |
113 | | |
114 | | impl<T: Sized> FmtForward for T { |
115 | | } |
116 | | |
117 | | /// Forwards a type’s `Binary` formatting implementation to `Debug`. |
118 | | #[repr(transparent)] |
119 | | pub struct FmtBinary<T: Binary>(pub T); |
120 | | |
121 | | /// Forwards a type’s `Display` formatting implementation to `Debug`. |
122 | | #[repr(transparent)] |
123 | | pub struct FmtDisplay<T: Display>(pub T); |
124 | | |
125 | | /// Renders each element of a stream into a list. |
126 | | #[repr(transparent)] |
127 | | pub struct FmtList<T>(pub T) |
128 | | where for<'a> &'a T: IntoIterator; |
129 | | |
130 | | /// Forwards a type’s `LowerExp` formatting implementation to `Debug`. |
131 | | #[repr(transparent)] |
132 | | pub struct FmtLowerExp<T: LowerExp>(pub T); |
133 | | |
134 | | /// Forwards a type’s `LowerHex` formatting implementation to `Debug`. |
135 | | #[repr(transparent)] |
136 | | pub struct FmtLowerHex<T: LowerHex>(pub T); |
137 | | |
138 | | /// Forwards a type’s `Octal` formatting implementation to `Debug`. |
139 | | #[repr(transparent)] |
140 | | pub struct FmtOctal<T: Octal>(pub T); |
141 | | |
142 | | /// Forwards a type’s `Pointer` formatting implementation to `Debug`. |
143 | | #[repr(transparent)] |
144 | | pub struct FmtPointer<T: Pointer>(pub T); |
145 | | |
146 | | /// Forwards a type’s `UpperExp` formatting implementation to `Debug`. |
147 | | #[repr(transparent)] |
148 | | pub struct FmtUpperExp<T: UpperExp>(pub T); |
149 | | |
150 | | /// Forwards a type’s `UpperHex` formatting implementation to `Debug`. |
151 | | #[repr(transparent)] |
152 | | pub struct FmtUpperHex<T: UpperHex>(pub T); |
153 | | |
154 | | macro_rules! fmt { |
155 | | ($($w:ty => $t:ident),* $(,)?) => { $( |
156 | | #[cfg(not(tarpaulin_include))] |
157 | | impl<T: $t + Binary> Binary for $w { |
158 | | #[inline(always)] |
159 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
160 | | Binary::fmt(&self.0, fmt) |
161 | | } |
162 | | } |
163 | | |
164 | | impl<T: $t> Debug for $w { |
165 | | #[inline(always)] |
166 | 0 | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
167 | 0 | <T as $t>::fmt(&self.0, fmt) |
168 | 0 | } |
169 | | } |
170 | | |
171 | | #[cfg(not(tarpaulin_include))] |
172 | | impl<T: $t + Display> Display for $w { |
173 | | #[inline(always)] |
174 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
175 | | Display::fmt(&self.0, fmt) |
176 | | } |
177 | | } |
178 | | |
179 | | #[cfg(not(tarpaulin_include))] |
180 | | impl<T: $t + LowerExp> LowerExp for $w { |
181 | | #[inline(always)] |
182 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
183 | | LowerExp::fmt(&self.0, fmt) |
184 | | } |
185 | | } |
186 | | |
187 | | #[cfg(not(tarpaulin_include))] |
188 | | impl<T: $t + LowerHex> LowerHex for $w { |
189 | | #[inline(always)] |
190 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
191 | | LowerHex::fmt(&self.0, fmt) |
192 | | } |
193 | | } |
194 | | |
195 | | #[cfg(not(tarpaulin_include))] |
196 | | impl<T: $t + Octal> Octal for $w { |
197 | | #[inline(always)] |
198 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
199 | | Octal::fmt(&self.0, fmt) |
200 | | } |
201 | | } |
202 | | |
203 | | #[cfg(not(tarpaulin_include))] |
204 | | impl<T: $t + Pointer> Pointer for $w { |
205 | | #[inline(always)] |
206 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
207 | | Pointer::fmt(&self.0, fmt) |
208 | | } |
209 | | } |
210 | | |
211 | | #[cfg(not(tarpaulin_include))] |
212 | | impl<T: $t + UpperExp> UpperExp for $w { |
213 | | #[inline(always)] |
214 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
215 | | UpperExp::fmt(&self.0, fmt) |
216 | | } |
217 | | } |
218 | | |
219 | | #[cfg(not(tarpaulin_include))] |
220 | | impl<T: $t + UpperHex> UpperHex for $w { |
221 | | #[inline(always)] |
222 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
223 | | UpperHex::fmt(&self.0, fmt) |
224 | | } |
225 | | } |
226 | | |
227 | | #[cfg(not(tarpaulin_include))] |
228 | | impl<T: $t> Deref for $w { |
229 | | type Target = T; |
230 | | |
231 | | #[inline(always)] |
232 | | fn deref(&self) -> &Self::Target { |
233 | | &self.0 |
234 | | } |
235 | | } |
236 | | |
237 | | #[cfg(not(tarpaulin_include))] |
238 | | impl<T: $t> DerefMut for $w { |
239 | | #[inline(always)] |
240 | | fn deref_mut(&mut self) -> &mut Self::Target { |
241 | | &mut self.0 |
242 | | } |
243 | | } |
244 | | |
245 | | #[cfg(not(tarpaulin_include))] |
246 | | impl<T: $t> AsRef<T> for $w { |
247 | | #[inline(always)] |
248 | | fn as_ref(&self) -> &T { |
249 | | &self.0 |
250 | | } |
251 | | } |
252 | | |
253 | | #[cfg(not(tarpaulin_include))] |
254 | | impl<T: $t> AsMut<T> for $w { |
255 | | #[inline(always)] |
256 | | fn as_mut(&mut self) -> &mut T { |
257 | | &mut self.0 |
258 | | } |
259 | | } |
260 | | )* }; |
261 | | } |
262 | | |
263 | | fmt!( |
264 | | FmtBinary<T> => Binary, |
265 | | FmtDisplay<T> => Display, |
266 | | FmtLowerExp<T> => LowerExp, |
267 | | FmtLowerHex<T> => LowerHex, |
268 | | FmtOctal<T> => Octal, |
269 | | FmtPointer<T> => Pointer, |
270 | | FmtUpperExp<T> => UpperExp, |
271 | | FmtUpperHex<T> => UpperHex, |
272 | | ); |
273 | | |
274 | | impl<T> Binary for FmtList<T> |
275 | | where |
276 | | for<'a> &'a T: IntoIterator, |
277 | | for<'a> <&'a T as IntoIterator>::Item: Binary, |
278 | | { |
279 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
280 | | fmt.debug_list() |
281 | | .entries((&self.0).into_iter().map(FmtBinary)) |
282 | | .finish() |
283 | | } |
284 | | } |
285 | | |
286 | | impl<T> Debug for FmtList<T> |
287 | | where |
288 | | for<'a> &'a T: IntoIterator, |
289 | | for<'a> <&'a T as IntoIterator>::Item: Debug, |
290 | | { |
291 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
292 | | fmt.debug_list().entries((&self.0).into_iter()).finish() |
293 | | } |
294 | | } |
295 | | |
296 | | impl<T> Display for FmtList<T> |
297 | | where |
298 | | for<'a> &'a T: IntoIterator, |
299 | | for<'a> <&'a T as IntoIterator>::Item: Display, |
300 | | { |
301 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
302 | | fmt.debug_list() |
303 | | .entries((&self.0).into_iter().map(FmtDisplay)) |
304 | | .finish() |
305 | | } |
306 | | } |
307 | | |
308 | | impl<T> LowerExp for FmtList<T> |
309 | | where |
310 | | for<'a> &'a T: IntoIterator, |
311 | | for<'a> <&'a T as IntoIterator>::Item: LowerExp, |
312 | | { |
313 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
314 | | fmt.debug_list() |
315 | | .entries((&self.0).into_iter().map(FmtLowerExp)) |
316 | | .finish() |
317 | | } |
318 | | } |
319 | | |
320 | | impl<T> LowerHex for FmtList<T> |
321 | | where |
322 | | for<'a> &'a T: IntoIterator, |
323 | | for<'a> <&'a T as IntoIterator>::Item: LowerHex, |
324 | | { |
325 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
326 | | fmt.debug_list() |
327 | | .entries((&self.0).into_iter().map(FmtLowerHex)) |
328 | | .finish() |
329 | | } |
330 | | } |
331 | | |
332 | | impl<T> Octal for FmtList<T> |
333 | | where |
334 | | for<'a> &'a T: IntoIterator, |
335 | | for<'a> <&'a T as IntoIterator>::Item: Octal, |
336 | | { |
337 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
338 | | fmt.debug_list() |
339 | | .entries((&self.0).into_iter().map(FmtOctal)) |
340 | | .finish() |
341 | | } |
342 | | } |
343 | | |
344 | | impl<T> UpperExp for FmtList<T> |
345 | | where |
346 | | for<'a> &'a T: IntoIterator, |
347 | | for<'a> <&'a T as IntoIterator>::Item: UpperExp, |
348 | | { |
349 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
350 | | fmt.debug_list() |
351 | | .entries((&self.0).into_iter().map(FmtUpperExp)) |
352 | | .finish() |
353 | | } |
354 | | } |
355 | | |
356 | | impl<T> UpperHex for FmtList<T> |
357 | | where |
358 | | for<'a> &'a T: IntoIterator, |
359 | | for<'a> <&'a T as IntoIterator>::Item: UpperHex, |
360 | | { |
361 | | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
362 | | fmt.debug_list() |
363 | | .entries((&self.0).into_iter().map(FmtUpperHex)) |
364 | | .finish() |
365 | | } |
366 | | } |
367 | | |
368 | | #[cfg(not(tarpaulin_include))] |
369 | | impl<T> Deref for FmtList<T> |
370 | | where for<'a> &'a T: IntoIterator |
371 | | { |
372 | | type Target = T; |
373 | | |
374 | | #[inline(always)] |
375 | | fn deref(&self) -> &Self::Target { |
376 | | &self.0 |
377 | | } |
378 | | } |
379 | | |
380 | | #[cfg(not(tarpaulin_include))] |
381 | | impl<T> DerefMut for FmtList<T> |
382 | | where for<'a> &'a T: IntoIterator |
383 | | { |
384 | | #[inline(always)] |
385 | | fn deref_mut(&mut self) -> &mut Self::Target { |
386 | | &mut self.0 |
387 | | } |
388 | | } |
389 | | |
390 | | #[cfg(not(tarpaulin_include))] |
391 | | impl<T> AsRef<T> for FmtList<T> |
392 | | where for<'a> &'a T: IntoIterator |
393 | | { |
394 | | #[inline(always)] |
395 | | fn as_ref(&self) -> &T { |
396 | | &self.0 |
397 | | } |
398 | | } |
399 | | |
400 | | #[cfg(not(tarpaulin_include))] |
401 | | impl<T> AsMut<T> for FmtList<T> |
402 | | where for<'a> &'a T: IntoIterator |
403 | | { |
404 | | #[inline(always)] |
405 | | fn as_mut(&mut self) -> &mut T { |
406 | | &mut self.0 |
407 | | } |
408 | | } |
409 | | |
410 | | #[cfg(all(test, feature = "alloc"))] |
411 | | mod tests { |
412 | | #[cfg(not(feature = "std"))] |
413 | | use alloc::format; |
414 | | |
415 | | #[cfg(feature = "std")] |
416 | | use std::format; |
417 | | |
418 | | use super::*; |
419 | | |
420 | | #[test] |
421 | | fn render_item() { |
422 | | let num = 29; |
423 | | |
424 | | assert_eq!(format!("{:?}", num.fmt_binary()), "11101"); |
425 | | assert_eq!(format!("{:?}", num.fmt_display()), "29"); |
426 | | assert_eq!(format!("{:?}", num.fmt_upper_hex()), "1D"); |
427 | | assert_eq!(format!("{:?}", num.fmt_octal()), "35"); |
428 | | assert_eq!(format!("{:?}", num.fmt_lower_hex()), "1d"); |
429 | | |
430 | | let num = 53.7; |
431 | | assert_eq!(format!("{:?}", num.fmt_lower_exp()), "5.37e1"); |
432 | | assert_eq!(format!("{:?}", num.fmt_upper_exp()), "5.37E1"); |
433 | | } |
434 | | |
435 | | #[test] |
436 | | fn render_list() { |
437 | | let list = [0, 1, 2, 3]; |
438 | | assert_eq!(format!("{:02b}", list.fmt_list()), "[00, 01, 10, 11]"); |
439 | | assert_eq!(format!("{:01?}", list.fmt_list()), "[0, 1, 2, 3]"); |
440 | | assert_eq!(format!("{:01}", list.fmt_list()), "[0, 1, 2, 3]"); |
441 | | |
442 | | let list = [-51.0, -1.2, 1.3, 54.0]; |
443 | | assert_eq!( |
444 | | format!("{:e}", list.fmt_list()), |
445 | | "[-5.1e1, -1.2e0, 1.3e0, 5.4e1]" |
446 | | ); |
447 | | assert_eq!( |
448 | | format!("{:E}", list.fmt_list()), |
449 | | "[-5.1E1, -1.2E0, 1.3E0, 5.4E1]" |
450 | | ); |
451 | | |
452 | | let list = [0, 10, 20, 30]; |
453 | | assert_eq!(format!("{:02x}", list.fmt_list()), "[00, 0a, 14, 1e]"); |
454 | | assert_eq!(format!("{:02o}", list.fmt_list()), "[00, 12, 24, 36]"); |
455 | | assert_eq!(format!("{:02X}", list.fmt_list()), "[00, 0A, 14, 1E]"); |
456 | | } |
457 | | } |