khive_wire_protocol/
version.rs1use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
13#[serde(transparent)]
14pub struct ProtocolVersion(pub u32);
15
16impl ProtocolVersion {
17 pub const fn new(version: u32) -> Self {
18 Self(version)
19 }
20
21 pub const fn get(self) -> u32 {
22 self.0
23 }
24}
25
26impl From<u32> for ProtocolVersion {
27 fn from(value: u32) -> Self {
28 Self(value)
29 }
30}
31
32impl std::fmt::Display for ProtocolVersion {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 write!(f, "{}", self.0)
35 }
36}
37
38pub const CURRENT_VERSION: ProtocolVersion = ProtocolVersion(1);
40
41const _: () = assert!(CURRENT_VERSION.0 >= 1, "CURRENT_VERSION must be >= 1");
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub struct SupportedVersions {
55 min: ProtocolVersion,
56 max: ProtocolVersion,
57}
58
59impl SupportedVersions {
60 pub const fn current() -> Self {
62 let max = CURRENT_VERSION.0;
63 let min = if max > 1 { max - 1 } else { 1 };
64 Self {
65 min: ProtocolVersion(min),
66 max: ProtocolVersion(max),
67 }
68 }
69
70 pub const fn new(
86 min: ProtocolVersion,
87 max: ProtocolVersion,
88 ) -> Result<Self, SupportedVersionsError> {
89 if min.0 < 1 {
90 return Err(SupportedVersionsError::MinVersionZero);
91 }
92 if min.0 > max.0 {
93 return Err(SupportedVersionsError::InvertedRange);
94 }
95 if max.0 > CURRENT_VERSION.0 {
96 return Err(SupportedVersionsError::MaxAboveCurrent);
97 }
98 Ok(Self { min, max })
99 }
100
101 pub const fn min(self) -> ProtocolVersion {
102 self.min
103 }
104
105 pub const fn max(self) -> ProtocolVersion {
106 self.max
107 }
108
109 pub const fn contains(self, version: ProtocolVersion) -> bool {
110 version.0 >= self.min.0 && version.0 <= self.max.0
111 }
112}
113
114impl Default for SupportedVersions {
115 fn default() -> Self {
116 Self::current()
117 }
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
122pub enum SupportedVersionsError {
123 #[error("supported-version range floor must be >= 1 (version 0 does not exist)")]
126 MinVersionZero,
127 #[error("supported-version range is inverted: min must not exceed max")]
130 InvertedRange,
131 #[error("supported-version range max must not exceed the current protocol version")]
134 MaxAboveCurrent,
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
142 fn new_accepts_the_current_range() {
143 let supported =
144 SupportedVersions::new(ProtocolVersion::new(1), ProtocolVersion::new(1)).unwrap();
145 assert_eq!(supported.min(), ProtocolVersion::new(1));
146 assert_eq!(supported.max(), ProtocolVersion::new(1));
147 }
148
149 #[test]
150 fn new_rejects_a_range_above_current_version() {
151 for (min, max) in [(1, 2), (2, 2)] {
152 let err = SupportedVersions::new(ProtocolVersion::new(min), ProtocolVersion::new(max))
153 .unwrap_err();
154 assert_eq!(err, SupportedVersionsError::MaxAboveCurrent);
155 }
156 }
157
158 #[test]
159 fn new_rejects_an_inverted_range() {
160 let err =
161 SupportedVersions::new(ProtocolVersion::new(5), ProtocolVersion::new(2)).unwrap_err();
162 assert_eq!(err, SupportedVersionsError::InvertedRange);
163 }
164
165 #[test]
166 fn new_rejects_a_zero_min_version() {
167 let err =
171 SupportedVersions::new(ProtocolVersion::new(0), ProtocolVersion::new(1)).unwrap_err();
172 assert_eq!(err, SupportedVersionsError::MinVersionZero);
173 let err =
174 SupportedVersions::new(ProtocolVersion::new(0), ProtocolVersion::new(0)).unwrap_err();
175 assert_eq!(err, SupportedVersionsError::MinVersionZero);
176 }
177
178 #[test]
179 fn current_version_is_at_least_one() {
180 assert!(CURRENT_VERSION.get() >= 1);
184 }
185
186 #[test]
187 fn contains_is_inclusive_at_both_bounds() {
188 let supported =
191 SupportedVersions::new(ProtocolVersion::new(1), ProtocolVersion::new(1)).unwrap();
192 assert!(!supported.contains(ProtocolVersion::new(0)));
193 assert!(supported.contains(ProtocolVersion::new(1)));
194 assert!(!supported.contains(ProtocolVersion::new(2)));
195 }
196
197 #[test]
198 fn current_saturates_at_version_one() {
199 let supported = SupportedVersions::current();
202 assert_eq!(supported.min(), ProtocolVersion::new(1));
203 assert_eq!(supported.max(), ProtocolVersion::new(1));
204 }
205}