use std::fmt::{Debug, Display, Formatter, Result};
#[macro_export]
macro_rules! lazy_format {
(move, $($arg:tt)*) => {
$crate::LazyString::new(move |f: &mut std::fmt::Formatter<'_>| {
::core::write!(f, $($arg)*)
})
};
($($arg:tt)*) => {
$crate::LazyString::new(|f: &mut std::fmt::Formatter<'_>| {
::core::write!(f, $($arg)*)
})
};
}
pub struct LazyString<F>(F)
where
F: Fn(&mut Formatter<'_>) -> Result;
impl<F> LazyString<F>
where
F: Fn(&mut Formatter<'_>) -> Result,
{
#[doc(hidden)]
pub fn new(f: F) -> Self {
Self(f)
}
}
impl<F> Display for LazyString<F>
where
F: Fn(&mut Formatter<'_>) -> Result,
{
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
(self.0)(f)
}
}
impl<F> Debug for LazyString<F>
where
F: Fn(&mut Formatter<'_>) -> Result,
{
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.debug_tuple("LazyString")
.field(&format_args!("{self}"))
.finish()
}
}
#[cfg(test)]
mod test {
use super::*;
fn assert_static<T: 'static>(_: &T) {}
#[test]
fn test_lazy_string() {
let x: f32 = 10.5;
let y: usize = 20;
let lazy = LazyString::new(|f: &mut std::fmt::Formatter| {
write!(f, "Lazy Message: x = {x}, y = {y}")
});
assert_eq!(lazy.to_string(), "Lazy Message: x = 10.5, y = 20");
let lazy = lazy_format!("Lazy Message: x = {x}, y = {y}");
assert_eq!(lazy.to_string(), "Lazy Message: x = 10.5, y = 20");
let lazy = lazy_format!(move, "Lazy Message: x = {}, y = {y}", x);
assert_static(&lazy);
assert_eq!(lazy.to_string(), "Lazy Message: x = 10.5, y = 20");
assert_eq!(
format!("{:?}", lazy),
"LazyString(Lazy Message: x = 10.5, y = 20)",
);
}
}