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