1#![deny(missing_docs, clippy::all)]
4
5use std::collections::BTreeSet;
6use std::fmt::Display;
7use std::rc::Rc;
8use std::str::FromStr;
9
10#[derive(Eq, PartialEq, Clone, Debug, Ord, PartialOrd, Default)]
15pub struct SetVersion {
16 versions: BTreeSet<Rc<SetVersion>>,
18}
19
20impl SetVersion {
21 pub fn setver_compare(&self, other: &SetVersion) -> f32 {
25 if self.is_subset(other) {
26 0.0
27 } else if self == other {
28 1.0
29 } else if other.is_subset(self) {
30 f32::INFINITY
31 } else {
32 f32::NAN
33 }
34 }
35
36 pub fn is_subset(&self, other: &SetVersion) -> bool {
44 self.versions.is_subset(&other.versions)
45 }
46
47 pub fn is_strict_subset(&self, other: &SetVersion) -> bool {
49 !other.is_superset(self)
50 }
51 pub fn is_superset(&self, other: &SetVersion) -> bool {
53 self.versions.is_superset(&other.versions)
54 }
55
56 pub fn is_strict_superset(&self, other: &SetVersion) -> bool {
58 !other.is_subset(self)
59 }
60
61 pub fn add_child_version(&mut self, child: Rc<SetVersion>) -> &mut Self {
63 self.versions.insert(child);
64 self
65 }
66
67 pub fn to_integralternative(&self) -> u128 {
72 self.into()
73 }
74
75 pub fn string_to_integralternative(setver: &str) -> u128 {
81 let bytes = Self::string_to_integralternative_bytes(setver);
82 Self::u128_from_vec(bytes)
83 }
84
85 pub fn to_integralternative_bytes(&self) -> Vec<u8> {
90 let stringified = String::from(self);
92 Self::string_to_integralternative_bytes(&stringified)
93 }
94
95 pub fn string_to_integralternative_bytes(setver: &str) -> Vec<u8> {
101 let mut current_byte = 0;
102 let mut bytes = Vec::new();
103 let mut bit_count = 0;
104 for c in setver.chars().rev() {
105 current_byte = (current_byte >> 1)
106 | match c {
107 '{' => 0,
108 '}' => 1 << 7,
109 _ => unreachable!(),
110 };
111 bit_count += 1;
112 if bit_count > 7 {
113 bit_count = 0;
114 bytes.push(current_byte);
115 current_byte = 0;
116 }
117 }
118 if bit_count != 0 {
119 current_byte >>= 8 - bit_count;
121 bytes.push(current_byte);
122 }
123 bytes.reverse();
124 bytes
125 }
126
127 fn u128_from_vec(vec: Vec<u8>) -> u128 {
129 if vec.len() > 128 / 8 {
130 panic!("Input {:?} is too large to be represented in u128", vec);
131 }
132 let mut result = 0u128;
133 for byte in vec {
134 result = (result << 8) | (byte as u128);
135 }
136 result
137 }
138}
139
140impl Display for SetVersion {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 write!(f, "{{")?;
144 for version in &self.versions {
145 version.fmt(f)?;
146 }
147 write!(f, "}}")
148 }
149}
150
151impl From<&SetVersion> for String {
152 fn from(this: &SetVersion) -> Self {
153 format!("{}", this)
154 }
155}
156
157impl From<&SetVersion> for u128 {
158 fn from(this: &SetVersion) -> Self {
159 let bytes = this.to_integralternative_bytes();
160 SetVersion::u128_from_vec(bytes)
161 }
162}
163
164impl PartialEq<u128> for SetVersion {
165 fn eq(&self, other: &u128) -> bool {
167 self.to_integralternative() == *other
168 }
169}
170
171impl PartialEq<&str> for SetVersion {
172 fn eq(&self, other: &&str) -> bool {
175 match other.parse::<SetVersion>() {
176 Ok(other_setver) => self == &other_setver,
177 Err(_) => false,
178 }
179 }
180}
181
182#[derive(Debug, Copy, Clone, Eq, PartialEq)]
184pub enum SetVerParseError {
185 IllegalCharacter(char),
187 NonUniqueElements,
189 UnclosedBrace,
191 Empty,
193 TooManySets,
195}
196
197impl Display for SetVerParseError {
198 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199 write!(
200 f,
201 "{}",
202 match &self {
203 Self::IllegalCharacter(c) => format!("Illegal character '{}'", c),
204 Self::NonUniqueElements => "Set contains non-unique subsets".to_string(),
205 Self::UnclosedBrace => "Unclosed set brace".to_string(),
206 Self::Empty => "Empty string".to_string(),
207 Self::TooManySets => "Too many sets (more than one)".to_string(),
208 }
209 )
210 }
211}
212
213impl FromStr for SetVersion {
214 type Err = SetVerParseError;
215 fn from_str(value: &str) -> Result<Self, Self::Err> {
216 if value.len() < 2 {
218 return Err(SetVerParseError::Empty);
219 }
220 let mut chars = value.chars();
221 let open_curly = chars.next().unwrap();
222 if open_curly != '{' {
223 return Err(SetVerParseError::IllegalCharacter(open_curly));
224 }
225
226 let mut brace_level = 1;
228 let mut inner_sets = vec!["".to_owned()];
229 for next_char in &mut chars {
230 match next_char {
231 '{' => brace_level += 1,
232 '}' => brace_level -= 1,
233 _ => return Err(SetVerParseError::IllegalCharacter(next_char)),
234 }
235 if brace_level == 0 {
236 break;
237 }
238 inner_sets.last_mut().unwrap().push(next_char);
239 if brace_level == 1 {
240 inner_sets.push("".to_owned());
241 }
242 }
243 if brace_level != 0 {
244 return Err(SetVerParseError::UnclosedBrace);
245 }
246 if chars.next() != None {
247 return Err(SetVerParseError::TooManySets);
248 }
249
250 inner_sets.remove(inner_sets.len() - 1);
252 if inner_sets.is_empty() {
253 return Ok(Self::default());
254 }
255
256 let versions = inner_sets
257 .iter()
258 .map(|string_set| string_set.parse::<SetVersion>().map(Rc::new))
259 .collect::<Result<BTreeSet<Rc<SetVersion>>, SetVerParseError>>()?;
260 if versions.len() < inner_sets.len() {
261 return Err(SetVerParseError::NonUniqueElements);
262 }
263 Ok(Self { versions })
264 }
265}
266
267#[cfg(test)]
268mod tests {
269 use super::*;
270
271 #[test]
272 fn parse_correct_setver() -> Result<(), SetVerParseError> {
273 for test_string in
275 ["{}", "{{}}", "{{}{{}}}", "{{}{{}}{{}{{}}}}", "{{{{{{{}}}}}}}", "{{}{{}}{{{}}}}", "{{}{{{}}{{}{{}}}}}"]
276 {
277 assert_eq!(test_string.parse::<SetVersion>()?.to_string(), test_string);
278 }
279
280 Ok(())
281 }
282
283 #[test]
284 fn parse_incorrect_setver() {
285 assert_eq!("".parse::<SetVersion>().unwrap_err(), SetVerParseError::Empty);
286 assert_eq!("asd".parse::<SetVersion>().unwrap_err(), SetVerParseError::IllegalCharacter('a'));
287 assert_eq!("{{b}}".parse::<SetVersion>().unwrap_err(), SetVerParseError::IllegalCharacter('b'));
288 "{{}{}".parse::<SetVersion>().unwrap_err();
289 "}{}".parse::<SetVersion>().unwrap_err();
290 assert_eq!("{}{}".parse::<SetVersion>().unwrap_err(), SetVerParseError::TooManySets);
291 assert_eq!("{{}{}}".parse::<SetVersion>().unwrap_err(), SetVerParseError::NonUniqueElements);
292 assert_eq!("{{{}{}}{}}".parse::<SetVersion>().unwrap_err(), SetVerParseError::NonUniqueElements);
293 assert_eq!("{{}{{}{{}}}{{}{{}}}}".parse::<SetVersion>().unwrap_err(), SetVerParseError::NonUniqueElements);
294 }
295
296 #[test]
297 fn equality() {
298 assert_eq!("{}".parse::<SetVersion>().unwrap(), "{}".parse::<SetVersion>().unwrap());
299 assert_ne!("{{{}}}".parse::<SetVersion>().unwrap(), "{{}}".parse::<SetVersion>().unwrap());
300 assert_eq!("{{}{{}}}".parse::<SetVersion>().unwrap(), "{{{}}{}}".parse::<SetVersion>().unwrap());
301 assert_eq!(
302 "{{{{}{{}}}{{}}}{}}".parse::<SetVersion>().unwrap(),
303 "{{}{{{}}{{}{{}}}}}".parse::<SetVersion>().unwrap()
304 );
305 assert_eq!("{{{{}{{}}}{{}}}{}}".parse::<SetVersion>().unwrap(), "{{}{{{}}{{}{{}}}}}");
306 }
307
308 #[test]
309 fn integralternative() {
310 assert_eq!("{{}{{{}}{{}{{}}}}}".parse::<SetVersion>().unwrap().to_integralternative(), 35999);
311 assert_eq!("{{}{{{}}{{}{{}}}}}".parse::<SetVersion>().unwrap(), 35999);
312 assert_eq!(SetVersion::string_to_integralternative("{{{{}}{}}{{}}}"), 871);
313 assert_eq!(SetVersion::string_to_integralternative("{{{}}{{{}}{}}}"), 1591);
314 }
315}