use crate::Formatter; #[derive(Debug, Clone, Copy)] pub enum Alignment { Left, Center, Right, Unknown, } macro_rules! options { ( $( fn $name:ident(&self) -> $ret:ty { $($default:tt)* } struct $with_name:ident$(<$(const $const_gen_name:ident: $with_ty:ty),*>)? { $($struct_body:tt)* } )* ) => { // FIXME: We can get rid of this Copy can't we pub trait FmtOpts: Copy { #[doc(hidden)] type Inner: FmtOpts; /// Replaces the innermost `()` with `I` type ReplaceInnermost: FmtOpts; fn inner(&self) -> &Self::Inner; /// # Example /// `Self` is `WithAlternate>` /// `Other` is WithMinus<()> /// /// This returns `WithAlternate, ' '>>` /// fn override_other(self, other: Other) -> Self::ReplaceInnermost; $( #[inline] fn $name(&self) -> $ret { Self::Inner::$name(Self::inner(self)) } )* } impl FmtOpts for () { type Inner = Self; type ReplaceInnermost = I; fn inner(&self) -> &Self::Inner { self } fn override_other(self, other: Other) -> Self::ReplaceInnermost:: { other } $( #[inline] fn $name(&self) -> $ret { $($default)* } )* } impl FmtOpts for &'_ O { type Inner = O::Inner; type ReplaceInnermost = O::ReplaceInnermost; fn inner(&self) -> &Self::Inner { O::inner(self) } fn override_other(self, other: Other) -> Self::ReplaceInnermost { O::override_other(*self, other) } $( #[inline] fn $name(&self) -> $ret { O::$name(self) } )* } impl Formatter { $( #[doc = concat!("Gets the `", stringify!($name), "` option from the underlying options type.")] #[inline] pub fn $name(&self) -> $ret { O::$name(&self.opts) } )* } $( #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct $with_name(#[doc(hidden)] pub I); impl FmtOpts for $with_name { type Inner = I; type ReplaceInnermost = $with_name, $($($const_gen_name),*)?>; fn inner(&self) -> &Self::Inner { &self.0 } fn override_other(self, other: Other) -> Self::ReplaceInnermost { $with_name(self.0.override_other(other)) } fn $name(&self) -> $ret { $($struct_body)* } } )* pub mod exports { pub use super::{$($with_name),*}; } }; } options!( fn alternate(&self) -> bool { false } struct WithAlternate { true } fn width(&self) -> Option { None } struct WithWidth { Some(A) } fn align(&self) -> Alignment { Alignment::Unknown } struct WithAlign { match A { 0 => Alignment::Unknown, 1 => Alignment::Left, 2 => Alignment::Center, 3 => Alignment::Right, _ => panic!("invalid alignment number {A}") } } fn fill(&self) -> char { ' ' } struct WithFill { A } fn sign_plus(&self) -> bool { false } struct WithSignPlus { true } fn sign_aware_zero_pad(&self) -> bool { false } struct WithSignAwareZeroPad { true } fn sign_minus(&self) -> bool { false } struct WithMinus { true } fn precision(&self) -> Option { None } struct WithPrecision { Some(A) } fn debug_lower_hex(&self) -> bool { false } struct WithDebugLowerHex { true } fn debug_upper_hex(&self) -> bool { false } struct WithDebugUpperHex { false } );