use serde::{de::Error, Deserialize}; use std::{ fmt::Display, ops::{Deref, DerefMut}, str::FromStr, }; #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)] #[serde(transparent)] pub(crate) struct Optional { #[serde(skip_serializing_if = "Option::is_none")] inner: Option, } impl Deref for Optional { type Target = Option; fn deref(&self) -> &Self::Target { &self.inner } } impl DerefMut for Optional { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } impl From> for Optional { fn from(inner: Option) -> Self { Optional { inner } } } impl From> for Option { fn from(e: Optional) -> Self { e.inner } } impl Optional { pub fn as_ref(&self) -> Option<&T> { self.inner.as_ref() } pub fn as_deref(&self) -> Option<&T::Target> where T: Deref, { self.inner.as_deref() } } impl<'de, T> Deserialize<'de> for Optional where T: FromStr, T::Err: Display, { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let s: Option = Deserialize::<'de>::deserialize(deserializer)?; match s.as_deref().map(|s| s.trim()) { None | Some("") => Ok(Optional { inner: None }), Some(s) => T::from_str(&s) .map_err(D::Error::custom) .map(Some) .map(|inner| Optional { inner }), } } }