use std::fmt;
pub struct DisplayOption<'a, T> {
inner: &'a Option<T>,
fmt_fn: fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result,
}
impl<T> fmt::Display for DisplayOption<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
None => write!(f, "None"),
Some(x) => (self.fmt_fn)(x, f),
}
}
}
pub trait DisplayOptionExt<'a, T: fmt::Display> {
fn display(&'a self) -> DisplayOption<'a, T>;
}
impl<T> DisplayOptionExt<'_, T> for Option<T>
where T: fmt::Display
{
fn display(&self) -> DisplayOption<T> {
DisplayOption {
inner: self,
fmt_fn: <T as fmt::Display>::fmt,
}
}
}
pub trait DisplayDebugOptionExt<'a, T: fmt::Debug> {
fn display_debug(&'a self) -> DisplayOption<'a, T>;
}
impl<T> DisplayDebugOptionExt<'_, T> for Option<T>
where T: fmt::Debug
{
fn display_debug(&self) -> DisplayOption<T> {
DisplayOption {
inner: self,
fmt_fn: <T as fmt::Debug>::fmt,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_display_option() {
let option = Some(1);
assert_eq!(option.display().to_string(), "1");
}
#[test]
fn test_display_option_none() {
let option = None::<u64>;
assert_eq!(option.display().to_string(), "None");
}
#[test]
fn test_debug_option() {
assert_eq!(Some(1).display_debug().to_string(), "1");
assert_eq!(None::<u64>.display_debug().to_string(), "None");
assert_eq!(Some("hello").display_debug().to_string(), "\"hello\"");
assert_eq!(Some(vec![1, 2, 3]).display_debug().to_string(), "[1, 2, 3]");
}
}