1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Rust language amplification library providing multiple generic trait
// implementations, type wrappers, derive macros and other language enhancements
//
// Written in 2019-2020 by
//     Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
//     Martin Habovstiak <martin.habovstiak@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the MIT License
// along with this software.
// If not, see <https://opensource.org/licenses/MIT>.

//! This module contains various tools for converting values

/// impls TryFrom<T> where T: Deref<Target=str> in terms of FromStr.
///
/// This needs to be a macro instead of blanket imple in order to resolve the
/// conflict with T: Into<Self>
#[macro_export]
macro_rules! impl_try_from_stringly {
    ($to:ty $(, $from:ty)+ $(,)?) => {
        $(
            impl ::core::convert::TryFrom<$from> for $to {
                type Error = <$to as ::core::str::FromStr>::Err;
                #[inline]
                fn try_from(value: $from) -> Result<Self, Self::Error> {
                    <$to>::from_str(&value)
                }
            }
        )*
    };

    (@std, $to:ty $(, $from:ty)+ $(,)?) => {
        $(
            #[cfg(feature = "std")]
            impl std::convert::TryFrom<$from> for $to {
                type Error = <$to as ::core::str::FromStr>::Err;
                #[inline]
                fn try_from(value: $from) -> Result<Self, Self::Error> {
                    <$to>::from_str(&value)
                }
            }
        )*
    }
}

/// Calls impl_try_from_stringly!() with a set of standard stringly types.
#[macro_export]
macro_rules! impl_try_from_stringly_standard {
    ($type:ty) => {
        #[cfg(feature = "std")]
        use ::std::borrow::Cow;
        #[cfg(feature = "std")]
        use ::std::rc::Rc;
        #[cfg(feature = "std")]
        use ::std::sync::Arc;

        impl_try_from_stringly! { $type,
            &str,
            String,
        }

        #[cfg(feature = "std")]
        impl_try_from_stringly! { @std $type,
            Cow<'_, str>
            Box<str>,
            Box<Cow<'_, str>>,
            Rc<str>,
            Rc<String>,
            Rc<Cow<'_, str>>,
            Arc<str>,
            Arc<String>,
            Arc<Cow<'_, str>>,
        }

        #[cfg(feature = "serde")]
        impl_try_from_stringly!($type, $crate::CowHelper<'_>);
    };
}

/// Impls From<T> for Stringly where String: Into<Stringly>, T: Display
#[macro_export]
macro_rules! impl_into_stringly {
    ($from:ty $(, $into:ty)+ $(,)?) => {
        $(
            impl From<$from> for $into {
                fn from(value: $from) -> Self {
                    value.to_string().into()
                }
            }
        )+
    }
}

/// Implements `impl_into_stringly` for `$type` and traits with `$type`
#[macro_export]
macro_rules! impl_into_stringly_standard {
    ($type:ty) => {
        #[cfg(feature = "std")]
        use ::core::rc::Rc;
        #[cfg(feature = "std")]
        use ::core::sync::Arc;
        #[cfg(feature = "std")]
        use ::std::borrow::Cow;

        impl_into_stringly! { $type,
            String,
        }

        #[cfg(feature = "std")]
        impl_into_stringly! { @std, $type,
            Cow<'_, str>
            Box<str>,
            Rc<str>,
            Rc<String>,
            Arc<str>,
            Arc<String>,
        }
    };
}