powerfmt/
smart_display.rs

1//! Definition of [`SmartDisplay`] and its related items.
2//!
3//! [`SmartDisplay`] is a trait that allows authors to provide additional information to both the
4//! formatter and other users. This information is provided in the form of a metadata type. The only
5//! required piece of metadata is the width of the value. This is _before_ it is passed to the
6//! formatter (i.e. it does not include any padding added by the formatter). Other information
7//! can be stored in a custom metadata type as needed. This information may be made available to
8//! downstream users, but it is not required.
9//!
10//! This module contains the [`SmartDisplay`] and associated items.
11//!
12//! # Example
13//!
14//! ```rust
15//! use std::fmt;
16//!
17//! use powerfmt::ext::FormatterExt as _;
18//! use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
19//!
20//! #[derive(Debug)]
21//! struct User {
22//!     id: usize,
23//! }
24//!
25//! // If you try to use `UserMetadata` in the `SmartDisplay` implementation, you will get a
26//! // compiler error about a private type being used publicly. To avoid this, use this attribute to
27//! // declare a private metadata type. You shouldn't need to worry about how this works, but be
28//! // aware that any public fields or methods remain usable by downstream users.
29//! #[smart_display::private_metadata]
30//! struct UserMetadata {
31//!     username: String,
32//!     legal_name: String,
33//! }
34//!
35//! // This attribute can be applied to `SmartDisplay` implementations. It will generate an
36//! // implementation of `Display` that delegates to `SmartDisplay`, avoiding the need to write
37//! // boilerplate.
38//! #[smart_display::delegate]
39//! impl SmartDisplay for User {
40//!     type Metadata = UserMetadata;
41//!
42//!     fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
43//!         // This could be obtained from a database, for example.
44//!         let legal_name = "John Doe".to_owned();
45//!         let username = "jdoe".to_owned();
46//!
47//!         // Note that this must be kept in sync with the implementation of `fmt_with_metadata`.
48//!         let width = smart_display::padded_width_of!(username, " (", legal_name, ")",);
49//!
50//!         Metadata::new(
51//!             width,
52//!             self,
53//!             UserMetadata {
54//!                 username,
55//!                 legal_name,
56//!             },
57//!         )
58//!     }
59//!
60//!     // Use the now-generated metadata to format the value. Here we use the `pad_with_width`
61//!     // method to use the alignment and desired width from the formatter.
62//!     fn fmt_with_metadata(
63//!         &self,
64//!         f: &mut fmt::Formatter<'_>,
65//!         metadata: Metadata<Self>,
66//!     ) -> fmt::Result {
67//!         f.pad_with_width(
68//!             metadata.unpadded_width(),
69//!             format_args!("{} ({})", metadata.username, metadata.legal_name),
70//!         )
71//!     }
72//! }
73//!
74//! let user = User { id: 42 };
75//! assert_eq!(user.to_string(), "jdoe (John Doe)");
76//! assert_eq!(format!("{user:>20}"), "     jdoe (John Doe)");
77//! ```
78
79use core::cmp;
80use core::convert::Infallible;
81use core::fmt::{Alignment, Debug, Display, Formatter, Result};
82use core::marker::PhantomData;
83use core::mem::MaybeUninit;
84use core::ops::Deref;
85
86/// Compute the width of multiple items while optionally declaring the options for each item.
87///
88/// ```rust
89/// # use powerfmt::smart_display;
90/// let alpha = 0;
91/// let beta = 1;
92/// let gamma = 100;
93///
94/// let width = smart_display::padded_width_of!(
95///     alpha, // use the default options
96///     beta => width(2), // use the specified options
97///     gamma => width(2) sign_plus(true), // use multiple options
98/// );
99/// assert_eq!(width, 7);
100///
101/// let formatted = format!("{alpha}{beta:2}{gamma:+2}");
102/// assert_eq!(formatted.len(), width);
103/// ```
104///
105/// Supported options are:
106///
107/// Option                      | Method called
108/// ---                         | ---
109/// `fill(char)`                | [`FormatterOptions::with_fill`]
110/// `sign_plus(bool)`           | [`FormatterOptions::with_sign_plus`]
111/// `sign_minus(bool)`          | [`FormatterOptions::with_sign_minus`]
112/// `align(Alignment)`          | [`FormatterOptions::with_align`]
113/// `width(usize)`              | [`FormatterOptions::with_width`]
114/// `precision(usize)`          | [`FormatterOptions::with_precision`]
115/// `alternate(bool)`           | [`FormatterOptions::with_alternate`]
116/// `sign_aware_zero_pad(bool)` | [`FormatterOptions::with_sign_aware_zero_pad`]
117///
118/// If there are future additions to [`FormatterOptions`], they will be added to this macro as well.
119///
120/// Options may be provided in any order and will be called in the order they are provided. The
121/// ordering matters if providing both `sign_plus` and `sign_minus`.
122#[cfg(doc)]
123#[doc(hidden)] // Don't show at crate root.
124#[macro_export]
125macro_rules! padded_width_of {
126    ($($t:tt)*) => {};
127}
128
129#[cfg(not(doc))]
130#[allow(missing_docs)] // This is done with `#[cfg(doc)]` to avoid showing the various rules.
131#[macro_export]
132macro_rules! __not_public_at_root__padded_width_of {
133    // Base case
134    (@inner [] [$($output:tt)+]) => { $($output)+ };
135    (@inner [$e:expr $(, $($remaining:tt)*)?] [$($expansion:tt)+]) => {
136        $crate::smart_display::padded_width_of!(@inner [$($($remaining)*)?] [
137            $($expansion)+ + $crate::smart_display::Metadata::padded_width_of(
138                &$e,
139                $crate::smart_display::padded_width_of!(@options)
140            )
141        ])
142    };
143    (@inner
144        [$e:expr => $($call:ident($call_expr:expr))+ $(, $($remaining:tt)*)?]
145        [$($expansion:tt)+]
146    ) => {
147        $crate::smart_display::padded_width_of!(@inner [$($($remaining)*)?] [
148            $($expansion)+ + $crate::smart_display::Metadata::padded_width_of(
149                &$e,
150                *$crate::smart_display::padded_width_of!(@options $($call($call_expr))+)
151            )
152        ])
153    };
154
155    // Options base case
156    (@options_inner [] [$($output:tt)+]) => { $($output)+ };
157    (@options_inner [fill($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
158        $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
159            $($expansion)*.with_fill($e)
160        ])
161    };
162    (@options_inner [sign_plus($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
163        $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
164            $($expansion)*.with_sign_plus($e)
165        ])
166    };
167    (@options_inner [sign_minus($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
168        $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
169            $($expansion)*.with_sign_minus($e)
170        ])
171    };
172    (@options_inner [align($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
173        $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
174            $($expansion)*.with_align(Some($e))
175        ])
176    };
177    (@options_inner [width($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
178        $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
179            $($expansion)*.with_width(Some($e))
180        ])
181    };
182    (@options_inner [precision($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
183        $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
184            $($expansion)*.with_precision(Some($e))
185        ])
186    };
187    (@options_inner [alternate($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
188        $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
189            $($expansion)*.with_width($e)
190        ])
191    };
192    (@options_inner [sign_aware_zero_pad($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
193        $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
194            $($expansion)*.with_sign_aware_zero_pad($e)
195        ])
196    };
197    // Options entry point
198    (@options $($e:tt)*) => {
199        $crate::smart_display::padded_width_of!(@options_inner [$($e)*] [
200            $crate::smart_display::FormatterOptions::default()
201        ])
202    };
203
204    // Entry point
205    ($($t:tt)*) => {
206        $crate::smart_display::padded_width_of!(
207            @inner [$($t)*] [0]
208        )
209    };
210}
211
212#[cfg(not(doc))]
213pub use __not_public_at_root__padded_width_of as padded_width_of;
214#[cfg(doc)]
215#[doc(inline)] // Show in this module.
216pub use padded_width_of;
217/// Implement [`Display`] for a type by using its implementation of [`SmartDisplay`].
218///
219/// This attribute is applied to the `SmartDisplay` implementation.
220///
221/// ```rust,no_run
222/// # use powerfmt::smart_display::{self, SmartDisplay, Metadata, FormatterOptions};
223/// # struct Foo;
224/// #[smart_display::delegate]
225/// impl SmartDisplay for Foo {
226/// #   type Metadata = ();
227/// #   fn metadata(&self, f: FormatterOptions) -> Metadata<Self> {
228/// #       todo!()
229/// #   }
230///     // ...
231/// }
232/// ```
233#[cfg(feature = "macros")]
234pub use powerfmt_macros::smart_display_delegate as delegate;
235/// Declare a private metadata type for `SmartDisplay`.
236///
237/// Use this attribute if you want to provide metadata for a type that is not public. Doing
238/// this will avoid a compiler error about a private type being used publicly. Keep in mind
239/// that any public fields, public methods, and trait implementations _will_ be able to be used
240/// by downstream users.
241///
242/// To avoid accidentally exposing details, such as when all fields are public or if the type
243/// is a unit struct, the type is annotated with `#[non_exhaustive]` automatically.
244///
245/// ```rust,no_run
246/// # use powerfmt::smart_display;
247/// /// Metadata for `Foo`
248/// #[smart_display::private_metadata]
249/// #[derive(Debug)]
250/// pub(crate) struct FooMetadata {
251///     pub(crate) expensive_to_calculate: usize,
252/// }
253/// ```
254#[cfg(feature = "macros")]
255pub use powerfmt_macros::smart_display_private_metadata as private_metadata;
256
257#[derive(Debug)]
258enum FlagBit {
259    SignPlus,
260    SignMinus,
261    Alternate,
262    SignAwareZeroPad,
263    WidthIsInitialized,
264    PrecisionIsInitialized,
265}
266
267/// Configuration for formatting.
268///
269/// This struct is obtained from a [`Formatter`]. It provides the same functionality as that of a
270/// reference to a `Formatter`. However, it is not possible to construct a `Formatter`, which is
271/// necessary for some use cases of [`SmartDisplay`]. `FormatterOptions` implements [`Default`] and
272/// has builder methods to alleviate this.
273#[derive(Clone, Copy)]
274pub struct FormatterOptions {
275    flags: u8,
276    fill: char,
277    align: Option<Alignment>,
278    width: MaybeUninit<usize>,
279    precision: MaybeUninit<usize>,
280}
281
282impl Debug for FormatterOptions {
283    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
284        f.debug_struct("FormatterOptions")
285            .field("fill", &self.fill)
286            .field("align", &self.align())
287            .field("width", &self.width())
288            .field("precision", &self.precision())
289            .field("sign_plus", &self.sign_plus())
290            .field("sign_minus", &self.sign_minus())
291            .field("alternate", &self.alternate())
292            .field("sign_aware_zero_pad", &self.sign_aware_zero_pad())
293            .finish()
294    }
295}
296
297impl Default for FormatterOptions {
298    #[inline]
299    fn default() -> Self {
300        Self {
301            flags: 0,
302            fill: ' ',
303            align: None,
304            width: MaybeUninit::uninit(),
305            precision: MaybeUninit::uninit(),
306        }
307    }
308}
309
310impl FormatterOptions {
311    /// Sets the fill character to use whenever there is alignment.
312    #[inline]
313    pub fn with_fill(&mut self, c: char) -> &mut Self {
314        self.fill = c;
315        self
316    }
317
318    /// Set whether the `+` flag is specified.
319    #[inline]
320    pub fn with_sign_plus(&mut self, b: bool) -> &mut Self {
321        if b {
322            self.flags |= 1 << FlagBit::SignPlus as u8;
323            self.flags &= !(1 << FlagBit::SignMinus as u8);
324        } else {
325            self.flags &= !(1 << FlagBit::SignPlus as u8);
326        }
327        self
328    }
329
330    /// Set whether the `-` flag is specified.
331    #[inline]
332    pub fn with_sign_minus(&mut self, b: bool) -> &mut Self {
333        if b {
334            self.flags |= 1 << FlagBit::SignMinus as u8;
335            self.flags &= !(1 << FlagBit::SignPlus as u8);
336        } else {
337            self.flags &= !(1 << FlagBit::SignMinus as u8);
338        }
339        self
340    }
341
342    /// Set the flag indicating what form of alignment is requested, if any.
343    #[inline]
344    pub fn with_align(&mut self, align: Option<Alignment>) -> &mut Self {
345        self.align = align;
346        self
347    }
348
349    /// Set the optional integer width that the output should be.
350    #[inline]
351    pub fn with_width(&mut self, width: Option<usize>) -> &mut Self {
352        if let Some(width) = width {
353            self.flags |= 1 << FlagBit::WidthIsInitialized as u8;
354            self.width = MaybeUninit::new(width);
355        } else {
356            self.flags &= !(1 << FlagBit::WidthIsInitialized as u8);
357        }
358        self
359    }
360
361    /// Set the optional precision for numeric types. Alternatively, the maximum width for string
362    /// types.
363    #[inline]
364    pub fn with_precision(&mut self, precision: Option<usize>) -> &mut Self {
365        if let Some(precision) = precision {
366            self.flags |= 1 << FlagBit::PrecisionIsInitialized as u8;
367            self.precision = MaybeUninit::new(precision);
368        } else {
369            self.flags &= !(1 << FlagBit::PrecisionIsInitialized as u8);
370        }
371        self
372    }
373
374    /// Set whether the `#` flag is specified.
375    #[inline]
376    pub fn with_alternate(&mut self, b: bool) -> &mut Self {
377        if b {
378            self.flags |= 1 << FlagBit::Alternate as u8;
379        } else {
380            self.flags &= !(1 << FlagBit::Alternate as u8);
381        }
382        self
383    }
384
385    /// Set whether the `0` flag is specified.
386    #[inline]
387    pub fn with_sign_aware_zero_pad(&mut self, b: bool) -> &mut Self {
388        if b {
389            self.flags |= 1 << FlagBit::SignAwareZeroPad as u8;
390        } else {
391            self.flags &= !(1 << FlagBit::SignAwareZeroPad as u8);
392        }
393        self
394    }
395}
396
397impl FormatterOptions {
398    /// Character used as 'fill' whenever there is alignment.
399    #[inline]
400    #[must_use]
401    pub const fn fill(&self) -> char {
402        self.fill
403    }
404
405    /// Flag indicating what form of alignment was requested.
406    #[inline]
407    #[must_use]
408    pub const fn align(&self) -> Option<Alignment> {
409        self.align
410    }
411
412    /// Optionally specified integer width that the output should be.
413    #[inline]
414    #[must_use]
415    pub const fn width(&self) -> Option<usize> {
416        if (self.flags >> FlagBit::WidthIsInitialized as u8) & 1 == 1 {
417            // Safety: `width` is initialized if the flag is set.
418            Some(unsafe { self.width.assume_init() })
419        } else {
420            None
421        }
422    }
423
424    /// Optionally specified precision for numeric types. Alternatively, the maximum width for
425    /// string types.
426    #[inline]
427    #[must_use]
428    pub const fn precision(&self) -> Option<usize> {
429        if (self.flags >> FlagBit::PrecisionIsInitialized as u8) & 1 == 1 {
430            // Safety: `precision` is initialized if the flag is set.
431            Some(unsafe { self.precision.assume_init() })
432        } else {
433            None
434        }
435    }
436
437    /// Determines if the `+` flag was specified.
438    #[inline]
439    #[must_use]
440    pub const fn sign_plus(&self) -> bool {
441        (self.flags >> FlagBit::SignPlus as u8) & 1 == 1
442    }
443
444    /// Determines if the `-` flag was specified.
445    #[inline]
446    #[must_use]
447    pub const fn sign_minus(&self) -> bool {
448        (self.flags >> FlagBit::SignMinus as u8) & 1 == 1
449    }
450
451    /// Determines if the `#` flag was specified.
452    #[inline]
453    #[must_use]
454    pub const fn alternate(&self) -> bool {
455        (self.flags >> FlagBit::Alternate as u8) & 1 == 1
456    }
457
458    /// Determines if the `0` flag was specified.
459    #[inline]
460    #[must_use]
461    pub const fn sign_aware_zero_pad(&self) -> bool {
462        (self.flags >> FlagBit::SignAwareZeroPad as u8) & 1 == 1
463    }
464}
465
466impl From<&Formatter<'_>> for FormatterOptions {
467    fn from(value: &Formatter<'_>) -> Self {
468        *Self::default()
469            .with_fill(value.fill())
470            .with_sign_plus(value.sign_plus())
471            .with_sign_minus(value.sign_minus())
472            .with_align(value.align())
473            .with_width(value.width())
474            .with_precision(value.precision())
475            .with_alternate(value.alternate())
476            .with_sign_aware_zero_pad(value.sign_aware_zero_pad())
477    }
478}
479
480impl From<&mut Formatter<'_>> for FormatterOptions {
481    #[inline]
482    fn from(value: &mut Formatter<'_>) -> Self {
483        (&*value).into()
484    }
485}
486
487/// Information used to format a value. This is returned by [`SmartDisplay::metadata`].
488///
489/// This type is generic over any user-provided type. This allows the author to store any
490/// information that is needed. For example, a type's implementation of [`SmartDisplay`] may need
491/// to calculate something before knowing its width. This calculation can be performed, with the
492/// result being stored in the custom metadata type.
493///
494/// Note that `Metadata` _always_ contains the width of the type. Authors do not need to store this
495/// information in their custom metadata type.
496///
497/// Generally speaking, a type should be able to be formatted using only its metadata, fields, and
498/// the formatter. Any other information should be stored in the metadata type.
499pub struct Metadata<'a, T>
500where
501    T: SmartDisplay + ?Sized,
502{
503    unpadded_width: usize,
504    metadata: T::Metadata,
505    _value: PhantomData<&'a T>, // variance
506}
507
508// manual impls for bounds
509impl<T> Debug for Metadata<'_, T>
510where
511    T: SmartDisplay,
512    T::Metadata: Debug,
513{
514    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
515        f.debug_struct("Metadata")
516            .field("unpadded_width", &self.unpadded_width)
517            .field("metadata", &self.metadata)
518            .finish()
519    }
520}
521
522impl<T> Clone for Metadata<'_, T>
523where
524    T: SmartDisplay,
525    T::Metadata: Clone,
526{
527    fn clone(&self) -> Self {
528        Self {
529            unpadded_width: self.unpadded_width,
530            metadata: self.metadata.clone(),
531            _value: self._value,
532        }
533    }
534}
535
536impl<T> Copy for Metadata<'_, T>
537where
538    T: SmartDisplay,
539    T::Metadata: Copy,
540{
541}
542
543impl<'a, T> Metadata<'a, T>
544where
545    T: SmartDisplay + ?Sized,
546{
547    /// Creates a new `Metadata` with the given width and metadata. While the width _should_ be
548    /// exact, this is not a requirement for soundness.
549    pub const fn new(unpadded_width: usize, _value: &T, metadata: T::Metadata) -> Self {
550        Self {
551            unpadded_width,
552            metadata,
553            _value: PhantomData,
554        }
555    }
556
557    /// Reuse the metadata for another type. This is useful when implementing [`SmartDisplay`] for a
558    /// type that wraps another type. Both type's metadata type must be the same.
559    pub fn reuse<'b, U>(self) -> Metadata<'b, U>
560    where
561        'a: 'b,
562        U: SmartDisplay<Metadata = T::Metadata> + ?Sized,
563    {
564        Metadata {
565            unpadded_width: self.unpadded_width,
566            metadata: self.metadata,
567            _value: PhantomData,
568        }
569    }
570
571    /// Obtain the width of the value before padding.
572    pub const fn unpadded_width(&self) -> usize {
573        self.unpadded_width
574    }
575
576    /// Obtain the width of the value after padding.
577    pub fn padded_width(&self, f: FormatterOptions) -> usize {
578        match f.width() {
579            Some(requested_width) => cmp::max(self.unpadded_width(), requested_width),
580            None => self.unpadded_width(),
581        }
582    }
583}
584
585impl Metadata<'_, Infallible> {
586    /// Obtain the width of the value before padding, given the formatter options.
587    pub fn unpadded_width_of<T>(value: T, f: FormatterOptions) -> usize
588    where
589        T: SmartDisplay,
590    {
591        value.metadata(f).unpadded_width
592    }
593
594    /// Obtain the width of the value after padding, given the formatter options.
595    pub fn padded_width_of<T>(value: T, f: FormatterOptions) -> usize
596    where
597        T: SmartDisplay,
598    {
599        value.metadata(f).padded_width(f)
600    }
601}
602
603/// Permit using `Metadata` as a smart pointer to the user-provided metadata.
604impl<T> Deref for Metadata<'_, T>
605where
606    T: SmartDisplay + ?Sized,
607{
608    type Target = T::Metadata;
609
610    fn deref(&self) -> &T::Metadata {
611        &self.metadata
612    }
613}
614
615/// Format trait that allows authors to provide additional information.
616///
617/// This trait is similar to [`Display`], but allows the author to provide additional information
618/// to the formatter. This information is provided in the form of a custom metadata type.
619///
620/// The only required piece of metadata is the width of the value. This is _before_ it is passed to
621/// the formatter (i.e. it does not include any padding added by the formatter). Other information
622/// can be stored in a custom metadata type as needed. This information may be made available to
623/// downstream users, but it is not required.
624///
625/// **Note**: While both `fmt_with_metadata` and `fmt` have default implementations, it is strongly
626/// recommended to implement only `fmt_with_metadata`. `fmt` should be implemented if and only if
627/// the type does not require any of the calculated metadata. In that situation, `fmt_with_metadata`
628/// should be omitted.
629#[cfg_attr(__powerfmt_docs, rustc_must_implement_one_of(fmt, fmt_with_metadata))]
630pub trait SmartDisplay: Display {
631    /// User-provided metadata type.
632    type Metadata;
633
634    /// Compute any information needed to format the value. This must, at a minimum, determine the
635    /// width of the value before any padding is added by the formatter.
636    ///
637    /// If the type uses other types that implement `SmartDisplay` verbatim, the inner types should
638    /// have their metadata calculated and included in the returned value.
639    ///
640    /// # Lifetimes
641    ///
642    /// This method's return type contains a lifetime to `self`. This ensures that the metadata will
643    /// neither outlive the value nor be invalidated by a mutation of the value (barring interior
644    /// mutability).
645    ///
646    /// ```rust,compile_fail
647    /// # use std::fmt;
648    /// # use std::fmt::Write;
649    /// # use powerfmt::buf::WriteBuffer;
650    /// # use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
651    /// #[derive(Debug)]
652    /// struct WrappedBuffer(WriteBuffer<128>);
653    ///
654    /// #[smart_display::delegate]
655    /// impl SmartDisplay for WrappedBuffer {
656    ///     type Metadata = ();
657    ///
658    ///     fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
659    ///         Metadata::new(self.0.len(), self, ())
660    ///     }
661    ///
662    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
663    ///         f.pad(self.0.as_str())
664    ///     }
665    /// }
666    ///
667    /// let mut buf = WrappedBuffer(WriteBuffer::new());
668    /// let metadata = buf.metadata(FormatterOptions::default());
669    /// // We cannot mutate the buffer while it is borrowed and use its previous metadata on the
670    /// // following line.
671    /// write!(buf.0, "Hello, world!")?;
672    /// assert_eq!(metadata.width(), 13);
673    /// # Ok::<(), Box<dyn std::error::Error>>(())
674    /// ```
675    fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self>;
676
677    /// Format the value using the given formatter and metadata. The formatted output should have
678    /// the width indicated by the metadata. This is before any padding is added by the
679    /// formatter.
680    ///
681    /// If the metadata is not needed, you should implement the `fmt` method instead.
682    fn fmt_with_metadata(&self, f: &mut Formatter<'_>, _metadata: Metadata<'_, Self>) -> Result {
683        SmartDisplay::fmt(self, f)
684    }
685
686    /// Format the value using the given formatter. This is the same as [`Display::fmt`].
687    ///
688    /// The default implementation of this method calls `fmt_with_metadata` with the result of
689    /// `metadata`. Generally speaking, this method should not be implemented. You should implement
690    /// the `fmt_with_metadata` method instead.
691    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
692        let metadata = self.metadata(f.into());
693        self.fmt_with_metadata(f, metadata)
694    }
695}