/// Support for parsing strings. // Impls a single TryFrom conversion #[doc(hidden)] #[macro_export] macro_rules! impl_try_from_stringly { ($from:ty, $to:ty, $error:ty, $func:expr) => { $(#[$attr])? impl core::convert::TryFrom<$from> for $to { type Error = $error; fn try_from(s: $from) -> Result { $func(AsRef::::as_ref(s)).map_err(|source| <$error>::new(s, source)) } } } } /// Implements conversions from various string types. /// /// This macro implements `FromStr` as well as `TryFrom<{stringly}` where `{stringly}` is one of /// these types: /// /// * `&str` /// * `String` /// * `Box` /// * `Cow<'_, str>` /// /// The last three are only available with `alloc` feature turned on. #[macro_export] macro_rules! impl_parse { ($type:ty, $descr:expr, $func:expr, $vis:vis $error:ident, $error_source:ty $(, $error_derive:path)*) => { $crate::parse_error_type!($vis $error, $error_source, $descr $(, $error_derive)*); impl core::str::FromStr for $type { type Err = $error; fn from_str(s: &str) -> Result { $func(s).map_err(|source| <$error>::new(s, source)) } } impl_try_from_stringly!(&str); #[cfg(feature = "alloc")] impl_try_from_stringly!(alloc::string::String, $type, $error, $func); #[cfg(feature = "alloc")] impl_try_from_stringly!(alloc::borrow::Cow<'_, str>, $type, $error, $func); #[cfg(feature = "alloc")] impl_try_from_stringly!(alloc::boxed::Box, $type, $error, $func); } } /// Implements conversions from various string types as well as `serde` (de)serialization. /// /// This calls `impl_parse` macro and implements serde deserialization by expecting and parsing a /// string and serialization by outputting a string. #[macro_export] macro_rules! impl_parse_and_serde { ($type:ty, $descr:expr, $func:expr, $error:ident, $error_source:ty $(, $error_derive:path)*) => { impl_parse!($type, $descr, $func, $error, $error_source $(, $error_derive)*); // We don't use `serde_string_impl` because we want to avoid allocating input. #[cfg(feature = "serde")] impl<'de> $crate::serde::Deserialize<'de> for $type { fn deserialize(deserializer: D) -> Result<$name, D::Error> where D: $crate::serde::de::Deserializer<'de>, { use core::fmt::{self, Formatter}; use core::str::FromStr; struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { type Value = $name; fn expecting(&self, f: &mut Formatter) -> fmt::Result { f.write_str($descr) } fn visit_str(self, s: &str) -> Result where E: $crate::serde::de::Error, { s.parse().map_err(|error| { $crate::serde::IntoDeError::try_into_de_error(error) .unwrap_or_else(|_| E::invalid_value(Unexpected::Str(s), &self)) }) } } deserializer.deserialize_str(Visitor) } } #[cfg(feature = "serde")] impl $crate::serde::Serialize for $name { fn serialize(&self, serializer: S) -> Result where S: $crate::serde::Serializer, { serializer.collect_str(&self) } } } }