1use 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#[cfg(not(tarpaulin_include))]
38pub trait FmtForward: Sized {
39 #[inline(always)]
54 fn fmt_binary(self) -> FmtBinary<Self>
55 where Self: Binary {
56 FmtBinary(self)
57 }
58
59 #[inline(always)]
85 fn fmt_display(self) -> FmtDisplay<Self>
86 where Self: Display {
87 FmtDisplay(self)
88 }
89
90 #[inline(always)]
106 fn fmt_lower_exp(self) -> FmtLowerExp<Self>
107 where Self: LowerExp {
108 FmtLowerExp(self)
109 }
110
111 #[inline(always)]
127 fn fmt_lower_hex(self) -> FmtLowerHex<Self>
128 where Self: LowerHex {
129 FmtLowerHex(self)
130 }
131
132 #[inline(always)]
147 fn fmt_octal(self) -> FmtOctal<Self>
148 where Self: Octal {
149 FmtOctal(self)
150 }
151
152 #[inline(always)]
168 fn fmt_pointer(self) -> FmtPointer<Self>
169 where Self: Pointer {
170 FmtPointer(self)
171 }
172
173 #[inline(always)]
189 fn fmt_upper_exp(self) -> FmtUpperExp<Self>
190 where Self: UpperExp {
191 FmtUpperExp(self)
192 }
193
194 #[inline(always)]
210 fn fmt_upper_hex(self) -> FmtUpperHex<Self>
211 where Self: UpperHex {
212 FmtUpperHex(self)
213 }
214
215 #[inline(always)]
236 fn fmt_list(self) -> FmtList<Self>
237 where for<'a> &'a Self: IntoIterator {
238 FmtList(self)
239 }
240}
241
242impl<T: Sized> FmtForward for T {
243}
244
245#[repr(transparent)]
247pub struct FmtBinary<T: Binary>(pub T);
248
249#[repr(transparent)]
251pub struct FmtDisplay<T: Display>(pub T);
252
253#[repr(transparent)]
255pub struct FmtList<T>(pub T)
256where for<'a> &'a T: IntoIterator;
257
258#[repr(transparent)]
260pub struct FmtLowerExp<T: LowerExp>(pub T);
261
262#[repr(transparent)]
264pub struct FmtLowerHex<T: LowerHex>(pub T);
265
266#[repr(transparent)]
268pub struct FmtOctal<T: Octal>(pub T);
269
270#[repr(transparent)]
272pub struct FmtPointer<T: Pointer>(pub T);
273
274#[repr(transparent)]
276pub struct FmtUpperExp<T: UpperExp>(pub T);
277
278#[repr(transparent)]
280pub struct FmtUpperHex<T: UpperHex>(pub T);
281
282macro_rules! fmt {
283 ($($w:ty => $t:ident),* $(,)?) => { $(
284 #[cfg(not(tarpaulin_include))]
285 impl<T: $t + Binary> Binary for $w {
286 #[inline(always)]
287 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
288 Binary::fmt(&self.0, fmt)
289 }
290 }
291
292 impl<T: $t> Debug for $w {
293 #[inline(always)]
294 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
295 <T as $t>::fmt(&self.0, fmt)
296 }
297 }
298
299 #[cfg(not(tarpaulin_include))]
300 impl<T: $t + Display> Display for $w {
301 #[inline(always)]
302 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
303 Display::fmt(&self.0, fmt)
304 }
305 }
306
307 #[cfg(not(tarpaulin_include))]
308 impl<T: $t + LowerExp> LowerExp for $w {
309 #[inline(always)]
310 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
311 LowerExp::fmt(&self.0, fmt)
312 }
313 }
314
315 #[cfg(not(tarpaulin_include))]
316 impl<T: $t + LowerHex> LowerHex for $w {
317 #[inline(always)]
318 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
319 LowerHex::fmt(&self.0, fmt)
320 }
321 }
322
323 #[cfg(not(tarpaulin_include))]
324 impl<T: $t + Octal> Octal for $w {
325 #[inline(always)]
326 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
327 Octal::fmt(&self.0, fmt)
328 }
329 }
330
331 #[cfg(not(tarpaulin_include))]
332 impl<T: $t + Pointer> Pointer for $w {
333 #[inline(always)]
334 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
335 Pointer::fmt(&self.0, fmt)
336 }
337 }
338
339 #[cfg(not(tarpaulin_include))]
340 impl<T: $t + UpperExp> UpperExp for $w {
341 #[inline(always)]
342 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
343 UpperExp::fmt(&self.0, fmt)
344 }
345 }
346
347 #[cfg(not(tarpaulin_include))]
348 impl<T: $t + UpperHex> UpperHex for $w {
349 #[inline(always)]
350 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
351 UpperHex::fmt(&self.0, fmt)
352 }
353 }
354
355 #[cfg(not(tarpaulin_include))]
356 impl<T: $t> Deref for $w {
357 type Target = T;
358
359 #[inline(always)]
360 fn deref(&self) -> &Self::Target {
361 &self.0
362 }
363 }
364
365 #[cfg(not(tarpaulin_include))]
366 impl<T: $t> DerefMut for $w {
367 #[inline(always)]
368 fn deref_mut(&mut self) -> &mut Self::Target {
369 &mut self.0
370 }
371 }
372
373 #[cfg(not(tarpaulin_include))]
374 impl<T: $t> AsRef<T> for $w {
375 #[inline(always)]
376 fn as_ref(&self) -> &T {
377 &self.0
378 }
379 }
380
381 #[cfg(not(tarpaulin_include))]
382 impl<T: $t> AsMut<T> for $w {
383 #[inline(always)]
384 fn as_mut(&mut self) -> &mut T {
385 &mut self.0
386 }
387 }
388 )* };
389}
390
391fmt!(
392 FmtBinary<T> => Binary,
393 FmtDisplay<T> => Display,
394 FmtLowerExp<T> => LowerExp,
395 FmtLowerHex<T> => LowerHex,
396 FmtOctal<T> => Octal,
397 FmtPointer<T> => Pointer,
398 FmtUpperExp<T> => UpperExp,
399 FmtUpperHex<T> => UpperHex,
400);
401
402impl<T> Binary for FmtList<T>
403where
404 for<'a> &'a T: IntoIterator,
405 for<'a> <&'a T as IntoIterator>::Item: Binary,
406{
407 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
408 fmt.debug_list()
409 .entries((&self.0).into_iter().map(FmtBinary))
410 .finish()
411 }
412}
413
414impl<T> Debug for FmtList<T>
415where
416 for<'a> &'a T: IntoIterator,
417 for<'a> <&'a T as IntoIterator>::Item: Debug,
418{
419 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
420 fmt.debug_list().entries((&self.0).into_iter()).finish()
421 }
422}
423
424impl<T> Display for FmtList<T>
425where
426 for<'a> &'a T: IntoIterator,
427 for<'a> <&'a T as IntoIterator>::Item: Display,
428{
429 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
430 fmt.debug_list()
431 .entries((&self.0).into_iter().map(FmtDisplay))
432 .finish()
433 }
434}
435
436impl<T> LowerExp for FmtList<T>
437where
438 for<'a> &'a T: IntoIterator,
439 for<'a> <&'a T as IntoIterator>::Item: LowerExp,
440{
441 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
442 fmt.debug_list()
443 .entries((&self.0).into_iter().map(FmtLowerExp))
444 .finish()
445 }
446}
447
448impl<T> LowerHex for FmtList<T>
449where
450 for<'a> &'a T: IntoIterator,
451 for<'a> <&'a T as IntoIterator>::Item: LowerHex,
452{
453 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
454 fmt.debug_list()
455 .entries((&self.0).into_iter().map(FmtLowerHex))
456 .finish()
457 }
458}
459
460impl<T> Octal for FmtList<T>
461where
462 for<'a> &'a T: IntoIterator,
463 for<'a> <&'a T as IntoIterator>::Item: Octal,
464{
465 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
466 fmt.debug_list()
467 .entries((&self.0).into_iter().map(FmtOctal))
468 .finish()
469 }
470}
471
472impl<T> UpperExp for FmtList<T>
473where
474 for<'a> &'a T: IntoIterator,
475 for<'a> <&'a T as IntoIterator>::Item: UpperExp,
476{
477 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
478 fmt.debug_list()
479 .entries((&self.0).into_iter().map(FmtUpperExp))
480 .finish()
481 }
482}
483
484impl<T> UpperHex for FmtList<T>
485where
486 for<'a> &'a T: IntoIterator,
487 for<'a> <&'a T as IntoIterator>::Item: UpperHex,
488{
489 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
490 fmt.debug_list()
491 .entries((&self.0).into_iter().map(FmtUpperHex))
492 .finish()
493 }
494}
495
496#[cfg(not(tarpaulin_include))]
497impl<T> Deref for FmtList<T>
498where for<'a> &'a T: IntoIterator
499{
500 type Target = T;
501
502 #[inline(always)]
503 fn deref(&self) -> &Self::Target {
504 &self.0
505 }
506}
507
508#[cfg(not(tarpaulin_include))]
509impl<T> DerefMut for FmtList<T>
510where for<'a> &'a T: IntoIterator
511{
512 #[inline(always)]
513 fn deref_mut(&mut self) -> &mut Self::Target {
514 &mut self.0
515 }
516}
517
518#[cfg(not(tarpaulin_include))]
519impl<T> AsRef<T> for FmtList<T>
520where for<'a> &'a T: IntoIterator
521{
522 #[inline(always)]
523 fn as_ref(&self) -> &T {
524 &self.0
525 }
526}
527
528#[cfg(not(tarpaulin_include))]
529impl<T> AsMut<T> for FmtList<T>
530where for<'a> &'a T: IntoIterator
531{
532 #[inline(always)]
533 fn as_mut(&mut self) -> &mut T {
534 &mut self.0
535 }
536}
537
538#[cfg(all(test, feature = "alloc"))]
539mod tests {
540 #[cfg(not(feature = "std"))]
541 use alloc::format;
542
543 #[cfg(feature = "std")]
544 use std::format;
545
546 use super::*;
547
548 #[test]
549 fn render_item() {
550 let num = 29;
551
552 assert_eq!(format!("{:?}", num.fmt_binary()), "11101");
553 assert_eq!(format!("{:?}", num.fmt_display()), "29");
554 assert_eq!(format!("{:?}", num.fmt_upper_hex()), "1D");
555 assert_eq!(format!("{:?}", num.fmt_octal()), "35");
556 assert_eq!(format!("{:?}", num.fmt_lower_hex()), "1d");
557
558 let num = 53.7;
559 assert_eq!(format!("{:?}", num.fmt_lower_exp()), "5.37e1");
560 assert_eq!(format!("{:?}", num.fmt_upper_exp()), "5.37E1");
561 }
562
563 #[test]
564 fn render_list() {
565 let list = [0, 1, 2, 3];
566 assert_eq!(format!("{:02b}", list.fmt_list()), "[00, 01, 10, 11]");
567 assert_eq!(format!("{:01?}", list.fmt_list()), "[0, 1, 2, 3]");
568 assert_eq!(format!("{:01}", list.fmt_list()), "[0, 1, 2, 3]");
569
570 let list = [-51.0, -1.2, 1.3, 54.0];
571 assert_eq!(
572 format!("{:e}", list.fmt_list()),
573 "[-5.1e1, -1.2e0, 1.3e0, 5.4e1]"
574 );
575 assert_eq!(
576 format!("{:E}", list.fmt_list()),
577 "[-5.1E1, -1.2E0, 1.3E0, 5.4E1]"
578 );
579
580 let list = [0, 10, 20, 30];
581 assert_eq!(format!("{:02x}", list.fmt_list()), "[00, 0a, 14, 1e]");
582 assert_eq!(format!("{:02o}", list.fmt_list()), "[00, 12, 24, 36]");
583 assert_eq!(format!("{:02X}", list.fmt_list()), "[00, 0A, 14, 1E]");
584
585 assert_eq!(
586 format!("{:02?}", list.fmt_list().fmt_lower_hex()),
587 "[00, 0a, 14, 1e]"
588 );
589 }
590}