use alloc::boxed::Box;
use alloc::string::String;
use core::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FormatType {
Display,
Debug,
LowerHex,
UpperHex,
Octal,
Binary,
LowerExp,
UpperExp,
}
pub trait FormatArg {
fn write(
&self,
ty: FormatType,
pretty: bool,
precision: Option<usize>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result;
fn is_numeric(&self) -> bool {
false
}
fn is_integer(&self) -> bool {
false
}
fn as_usize(&self) -> Option<usize> {
None
}
}
macro_rules! impl_format_arg_int {
($($t:ty),+ $(,)?) => {$(
impl FormatArg for $t {
fn write(
&self,
ty: FormatType,
pretty: bool,
_precision: Option<usize>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
match ty {
FormatType::Display => fmt::Display::fmt(self, f),
FormatType::Debug if pretty => write!(f, "{:#?}", self),
FormatType::Debug => fmt::Debug::fmt(self, f),
FormatType::LowerHex => fmt::LowerHex::fmt(self, f),
FormatType::UpperHex => fmt::UpperHex::fmt(self, f),
FormatType::Octal => fmt::Octal::fmt(self, f),
FormatType::Binary => fmt::Binary::fmt(self, f),
FormatType::LowerExp => fmt::LowerExp::fmt(self, f),
FormatType::UpperExp => fmt::UpperExp::fmt(self, f),
}
}
fn is_numeric(&self) -> bool { true }
fn is_integer(&self) -> bool { true }
fn as_usize(&self) -> Option<usize> { (*self).try_into().ok() }
}
)+};
}
impl_format_arg_int!(
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize
);
macro_rules! impl_format_arg_float {
($($t:ty),+ $(,)?) => {$(
impl FormatArg for $t {
fn write(
&self,
ty: FormatType,
pretty: bool,
precision: Option<usize>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
match ty {
FormatType::Display => match precision {
Some(prec) => write!(f, "{:.prec$}", self, prec = prec),
None => fmt::Display::fmt(self, f),
},
FormatType::Debug if pretty => write!(f, "{:#?}", self),
FormatType::Debug => fmt::Debug::fmt(self, f),
FormatType::LowerExp => match precision {
Some(prec) => write!(f, "{:.prec$e}", self, prec = prec),
None => fmt::LowerExp::fmt(self, f),
},
FormatType::UpperExp => match precision {
Some(prec) => write!(f, "{:.prec$E}", self, prec = prec),
None => fmt::UpperExp::fmt(self, f),
},
_ => Err(fmt::Error),
}
}
fn is_numeric(&self) -> bool { true }
}
)+};
}
impl_format_arg_float!(f32, f64);
macro_rules! impl_format_arg_text {
($($t:ty),+ $(,)?) => {$(
impl FormatArg for $t {
fn write(
&self,
ty: FormatType,
pretty: bool,
_precision: Option<usize>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
match ty {
FormatType::Display => fmt::Display::fmt(self, f),
FormatType::Debug if pretty => write!(f, "{:#?}", self),
FormatType::Debug => fmt::Debug::fmt(self, f),
_ => Err(fmt::Error),
}
}
}
)+};
}
impl_format_arg_text!(str, String, char, bool);
impl<T: FormatArg + ?Sized> FormatArg for &T {
fn write(
&self,
ty: FormatType,
pretty: bool,
precision: Option<usize>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
(**self).write(ty, pretty, precision, f)
}
fn is_numeric(&self) -> bool {
(**self).is_numeric()
}
fn is_integer(&self) -> bool {
(**self).is_integer()
}
fn as_usize(&self) -> Option<usize> {
(**self).as_usize()
}
}
impl<T: FormatArg + ?Sized> FormatArg for Box<T> {
fn write(
&self,
ty: FormatType,
pretty: bool,
precision: Option<usize>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
(**self).write(ty, pretty, precision, f)
}
fn is_numeric(&self) -> bool {
(**self).is_numeric()
}
fn is_integer(&self) -> bool {
(**self).is_integer()
}
fn as_usize(&self) -> Option<usize> {
(**self).as_usize()
}
}