facti_lib/
serde.rs

1use serde::{de::Visitor, Deserialize, Serialize};
2
3use super::{dependency::Dependency, version::Version, FactorioVersion};
4
5impl Serialize for Version {
6    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
7    where
8        S: serde::Serializer,
9    {
10        let str = format!("{}.{}.{}", self.major, self.minor, self.patch);
11        serializer.serialize_str(str.as_str())
12    }
13}
14
15impl<'de> Deserialize<'de> for Version {
16    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
17    where
18        D: serde::Deserializer<'de>,
19    {
20        struct VersionVisitor;
21
22        impl<'de> Visitor<'de> for VersionVisitor {
23            type Value = Version;
24
25            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
26                formatter.write_str("a valid version string ('major.minor.patch')")
27            }
28
29            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
30            where
31                E: serde::de::Error,
32            {
33                Version::parse(v).map_err(|_| serde::de::Error::custom("invalid version"))
34            }
35        }
36
37        deserializer.deserialize_str(VersionVisitor)
38    }
39}
40
41impl Serialize for FactorioVersion {
42    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
43    where
44        S: serde::Serializer,
45    {
46        let str = if let Some(patch) = self.patch {
47            format!("{}.{}.{}", self.major, self.minor, patch)
48        } else {
49            format!("{}.{}", self.major, self.minor)
50        };
51
52        serializer.serialize_str(str.as_str())
53    }
54}
55
56impl<'de> Deserialize<'de> for FactorioVersion {
57    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58    where
59        D: serde::Deserializer<'de>,
60    {
61        struct FactorioVersionVisitor;
62
63        impl<'de> Visitor<'de> for FactorioVersionVisitor {
64            type Value = FactorioVersion;
65
66            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
67                formatter.write_str("a valid Factorio version string ('major.minor')")
68            }
69
70            fn visit_none<E>(self) -> Result<Self::Value, E>
71            where
72                E: serde::de::Error,
73            {
74                Ok(FactorioVersion::default())
75            }
76
77            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
78            where
79                E: serde::de::Error,
80            {
81                FactorioVersion::parse(v)
82                    .map_err(|_| serde::de::Error::custom("invalid Factorio version"))
83            }
84        }
85
86        deserializer.deserialize_str(FactorioVersionVisitor)
87    }
88}
89
90impl Serialize for Dependency {
91    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
92    where
93        S: serde::Serializer,
94    {
95        serializer.collect_str(self)
96    }
97}
98
99impl<'de> Deserialize<'de> for Dependency {
100    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
101    where
102        D: serde::Deserializer<'de>,
103    {
104        struct DependencyVisitor;
105
106        impl<'de> Visitor<'de> for DependencyVisitor {
107            type Value = Dependency;
108
109            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
110                formatter.write_str("a valid dependency string ('[mode] name [version-req]')")
111            }
112
113            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
114            where
115                E: serde::de::Error,
116            {
117                Dependency::parse(v).map_err(|_| serde::de::Error::custom("invalid dependency"))
118            }
119        }
120
121        deserializer.deserialize_str(DependencyVisitor)
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use crate::version::VersionReq;
128
129    use super::*;
130
131    #[test]
132    fn test_serialize_version() {
133        let version = Version::parse("1.2.3").unwrap();
134        let serialized = serde_json::to_string(&version).unwrap();
135        assert_eq!(serialized, "\"1.2.3\"");
136    }
137
138    #[test]
139    fn test_deserialize_version() {
140        let version = Version::parse("1.2.3").unwrap();
141        let deserialized: Version = serde_json::from_str("\"1.2.3\"").unwrap();
142        assert_eq!(deserialized, version);
143    }
144
145    #[test]
146    fn test_serialize_factorio_version() {
147        let version = FactorioVersion::parse("1.2").unwrap();
148        let serialized = serde_json::to_string(&version).unwrap();
149        assert_eq!(serialized, "\"1.2\"");
150    }
151
152    #[test]
153    fn test_deserialize_factorio_version() {
154        let version = FactorioVersion::parse("1.2").unwrap();
155        let deserialized: FactorioVersion = serde_json::from_str("\"1.2\"").unwrap();
156        assert_eq!(deserialized, version);
157    }
158
159    #[test]
160    fn test_serialize_dependency() {
161        let dependency =
162            Dependency::optional("facti", VersionReq::parse(">= 4.2.0").unwrap(), false);
163        let serialized = serde_json::to_string(&dependency).unwrap();
164        assert_eq!(serialized, "\"? facti >= 4.2.0\"");
165    }
166
167    #[test]
168    fn test_deserialize_dependency() {
169        let dependency = Dependency::optional("facti", VersionReq::parse("< 1.0.0").unwrap(), true);
170        let deserialized: Dependency = serde_json::from_str("\"(?) facti < 1.0.0\"").unwrap();
171        assert_eq!(deserialized, dependency);
172    }
173}