use { serde::{Deserialize, Deserializer, Serialize, Serializer}, std::{fmt, str::FromStr}, }; #[derive(Default, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)] pub struct CliVersion(Option); impl CliVersion { pub fn unknown_version() -> Self { Self(None) } } impl fmt::Display for CliVersion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = match &self.0 { None => "unknown".to_string(), Some(version) => version.to_string(), }; write!(f, "{s}") } } impl From for CliVersion { fn from(version: semver::Version) -> Self { Self(Some(version)) } } impl FromStr for CliVersion { type Err = semver::Error; fn from_str(s: &str) -> Result { let version_option = if s == "unknown" { None } else { Some(semver::Version::from_str(s)?) }; Ok(CliVersion(version_option)) } } impl Serialize for CliVersion { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_str(&self.to_string()) } } impl<'de> Deserialize<'de> for CliVersion { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let s: &str = Deserialize::deserialize(deserializer)?; CliVersion::from_str(s).map_err(serde::de::Error::custom) } }