miden_assembly/library/
version.rs1use core::{
2 fmt,
3 str::{self, FromStr},
4};
5
6use crate::{
7 diagnostics::Diagnostic, ByteReader, ByteWriter, Deserializable, DeserializationError,
8 Serializable,
9};
10
11#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
13pub struct Version {
14 pub major: u16,
16 pub minor: u16,
18 pub patch: u16,
20}
21
22impl Version {
24 #[inline(always)]
26 pub const fn min() -> Self {
27 Self { major: 0, minor: 1, patch: 0 }
28 }
29}
30
31impl Version {
33 pub const fn to_nearest_major(self) -> Self {
37 Self { minor: 0, patch: 0, ..self }
38 }
39
40 pub const fn to_nearest_minor(self) -> Self {
44 Self { patch: 0, ..self }
45 }
46
47 pub const fn next_major(self) -> Self {
49 Self {
50 major: self.major + 1,
51 minor: 0,
52 patch: 0,
53 }
54 }
55
56 pub const fn next_minor(self) -> Self {
58 Self { minor: self.minor + 1, patch: 0, ..self }
59 }
60
61 pub const fn next_patch(self) -> Self {
63 Self { patch: self.patch + 1, ..self }
64 }
65}
66
67impl Default for Version {
68 fn default() -> Self {
69 Self::min()
70 }
71}
72impl fmt::Display for Version {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
75 }
76}
77impl Serializable for Version {
78 fn write_into<W: ByteWriter>(&self, target: &mut W) {
79 target.write_u16(self.major);
80 target.write_u16(self.minor);
81 target.write_u16(self.patch);
82 }
83}
84impl Deserializable for Version {
85 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
86 let major = source.read_u16()?;
87 let minor = source.read_u16()?;
88 let patch = source.read_u16()?;
89 Ok(Self { major, minor, patch })
90 }
91}
92
93#[derive(Debug, thiserror::Error, Diagnostic)]
95pub enum VersionError {
96 #[error("invalid version string: cannot be empty")]
97 #[diagnostic()]
98 Empty,
99 #[error("invalid version string: missing minor component, expected MAJOR.MINOR.PATCH")]
100 #[diagnostic()]
101 MissingMinor,
102 #[error("invalid version string: missing patch component, expected MAJOR.MINOR.PATCH")]
103 #[diagnostic()]
104 MissingPatch,
105 #[error("invalid version string: could not parse major version: {0}")]
106 #[diagnostic()]
107 Major(core::num::ParseIntError),
108 #[error("invalid version string: could not parse minor version: {0}")]
109 #[diagnostic()]
110 Minor(core::num::ParseIntError),
111 #[error("invalid version string: could not parse patch version: {0}")]
112 #[diagnostic()]
113 Patch(core::num::ParseIntError),
114 #[error(
115 "invalid version string: unsupported pre-release version, \
116 only MAJOR.MINOR.PATCH components are allowed"
117 )]
118 #[diagnostic()]
119 Unsupported,
120}
121
122impl FromStr for Version {
123 type Err = VersionError;
124
125 fn from_str(value: &str) -> Result<Self, Self::Err> {
126 let mut components = value.split('.');
127
128 let major = components
129 .next()
130 .ok_or(VersionError::Empty)?
131 .parse::<u16>()
132 .map_err(VersionError::Major)?;
133 let minor = components
134 .next()
135 .ok_or(VersionError::MissingMinor)?
136 .parse::<u16>()
137 .map_err(VersionError::Minor)?;
138 let patch = components
139 .next()
140 .ok_or(VersionError::MissingPatch)?
141 .parse::<u16>()
142 .map_err(VersionError::Patch)?;
143
144 if components.next().is_some() {
145 Err(VersionError::Unsupported)
146 } else {
147 Ok(Self { major, minor, patch })
148 }
149 }
150}