1use crate::error::ModelsError;
4use massa_serialization::{Deserializer, Serializer, U32VarIntDeserializer, U32VarIntSerializer};
5use nom::bytes::complete::take;
6use nom::error::context;
7use nom::sequence::tuple;
8use nom::Parser;
9use nom::{
10 error::{ContextError, ParseError},
11 IResult,
12};
13use serde::de::Unexpected;
14use std::ops::Bound::Included;
15use std::{convert::TryInto, fmt, str::FromStr};
16
17const INSTANCE_LEN: usize = 4;
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub struct Version {
22 instance: [char; INSTANCE_LEN],
24 major: u32,
25 minor: u32,
26}
27
28struct VersionVisitor;
29
30impl<'de> serde::de::Visitor<'de> for VersionVisitor {
31 type Value = Version;
32
33 fn visit_str<E>(self, value: &str) -> Result<Version, E>
34 where
35 E: serde::de::Error,
36 {
37 Version::from_str(value).map_err(|_| E::invalid_value(Unexpected::Str(value), &self))
38 }
39
40 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
41 write!(
42 formatter,
43 "an Version type representing a version identifier"
44 )
45 }
46}
47
48impl<'de> serde::Deserialize<'de> for Version {
49 fn deserialize<D>(deserializer: D) -> Result<Version, D::Error>
50 where
51 D: serde::de::Deserializer<'de>,
52 {
53 deserializer.deserialize_str(VersionVisitor)
54 }
55}
56
57impl serde::Serialize for Version {
58 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59 where
60 S: serde::Serializer,
61 {
62 serializer.serialize_str(&self.to_string())
63 }
64}
65
66#[derive(Clone)]
68pub struct VersionSerializer {
69 u32_serializer: U32VarIntSerializer,
70}
71
72impl VersionSerializer {
73 pub const fn new() -> Self {
75 Self {
76 u32_serializer: U32VarIntSerializer::new(),
77 }
78 }
79}
80
81impl Default for VersionSerializer {
82 fn default() -> Self {
83 Self::new()
84 }
85}
86
87impl Serializer<Version> for VersionSerializer {
88 fn serialize(
100 &self,
101 value: &Version,
102 buffer: &mut Vec<u8>,
103 ) -> Result<(), massa_serialization::SerializeError> {
104 buffer.extend(value.instance.iter().map(|&c| c as u8));
105 self.u32_serializer.serialize(&value.major, buffer)?;
106 self.u32_serializer.serialize(&value.minor, buffer)?;
107 Ok(())
108 }
109}
110
111#[derive(Clone)]
113pub struct VersionDeserializer {
114 u32_deserializer: U32VarIntDeserializer,
115}
116
117impl VersionDeserializer {
118 pub const fn new() -> Self {
120 Self {
121 u32_deserializer: U32VarIntDeserializer::new(Included(0), Included(u32::MAX)),
122 }
123 }
124}
125
126impl Default for VersionDeserializer {
127 fn default() -> Self {
128 Self::new()
129 }
130}
131
132impl Deserializer<Version> for VersionDeserializer {
133 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
149 &self,
150 buffer: &'a [u8],
151 ) -> IResult<&'a [u8], Version, E> {
152 context(
153 "Failed Version deserialization",
154 tuple((
155 context("Failed instance deserialization", |input: &'a [u8]| {
156 let (rest, instance) = take(INSTANCE_LEN)(input)?;
157 if instance.iter().any(|c| {
158 !c.is_ascii() || !c.is_ascii_alphabetic() || !c.is_ascii_uppercase()
159 }) {
160 return Err(nom::Err::Error(ParseError::from_error_kind(
161 input,
162 nom::error::ErrorKind::Char,
163 )));
164 }
165 let instance: [char; INSTANCE_LEN] = instance
167 .iter()
168 .map(|&c| char::from(c))
169 .collect::<Vec<char>>()
170 .try_into()
171 .unwrap();
172 Ok((rest, instance))
173 }),
174 context("Failed major deserialization", |input: &'a [u8]| {
175 self.u32_deserializer.deserialize(input)
176 }),
177 context("Failed minor deserialization", |input: &'a [u8]| {
178 self.u32_deserializer.deserialize(input)
179 }),
180 )),
181 )
182 .map(|(instance, major, minor)| Version {
183 instance,
184 major,
185 minor,
186 })
187 .parse(buffer)
188 }
189}
190
191impl Version {
192 pub fn is_compatible(&self, other: &Version) -> bool {
194 self.instance == other.instance
195 && (self.major == other.major
196 || (self.major == 2 && other.major == 3)
197 || (self.major == 3 && other.major == 2))
198 }
199}
200
201impl fmt::Display for Version {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 let network_str: String = self.instance.iter().cloned().collect();
210 write!(f, "{}.{}.{}", network_str, self.major, self.minor)
211 }
212}
213
214impl FromStr for Version {
215 type Err = ModelsError;
216
217 fn from_str(str_version: &str) -> Result<Self, Self::Err> {
218 let parts: Vec<String> = str_version.split('.').map(|v| v.to_string()).collect();
219 if parts.len() != 3 {
220 return Err(ModelsError::InvalidVersionError(
221 "version identifier is not in 3 parts separates by a dot".into(),
222 ));
223 }
224 if parts[0].len() != 4
225 || !parts[0].is_ascii()
226 || parts[0]
227 .chars()
228 .any(|c| !c.is_ascii_alphabetic() || !c.is_ascii_uppercase())
229 {
230 return Err(ModelsError::InvalidVersionError(
231 "version identifier instance part is not 4-char uppercase alphabetic ASCII".into(),
232 ));
233 }
234 let instance: [char; 4] = parts[0].chars().collect::<Vec<char>>().try_into().unwrap(); let major: u32 = u32::from_str(&parts[1]).map_err(|_| {
236 ModelsError::InvalidVersionError("version identifier major number invalid".into())
237 })?;
238 let minor: u32 = u32::from_str(&parts[2]).map_err(|_| {
239 ModelsError::InvalidVersionError("version identifier minor number invalid".into())
240 })?;
241 Ok(Version {
242 instance,
243 major,
244 minor,
245 })
246 }
247}