nix_compat/wire/
protocol_version.rs1static DEFAULT_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts(1, 37);
3
4#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub struct ProtocolVersion(u16);
12
13impl ProtocolVersion {
14 pub const fn from_parts(major: u8, minor: u8) -> Self {
15 Self(((major as u16) << 8) | minor as u16)
16 }
17
18 pub fn major(&self) -> u8 {
19 ((self.0 & 0xff00) >> 8) as u8
20 }
21
22 pub fn minor(&self) -> u8 {
23 (self.0 & 0x00ff) as u8
24 }
25}
26
27impl Default for ProtocolVersion {
28 fn default() -> Self {
29 DEFAULT_PROTOCOL_VERSION
30 }
31}
32
33impl PartialOrd for ProtocolVersion {
34 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
35 Some(self.cmp(other))
36 }
37}
38
39impl Ord for ProtocolVersion {
40 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
41 match self.major().cmp(&other.major()) {
42 std::cmp::Ordering::Less => std::cmp::Ordering::Less,
43 std::cmp::Ordering::Greater => std::cmp::Ordering::Greater,
44 std::cmp::Ordering::Equal => {
45 self.minor().cmp(&other.minor())
47 }
48 }
49 }
50}
51
52impl From<u16> for ProtocolVersion {
53 fn from(value: u16) -> Self {
54 Self::from_parts(((value & 0xff00) >> 8) as u8, (value & 0x00ff) as u8)
55 }
56}
57
58#[cfg(any(test, feature = "test"))]
59impl From<(u8, u8)> for ProtocolVersion {
60 fn from((major, minor): (u8, u8)) -> Self {
61 Self::from_parts(major, minor)
62 }
63}
64
65impl TryFrom<u64> for ProtocolVersion {
66 type Error = &'static str;
67
68 fn try_from(value: u64) -> Result<Self, Self::Error> {
69 if value & !0xffff != 0 {
70 return Err("only two least significant bits might be populated");
71 }
72
73 Ok((value as u16).into())
74 }
75}
76
77impl From<ProtocolVersion> for u16 {
78 fn from(value: ProtocolVersion) -> Self {
79 value.0
80 }
81}
82
83impl From<ProtocolVersion> for u64 {
84 fn from(value: ProtocolVersion) -> Self {
85 value.0 as u64
86 }
87}
88
89impl std::fmt::Display for ProtocolVersion {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 write!(f, "{}.{}", self.major(), self.minor())
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::ProtocolVersion;
98
99 #[test]
100 fn from_parts() {
101 let version = ProtocolVersion::from_parts(1, 37);
102 assert_eq!(version.major(), 1, "correct major");
103 assert_eq!(version.minor(), 37, "correct minor");
104 assert_eq!("1.37", &version.to_string(), "to_string");
105
106 assert_eq!(0x0125, Into::<u16>::into(version));
107 assert_eq!(0x0125, Into::<u64>::into(version));
108 }
109
110 #[test]
111 fn from_u16() {
112 let version = ProtocolVersion::from(0x0125_u16);
113 assert_eq!("1.37", &version.to_string());
114 }
115
116 #[test]
117 fn from_u64() {
118 let version = ProtocolVersion::try_from(0x0125_u64).expect("must succeed");
119 assert_eq!("1.37", &version.to_string());
120 }
121
122 #[test]
124 fn from_u64_fail() {
125 ProtocolVersion::try_from(0xaa0125_u64).expect_err("must fail");
126 }
127
128 #[test]
129 fn ord() {
130 let v0_37 = ProtocolVersion::from_parts(0, 37);
131 let v1_37 = ProtocolVersion::from_parts(1, 37);
132 let v1_40 = ProtocolVersion::from_parts(1, 40);
133
134 assert!(v0_37 < v1_37);
135 assert!(v1_37 > v0_37);
136 assert!(v1_37 < v1_40);
137 assert!(v1_40 > v1_37);
138 assert!(v1_40 <= v1_40);
139 }
140}