Skip to main content

impl_more/
fmt.rs

1/// Implement [`Debug`](core::fmt::Debug) by forwarding to a field.
2///
3/// The formatter is passed through unchanged. Emitted code supports `no_std`.
4/// Omit the field for a tuple newtype. All type parameters receive a `Debug` bound.
5///
6/// # Examples
7///
8/// With a newtype struct:
9///
10/// ```
11/// struct Value(u32);
12///
13/// impl_more::forward_debug!(Value);
14///
15/// assert_eq!(
16///     format!("{:?}", Value(42)),
17///     "42",
18/// );
19/// ```
20///
21/// With a generic newtype struct:
22///
23/// ```
24/// struct Value<T>(T);
25///
26/// impl_more::forward_debug!(<T> in Value<T>);
27///
28/// let inner = 42u32;
29///
30/// assert_eq!(
31///     format!("{:?}", Value(inner)),
32///     "42",
33/// );
34/// ```
35///
36/// Select a named field with `=> field`:
37///
38/// ```
39/// struct Value {
40///     inner: u32,
41/// }
42///
43/// impl_more::forward_debug!(Value => inner);
44///
45/// let value = Value { inner: 42 };
46///
47/// assert_eq!(
48///     format!("{:?}", value),
49///     "42",
50/// );
51/// ```
52#[macro_export]
53macro_rules! forward_debug {
54    (<$($generic:ident),+> in $this:ty => $field:tt $(,)?) => {
55        impl <$($generic: ::core::fmt::Debug),+> ::core::fmt::Debug for $this {
56            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
57                ::core::fmt::Debug::fmt(&self.$field, fmt)
58            }
59        }
60    };
61    (<$($generic:ident),+> in $this:ty $(,)?) => {
62        impl <$($generic: ::core::fmt::Debug),+> ::core::fmt::Debug for $this {
63            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
64                ::core::fmt::Debug::fmt(&self.0, fmt)
65            }
66        }
67    };
68    ($this:ty => $field:tt $(,)?) => {
69        impl ::core::fmt::Debug for $this {
70            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
71                ::core::fmt::Debug::fmt(&self.$field, fmt)
72            }
73        }
74    };
75    ($this:ty $(,)?) => {
76        impl ::core::fmt::Debug for $this {
77            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
78                ::core::fmt::Debug::fmt(&self.0, fmt)
79            }
80        }
81    };
82}
83
84/// Implement [`Binary`](core::fmt::Binary) by forwarding to a field.
85///
86/// The formatter is passed through unchanged. Emitted code supports `no_std`.
87/// Omit the field for a tuple newtype. All type parameters receive a `Binary` bound.
88///
89/// # Examples
90///
91/// With a newtype struct:
92///
93/// ```
94/// struct Value(u32);
95///
96/// impl_more::forward_binary!(Value);
97///
98/// assert_eq!(
99///     format!("{:b}", Value(42)),
100///     "101010",
101/// );
102/// ```
103///
104/// With a generic newtype struct:
105///
106/// ```
107/// struct Value<T>(T);
108///
109/// impl_more::forward_binary!(<T> in Value<T>);
110///
111/// let inner = 42u32;
112///
113/// assert_eq!(
114///     format!("{:b}", Value(inner)),
115///     "101010",
116/// );
117/// ```
118///
119/// Select a named field with `=> field`:
120///
121/// ```
122/// struct Value {
123///     inner: u32,
124/// }
125///
126/// impl_more::forward_binary!(Value => inner);
127///
128/// let value = Value { inner: 42 };
129///
130/// assert_eq!(
131///     format!("{:b}", value),
132///     "101010",
133/// );
134/// ```
135#[macro_export]
136macro_rules! forward_binary {
137    (<$($generic:ident),+> in $this:ty => $field:tt $(,)?) => {
138        impl <$($generic: ::core::fmt::Binary),+> ::core::fmt::Binary for $this {
139            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
140                ::core::fmt::Binary::fmt(&self.$field, fmt)
141            }
142        }
143    };
144    (<$($generic:ident),+> in $this:ty $(,)?) => {
145        impl <$($generic: ::core::fmt::Binary),+> ::core::fmt::Binary for $this {
146            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
147                ::core::fmt::Binary::fmt(&self.0, fmt)
148            }
149        }
150    };
151    ($this:ty => $field:tt $(,)?) => {
152        impl ::core::fmt::Binary for $this {
153            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
154                ::core::fmt::Binary::fmt(&self.$field, fmt)
155            }
156        }
157    };
158    ($this:ty $(,)?) => {
159        impl ::core::fmt::Binary for $this {
160            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
161                ::core::fmt::Binary::fmt(&self.0, fmt)
162            }
163        }
164    };
165}
166
167/// Implement [`Octal`](core::fmt::Octal) by forwarding to a field.
168///
169/// The formatter is passed through unchanged. Emitted code supports `no_std`.
170/// Omit the field for a tuple newtype. All type parameters receive a `Octal` bound.
171///
172/// # Examples
173///
174/// With a newtype struct:
175///
176/// ```
177/// struct Value(u32);
178///
179/// impl_more::forward_octal!(Value);
180///
181/// assert_eq!(
182///     format!("{:o}", Value(42)),
183///     "52",
184/// );
185/// ```
186///
187/// With a generic newtype struct:
188///
189/// ```
190/// struct Value<T>(T);
191///
192/// impl_more::forward_octal!(<T> in Value<T>);
193///
194/// let inner = 42u32;
195///
196/// assert_eq!(
197///     format!("{:o}", Value(inner)),
198///     "52",
199/// );
200/// ```
201///
202/// Select a named field with `=> field`:
203///
204/// ```
205/// struct Value {
206///     inner: u32,
207/// }
208///
209/// impl_more::forward_octal!(Value => inner);
210///
211/// let value = Value { inner: 42 };
212///
213/// assert_eq!(
214///     format!("{:o}", value),
215///     "52",
216/// );
217/// ```
218#[macro_export]
219macro_rules! forward_octal {
220    (<$($generic:ident),+> in $this:ty => $field:tt $(,)?) => {
221        impl <$($generic: ::core::fmt::Octal),+> ::core::fmt::Octal for $this {
222            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
223                ::core::fmt::Octal::fmt(&self.$field, fmt)
224            }
225        }
226    };
227    (<$($generic:ident),+> in $this:ty $(,)?) => {
228        impl <$($generic: ::core::fmt::Octal),+> ::core::fmt::Octal for $this {
229            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
230                ::core::fmt::Octal::fmt(&self.0, fmt)
231            }
232        }
233    };
234    ($this:ty => $field:tt $(,)?) => {
235        impl ::core::fmt::Octal for $this {
236            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
237                ::core::fmt::Octal::fmt(&self.$field, fmt)
238            }
239        }
240    };
241    ($this:ty $(,)?) => {
242        impl ::core::fmt::Octal for $this {
243            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
244                ::core::fmt::Octal::fmt(&self.0, fmt)
245            }
246        }
247    };
248}
249
250/// Implement [`LowerHex`](core::fmt::LowerHex) by forwarding to a field.
251///
252/// The formatter is passed through unchanged. Emitted code supports `no_std`.
253/// Omit the field for a tuple newtype. All type parameters receive a `LowerHex` bound.
254///
255/// # Examples
256///
257/// With a newtype struct:
258///
259/// ```
260/// struct Value(u32);
261///
262/// impl_more::forward_lower_hex!(Value);
263///
264/// assert_eq!(
265///     format!("{:x}", Value(42)),
266///     "2a",
267/// );
268/// ```
269///
270/// With a generic newtype struct:
271///
272/// ```
273/// struct Value<T>(T);
274///
275/// impl_more::forward_lower_hex!(<T> in Value<T>);
276///
277/// let inner = 42u32;
278///
279/// assert_eq!(
280///     format!("{:x}", Value(inner)),
281///     "2a",
282/// );
283/// ```
284///
285/// Select a named field with `=> field`:
286///
287/// ```
288/// struct Value {
289///     inner: u32,
290/// }
291///
292/// impl_more::forward_lower_hex!(Value => inner);
293///
294/// let value = Value { inner: 42 };
295///
296/// assert_eq!(
297///     format!("{:x}", value),
298///     "2a",
299/// );
300/// ```
301#[macro_export]
302macro_rules! forward_lower_hex {
303    (<$($generic:ident),+> in $this:ty => $field:tt $(,)?) => {
304        impl <$($generic: ::core::fmt::LowerHex),+> ::core::fmt::LowerHex for $this {
305            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
306                ::core::fmt::LowerHex::fmt(&self.$field, fmt)
307            }
308        }
309    };
310    (<$($generic:ident),+> in $this:ty $(,)?) => {
311        impl <$($generic: ::core::fmt::LowerHex),+> ::core::fmt::LowerHex for $this {
312            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
313                ::core::fmt::LowerHex::fmt(&self.0, fmt)
314            }
315        }
316    };
317    ($this:ty => $field:tt $(,)?) => {
318        impl ::core::fmt::LowerHex for $this {
319            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
320                ::core::fmt::LowerHex::fmt(&self.$field, fmt)
321            }
322        }
323    };
324    ($this:ty $(,)?) => {
325        impl ::core::fmt::LowerHex for $this {
326            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
327                ::core::fmt::LowerHex::fmt(&self.0, fmt)
328            }
329        }
330    };
331}
332
333/// Implement [`UpperHex`](core::fmt::UpperHex) by forwarding to a field.
334///
335/// The formatter is passed through unchanged. Emitted code supports `no_std`.
336/// Omit the field for a tuple newtype. All type parameters receive a `UpperHex` bound.
337///
338/// # Examples
339///
340/// With a newtype struct:
341///
342/// ```
343/// struct Value(u32);
344///
345/// impl_more::forward_upper_hex!(Value);
346///
347/// assert_eq!(
348///     format!("{:X}", Value(42)),
349///     "2A",
350/// );
351/// ```
352///
353/// With a generic newtype struct:
354///
355/// ```
356/// struct Value<T>(T);
357///
358/// impl_more::forward_upper_hex!(<T> in Value<T>);
359///
360/// let inner = 42u32;
361///
362/// assert_eq!(
363///     format!("{:X}", Value(inner)),
364///     "2A",
365/// );
366/// ```
367///
368/// Select a named field with `=> field`:
369///
370/// ```
371/// struct Value {
372///     inner: u32,
373/// }
374///
375/// impl_more::forward_upper_hex!(Value => inner);
376///
377/// let value = Value { inner: 42 };
378///
379/// assert_eq!(
380///     format!("{:X}", value),
381///     "2A",
382/// );
383/// ```
384#[macro_export]
385macro_rules! forward_upper_hex {
386    (<$($generic:ident),+> in $this:ty => $field:tt $(,)?) => {
387        impl <$($generic: ::core::fmt::UpperHex),+> ::core::fmt::UpperHex for $this {
388            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
389                ::core::fmt::UpperHex::fmt(&self.$field, fmt)
390            }
391        }
392    };
393    (<$($generic:ident),+> in $this:ty $(,)?) => {
394        impl <$($generic: ::core::fmt::UpperHex),+> ::core::fmt::UpperHex for $this {
395            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
396                ::core::fmt::UpperHex::fmt(&self.0, fmt)
397            }
398        }
399    };
400    ($this:ty => $field:tt $(,)?) => {
401        impl ::core::fmt::UpperHex for $this {
402            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
403                ::core::fmt::UpperHex::fmt(&self.$field, fmt)
404            }
405        }
406    };
407    ($this:ty $(,)?) => {
408        impl ::core::fmt::UpperHex for $this {
409            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
410                ::core::fmt::UpperHex::fmt(&self.0, fmt)
411            }
412        }
413    };
414}
415
416/// Implement [`LowerExp`](core::fmt::LowerExp) by forwarding to a field.
417///
418/// The formatter is passed through unchanged. Emitted code supports `no_std`.
419/// Omit the field for a tuple newtype. All type parameters receive a `LowerExp` bound.
420///
421/// # Examples
422///
423/// With a newtype struct:
424///
425/// ```
426/// struct Value(u32);
427///
428/// impl_more::forward_lower_exp!(Value);
429///
430/// assert_eq!(
431///     format!("{:e}", Value(42)),
432///     "4.2e1",
433/// );
434/// ```
435///
436/// With a generic newtype struct:
437///
438/// ```
439/// struct Value<T>(T);
440///
441/// impl_more::forward_lower_exp!(<T> in Value<T>);
442///
443/// let inner = 42u32;
444///
445/// assert_eq!(
446///     format!("{:e}", Value(inner)),
447///     "4.2e1",
448/// );
449/// ```
450///
451/// Select a named field with `=> field`:
452///
453/// ```
454/// struct Value {
455///     inner: u32,
456/// }
457///
458/// impl_more::forward_lower_exp!(Value => inner);
459///
460/// let value = Value { inner: 42 };
461///
462/// assert_eq!(
463///     format!("{:e}", value),
464///     "4.2e1",
465/// );
466/// ```
467#[macro_export]
468macro_rules! forward_lower_exp {
469    (<$($generic:ident),+> in $this:ty => $field:tt $(,)?) => {
470        impl <$($generic: ::core::fmt::LowerExp),+> ::core::fmt::LowerExp for $this {
471            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
472                ::core::fmt::LowerExp::fmt(&self.$field, fmt)
473            }
474        }
475    };
476    (<$($generic:ident),+> in $this:ty $(,)?) => {
477        impl <$($generic: ::core::fmt::LowerExp),+> ::core::fmt::LowerExp for $this {
478            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
479                ::core::fmt::LowerExp::fmt(&self.0, fmt)
480            }
481        }
482    };
483    ($this:ty => $field:tt $(,)?) => {
484        impl ::core::fmt::LowerExp for $this {
485            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
486                ::core::fmt::LowerExp::fmt(&self.$field, fmt)
487            }
488        }
489    };
490    ($this:ty $(,)?) => {
491        impl ::core::fmt::LowerExp for $this {
492            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
493                ::core::fmt::LowerExp::fmt(&self.0, fmt)
494            }
495        }
496    };
497}
498
499/// Implement [`UpperExp`](core::fmt::UpperExp) by forwarding to a field.
500///
501/// The formatter is passed through unchanged. Emitted code supports `no_std`.
502/// Omit the field for a tuple newtype. All type parameters receive a `UpperExp` bound.
503///
504/// # Examples
505///
506/// With a newtype struct:
507///
508/// ```
509/// struct Value(u32);
510///
511/// impl_more::forward_upper_exp!(Value);
512///
513/// assert_eq!(
514///     format!("{:E}", Value(42)),
515///     "4.2E1",
516/// );
517/// ```
518///
519/// With a generic newtype struct:
520///
521/// ```
522/// struct Value<T>(T);
523///
524/// impl_more::forward_upper_exp!(<T> in Value<T>);
525///
526/// let inner = 42u32;
527///
528/// assert_eq!(
529///     format!("{:E}", Value(inner)),
530///     "4.2E1",
531/// );
532/// ```
533///
534/// Select a named field with `=> field`:
535///
536/// ```
537/// struct Value {
538///     inner: u32,
539/// }
540///
541/// impl_more::forward_upper_exp!(Value => inner);
542///
543/// let value = Value { inner: 42 };
544///
545/// assert_eq!(
546///     format!("{:E}", value),
547///     "4.2E1",
548/// );
549/// ```
550#[macro_export]
551macro_rules! forward_upper_exp {
552    (<$($generic:ident),+> in $this:ty => $field:tt $(,)?) => {
553        impl <$($generic: ::core::fmt::UpperExp),+> ::core::fmt::UpperExp for $this {
554            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
555                ::core::fmt::UpperExp::fmt(&self.$field, fmt)
556            }
557        }
558    };
559    (<$($generic:ident),+> in $this:ty $(,)?) => {
560        impl <$($generic: ::core::fmt::UpperExp),+> ::core::fmt::UpperExp for $this {
561            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
562                ::core::fmt::UpperExp::fmt(&self.0, fmt)
563            }
564        }
565    };
566    ($this:ty => $field:tt $(,)?) => {
567        impl ::core::fmt::UpperExp for $this {
568            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
569                ::core::fmt::UpperExp::fmt(&self.$field, fmt)
570            }
571        }
572    };
573    ($this:ty $(,)?) => {
574        impl ::core::fmt::UpperExp for $this {
575            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
576                ::core::fmt::UpperExp::fmt(&self.0, fmt)
577            }
578        }
579    };
580}
581
582/// Implement [`Pointer`](core::fmt::Pointer) by forwarding to a field.
583///
584/// The formatter is passed through unchanged. Emitted code supports `no_std`.
585/// Omit the field for a tuple newtype. All type parameters receive a `Pointer` bound.
586///
587/// # Examples
588///
589/// With a newtype struct:
590///
591/// ```
592/// struct Value(*const i32);
593///
594/// impl_more::forward_pointer!(Value);
595///
596/// assert_eq!(
597///     format!("{:p}", Value(core::ptr::null())),
598///     "0x0",
599/// );
600/// ```
601///
602/// With a generic newtype struct:
603///
604/// ```
605/// struct Value<T>(T);
606///
607/// impl_more::forward_pointer!(<T> in Value<T>);
608///
609/// let inner = core::ptr::null::<i32>();
610///
611/// assert_eq!(
612///     format!("{:p}", Value(inner)),
613///     "0x0",
614/// );
615/// ```
616///
617/// Select a named field with `=> field`:
618///
619/// ```
620/// struct Value {
621///     inner: *const i32,
622/// }
623///
624/// impl_more::forward_pointer!(Value => inner);
625///
626/// let value = Value { inner: core::ptr::null() };
627///
628/// assert_eq!(
629///     format!("{:p}", value),
630///     "0x0",
631/// );
632/// ```
633#[macro_export]
634macro_rules! forward_pointer {
635    (<$($generic:ident),+> in $this:ty => $field:tt $(,)?) => {
636        impl <$($generic: ::core::fmt::Pointer),+> ::core::fmt::Pointer for $this {
637            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
638                ::core::fmt::Pointer::fmt(&self.$field, fmt)
639            }
640        }
641    };
642    (<$($generic:ident),+> in $this:ty $(,)?) => {
643        impl <$($generic: ::core::fmt::Pointer),+> ::core::fmt::Pointer for $this {
644            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
645                ::core::fmt::Pointer::fmt(&self.0, fmt)
646            }
647        }
648    };
649    ($this:ty => $field:tt $(,)?) => {
650        impl ::core::fmt::Pointer for $this {
651            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
652                ::core::fmt::Pointer::fmt(&self.$field, fmt)
653            }
654        }
655    };
656    ($this:ty $(,)?) => {
657        impl ::core::fmt::Pointer for $this {
658            fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
659                ::core::fmt::Pointer::fmt(&self.0, fmt)
660            }
661        }
662    };
663}
664
665#[cfg(test)]
666mod tests {
667    use alloc::{format, string::String, vec};
668
669    #[test]
670    fn debug_forwards_formatter_and_fields() {
671        struct Tuple(u32);
672        struct Named {
673            inner: u32,
674        }
675        struct Generic<T>(T);
676        struct GenericNamed<T> {
677            inner: T,
678        }
679        crate::forward_debug!(Tuple,);
680        crate::forward_debug!(Named => inner,);
681        crate::forward_debug!(<T> in Generic<T>);
682        crate::forward_debug!(<T> in GenericNamed<T> => inner);
683        let inner = 42u32;
684        let expected = format!("{:#012?}", inner);
685        assert_eq!(format!("{:#012?}", Tuple(inner)), expected);
686        assert_eq!(format!("{:#012?}", Named { inner }), expected);
687        assert_eq!(format!("{:#012?}", Generic(inner)), expected);
688        assert_eq!(format!("{:#012?}", GenericNamed { inner }), expected);
689    }
690
691    #[test]
692    fn binary_forwards_formatter_and_fields() {
693        struct Tuple(u32);
694        struct Named {
695            inner: u32,
696        }
697        struct Generic<T>(T);
698        struct GenericNamed<T> {
699            inner: T,
700        }
701        crate::forward_binary!(Tuple,);
702        crate::forward_binary!(Named => inner,);
703        crate::forward_binary!(<T> in Generic<T>);
704        crate::forward_binary!(<T> in GenericNamed<T> => inner);
705        let inner = 42u32;
706        let expected = format!("{:#012b}", inner);
707        assert_eq!(format!("{:#012b}", Tuple(inner)), expected);
708        assert_eq!(format!("{:#012b}", Named { inner }), expected);
709        assert_eq!(format!("{:#012b}", Generic(inner)), expected);
710        assert_eq!(format!("{:#012b}", GenericNamed { inner }), expected);
711    }
712
713    #[test]
714    fn octal_forwards_formatter_and_fields() {
715        struct Tuple(u32);
716        struct Named {
717            inner: u32,
718        }
719        struct Generic<T>(T);
720        struct GenericNamed<T> {
721            inner: T,
722        }
723        crate::forward_octal!(Tuple,);
724        crate::forward_octal!(Named => inner,);
725        crate::forward_octal!(<T> in Generic<T>);
726        crate::forward_octal!(<T> in GenericNamed<T> => inner);
727        let inner = 42u32;
728        let expected = format!("{:#012o}", inner);
729        assert_eq!(format!("{:#012o}", Tuple(inner)), expected);
730        assert_eq!(format!("{:#012o}", Named { inner }), expected);
731        assert_eq!(format!("{:#012o}", Generic(inner)), expected);
732        assert_eq!(format!("{:#012o}", GenericNamed { inner }), expected);
733    }
734
735    #[test]
736    fn lower_hex_forwards_formatter_and_fields() {
737        struct Tuple(u32);
738        struct Named {
739            inner: u32,
740        }
741        struct Generic<T>(T);
742        struct GenericNamed<T> {
743            inner: T,
744        }
745        crate::forward_lower_hex!(Tuple,);
746        crate::forward_lower_hex!(Named => inner,);
747        crate::forward_lower_hex!(<T> in Generic<T>);
748        crate::forward_lower_hex!(<T> in GenericNamed<T> => inner);
749        let inner = 42u32;
750        let expected = format!("{:#012x}", inner);
751        assert_eq!(format!("{:#012x}", Tuple(inner)), expected);
752        assert_eq!(format!("{:#012x}", Named { inner }), expected);
753        assert_eq!(format!("{:#012x}", Generic(inner)), expected);
754        assert_eq!(format!("{:#012x}", GenericNamed { inner }), expected);
755    }
756
757    #[test]
758    fn upper_hex_forwards_formatter_and_fields() {
759        struct Tuple(u32);
760        struct Named {
761            inner: u32,
762        }
763        struct Generic<T>(T);
764        struct GenericNamed<T> {
765            inner: T,
766        }
767        crate::forward_upper_hex!(Tuple,);
768        crate::forward_upper_hex!(Named => inner,);
769        crate::forward_upper_hex!(<T> in Generic<T>);
770        crate::forward_upper_hex!(<T> in GenericNamed<T> => inner);
771        let inner = 42u32;
772        let expected = format!("{:#012X}", inner);
773        assert_eq!(format!("{:#012X}", Tuple(inner)), expected);
774        assert_eq!(format!("{:#012X}", Named { inner }), expected);
775        assert_eq!(format!("{:#012X}", Generic(inner)), expected);
776        assert_eq!(format!("{:#012X}", GenericNamed { inner }), expected);
777    }
778
779    #[test]
780    fn lower_exp_forwards_formatter_and_fields() {
781        struct Tuple(u32);
782        struct Named {
783            inner: u32,
784        }
785        struct Generic<T>(T);
786        struct GenericNamed<T> {
787            inner: T,
788        }
789        crate::forward_lower_exp!(Tuple,);
790        crate::forward_lower_exp!(Named => inner,);
791        crate::forward_lower_exp!(<T> in Generic<T>);
792        crate::forward_lower_exp!(<T> in GenericNamed<T> => inner);
793        let inner = 42u32;
794        let expected = format!("{:#012e}", inner);
795        assert_eq!(format!("{:#012e}", Tuple(inner)), expected);
796        assert_eq!(format!("{:#012e}", Named { inner }), expected);
797        assert_eq!(format!("{:#012e}", Generic(inner)), expected);
798        assert_eq!(format!("{:#012e}", GenericNamed { inner }), expected);
799    }
800
801    #[test]
802    fn upper_exp_forwards_formatter_and_fields() {
803        struct Tuple(u32);
804        struct Named {
805            inner: u32,
806        }
807        struct Generic<T>(T);
808        struct GenericNamed<T> {
809            inner: T,
810        }
811        crate::forward_upper_exp!(Tuple,);
812        crate::forward_upper_exp!(Named => inner,);
813        crate::forward_upper_exp!(<T> in Generic<T>);
814        crate::forward_upper_exp!(<T> in GenericNamed<T> => inner);
815        let inner = 42u32;
816        let expected = format!("{:#012E}", inner);
817        assert_eq!(format!("{:#012E}", Tuple(inner)), expected);
818        assert_eq!(format!("{:#012E}", Named { inner }), expected);
819        assert_eq!(format!("{:#012E}", Generic(inner)), expected);
820        assert_eq!(format!("{:#012E}", GenericNamed { inner }), expected);
821    }
822
823    #[test]
824    fn pointer_forwards_formatter_and_fields() {
825        struct Tuple(*const i32);
826        struct Named {
827            inner: *const i32,
828        }
829        struct Generic<T>(T);
830        struct GenericNamed<T> {
831            inner: T,
832        }
833        crate::forward_pointer!(Tuple,);
834        crate::forward_pointer!(Named => inner,);
835        crate::forward_pointer!(<T> in Generic<T>);
836        crate::forward_pointer!(<T> in GenericNamed<T> => inner);
837        let inner = &42 as *const i32;
838        let expected = format!("{:#012p}", inner);
839        assert_eq!(format!("{:#012p}", Tuple(inner)), expected);
840        assert_eq!(format!("{:#012p}", Named { inner }), expected);
841        assert_eq!(format!("{:#012p}", Generic(inner)), expected);
842        assert_eq!(format!("{:#012p}", GenericNamed { inner }), expected);
843    }
844
845    #[test]
846    fn debug_preserves_pretty_layout_and_precision() {
847        struct Value<T>(T);
848        crate::forward_debug!(<T> in Value<T>);
849        assert_eq!(
850            format!("{:#?}", Value(vec![1, 2])),
851            format!("{:#?}", vec![1, 2])
852        );
853        assert_eq!(
854            format!("{:>12.3?}", Value(1.23456)),
855            format!("{:>12.3?}", 1.23456)
856        );
857    }
858
859    #[test]
860    fn forwards_format_errors() {
861        struct Fails;
862        impl core::fmt::LowerHex for Fails {
863            fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
864                Err(core::fmt::Error)
865            }
866        }
867        struct Value(Fails);
868        crate::forward_lower_hex!(Value);
869        let mut output = String::new();
870        assert!(core::fmt::write(&mut output, format_args!("{:x}", Value(Fails))).is_err());
871    }
872}