phlow 3.0.0

An engine for scripting reactive browsers in Rust by adding custom views to structures
Documentation
/// Tries to clone a value.
///
/// Accepts either `value` or `&value`.
///
/// Conversion order:
/// 1. Types implementing [`Copy`] are copied.
/// 2. Types implementing [`Clone`] are cloned.
/// 3. All other types return `None`.
///
/// # Examples
///
/// ```
/// let value = String::from("hello");
/// assert_eq!(phlow::try_to_clone!(value.clone()), Some(String::from("hello")));
/// assert_eq!(phlow::try_to_clone!(&value), Some(String::from("hello")));
/// ```
#[macro_export]
macro_rules! try_to_clone {
    (&$value:expr) => {{
        #[allow(unused_imports)]
        use $crate::cloning::{TryToCloneFallback, TryToCloneViaClone, TryToCloneViaCopy};
        (&&&$crate::cloning::TryToClone(&$value)).try_to_phlow_clone()
    }};
    ($value:expr) => {{
        #[allow(unused_imports)]
        use $crate::cloning::{TryToCloneFallback, TryToCloneViaClone, TryToCloneViaCopy};
        (&&&$crate::cloning::TryToClone(&$value)).try_to_phlow_clone()
    }};
}

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

pub trait TryToCloneViaCopy<T> {
    fn try_to_phlow_clone(&self) -> Option<T>;
}

impl<T: Copy> TryToCloneViaCopy<T> for &&TryToClone<'_, T> {
    fn try_to_phlow_clone(&self) -> Option<T> {
        Some(*self.0)
    }
}

pub trait TryToCloneViaClone<T> {
    fn try_to_phlow_clone(&self) -> Option<T>;
}

impl<T: Clone> TryToCloneViaClone<T> for &TryToClone<'_, T> {
    fn try_to_phlow_clone(&self) -> Option<T> {
        Some(self.0.clone())
    }
}

pub trait TryToCloneFallback<T> {
    fn try_to_phlow_clone(&self) -> Option<T>;
}

impl<T> TryToCloneFallback<T> for TryToClone<'_, T> {
    fn try_to_phlow_clone(&self) -> Option<T> {
        None
    }
}

#[cfg(test)]
mod tests {
    #[derive(Debug, PartialEq, Eq)]
    struct CloneOnly(&'static str);

    impl Clone for CloneOnly {
        fn clone(&self) -> Self {
            Self(self.0)
        }
    }

    #[test]
    fn try_to_clone_macro_is_usable_within_the_crate() {
        let value = CloneOnly("hello");
        assert_eq!(try_to_clone!(&value), Some(CloneOnly("hello")));
    }
}