sps_common/model/
version.rs1use std::fmt;
3use std::str::FromStr;
4
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6
7use crate::error::{Result, SpsError};
8
9#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct Version(semver::Version);
12
13impl Version {
14 pub fn parse(s: &str) -> Result<Self> {
15 semver::Version::parse(s).map(Version).or_else(|_| {
17 let cleaned = s.split('_').next().unwrap_or(s); let parts: Vec<&str> = cleaned.split('.').collect();
22 let padded = match parts.len() {
23 1 => format!("{}.0.0", parts[0]),
24 2 => format!("{}.{}.0", parts[0], parts[1]),
25 _ => cleaned.to_string(), };
27 semver::Version::parse(&padded).map(Version).map_err(|e| {
28 SpsError::VersionError(format!(
29 "Failed to parse version '{s}' (tried '{padded}'): {e}"
30 ))
31 })
32 })
33 }
34}
35
36impl FromStr for Version {
37 type Err = SpsError;
38 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
39 Self::parse(s)
40 }
41}
42
43impl fmt::Display for Version {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 write!(f, "{}", self.0)
48 }
49}
50
51impl Serialize for Version {
53 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
54 where
55 S: Serializer,
56 {
57 serializer.serialize_str(&self.to_string())
58 }
59}
60
61impl AsRef<Self> for Version {
62 fn as_ref(&self) -> &Self {
63 self
64 }
65}
66
67impl From<Version> for semver::Version {
70 fn from(version: Version) -> Self {
71 version.0
72 }
73}
74
75impl<'de> Deserialize<'de> for Version {
76 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
77 where
78 D: Deserializer<'de>,
79 {
80 let s = String::deserialize(deserializer)?;
81 Self::from_str(&s).map_err(serde::de::Error::custom)
82 }
83}
84
85