phlow 3.0.0

An engine for scripting reactive browsers in Rust by adding custom views to structures
Documentation
use std::fmt::{Debug, Display};

/// Tries to convert a value to a `String`.
///
/// Accepts either `value` or `&value`.
///
/// Conversion order:
/// 1. `String` values are cloned.
/// 2. Types implementing [`Display`] use `to_string()`.
/// 3. Types implementing [`Debug`] use `format!("{:?}", ...)`.
/// 4. All other types return `None`.
///
/// # Examples
///
/// ```
/// let owned = String::from("hello");
/// assert_eq!(phlow::try_to_string!(owned.clone()), Some(String::from("hello")));
/// assert_eq!(phlow::try_to_string!(&owned), Some(String::from("hello")));
/// ```
#[macro_export]
macro_rules! try_to_string {
    (&$value:expr) => {{
        use phlow::printing::{
            TryToStringFallback, TryToStringViaDebug, TryToStringViaDisplay, TryToStringViaString,
        };
        (&&&phlow::printing::TryToString(&$value)).try_to_phlow_string()
    }};
    ($value:expr) => {{
        use phlow::printing::{
            TryToStringFallback, TryToStringViaDebug, TryToStringViaDisplay, TryToStringViaString,
        };
        (&&&phlow::printing::TryToString(&$value)).try_to_phlow_string()
    }};
}

/// Converts a value to a `String`.
///
/// Accepts either `value` or `&value`.
///
/// Conversion order:
/// 1. `String` values are cloned.
/// 2. Types implementing [`Display`] use `to_string()`.
/// 3. Types implementing [`Debug`] use `format!("{:?}", ...)`.
/// 4. All other types fall back to `std::any::type_name::<T>()`.
///
/// # Examples
///
/// ```
/// let owned = String::from("hello");
/// assert_eq!(phlow::to_string!(owned.clone()), String::from("hello"));
/// assert_eq!(phlow::to_string!(&owned), String::from("hello"));
/// ```
#[macro_export]
macro_rules! to_string {
    (&$value:expr) => {{
        use phlow::printing::{
            TryToStringFallback, TryToStringViaDebug, TryToStringViaDisplay, TryToStringViaString,
        };
        (&&&phlow::printing::TryToString(&$value)).to_phlow_string()
    }};
    ($value:expr) => {{
        use phlow::printing::{
            TryToStringFallback, TryToStringViaDebug, TryToStringViaDisplay, TryToStringViaString,
        };
        (&&&phlow::printing::TryToString(&$value)).to_phlow_string()
    }};
}

pub struct TryToString<'a, T>(pub &'a T);

pub trait TryToStringViaString {
    fn try_to_phlow_string(&self) -> Option<String> {
        Some(self.to_phlow_string())
    }
    fn to_phlow_string(&self) -> String;
}
impl TryToStringViaString for &&&TryToString<'_, String> {
    fn to_phlow_string(&self) -> String {
        self.0.clone()
    }
}

pub trait TryToStringViaDisplay {
    fn try_to_phlow_string(&self) -> Option<String> {
        Some(self.to_phlow_string())
    }
    fn to_phlow_string(&self) -> String;
}
impl<T: Display> TryToStringViaDisplay for &&TryToString<'_, T> {
    fn to_phlow_string(&self) -> String {
        self.0.to_string()
    }
}

pub trait TryToStringViaDebug {
    fn try_to_phlow_string(&self) -> Option<String> {
        Some(self.to_phlow_string())
    }
    fn to_phlow_string(&self) -> String;
}
impl<T: Debug> TryToStringViaDebug for &TryToString<'_, T> {
    fn to_phlow_string(&self) -> String {
        format!("{:?}", self.0)
    }
}

pub trait TryToStringFallback {
    fn try_to_phlow_string(&self) -> Option<String>;
    fn to_phlow_string(&self) -> String;
}
impl<T> TryToStringFallback for TryToString<'_, T> {
    fn try_to_phlow_string(&self) -> Option<String> {
        None
    }

    fn to_phlow_string(&self) -> String {
        std::any::type_name::<T>().to_string()
    }
}