aldrin_core/
protocol_version.rs

1use crate::error::{ProtocolVersionError, ProtocolVersionErrorKind};
2use std::fmt;
3use std::str::FromStr;
4
5#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
6pub struct ProtocolVersion {
7    minor: Minor,
8}
9
10impl ProtocolVersion {
11    pub const MAJOR: u32 = 1;
12    pub const V1_14: Self = Self { minor: Minor::V14 };
13    pub const V1_15: Self = Self { minor: Minor::V15 };
14    pub const V1_16: Self = Self { minor: Minor::V16 };
15    pub const V1_17: Self = Self { minor: Minor::V17 };
16    pub const V1_18: Self = Self { minor: Minor::V18 };
17    pub const V1_19: Self = Self { minor: Minor::V19 };
18    pub const MIN: Self = Self::V1_14;
19    pub const MAX: Self = Self::V1_19;
20
21    pub const fn new(major: u32, minor: u32) -> Result<Self, ProtocolVersionError> {
22        if major != Self::MAJOR {
23            return Err(ProtocolVersionError {
24                kind: ProtocolVersionErrorKind::InvalidMajor,
25            });
26        }
27
28        match minor {
29            14 => Ok(Self { minor: Minor::V14 }),
30            15 => Ok(Self { minor: Minor::V15 }),
31            16 => Ok(Self { minor: Minor::V16 }),
32            17 => Ok(Self { minor: Minor::V17 }),
33            18 => Ok(Self { minor: Minor::V18 }),
34            19 => Ok(Self { minor: Minor::V19 }),
35
36            _ => Err(ProtocolVersionError {
37                kind: ProtocolVersionErrorKind::InvalidMinor,
38            }),
39        }
40    }
41
42    pub const fn major(&self) -> u32 {
43        Self::MAJOR
44    }
45
46    pub const fn minor(&self) -> u32 {
47        self.minor as u32
48    }
49}
50
51#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
52enum Minor {
53    V14 = 14,
54    V15 = 15,
55    V16 = 16,
56    V17 = 17,
57    V18 = 18,
58    V19 = 19,
59}
60
61impl fmt::Display for ProtocolVersion {
62    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63        write!(f, "{}.{}", self.major(), self.minor())
64    }
65}
66
67impl FromStr for ProtocolVersion {
68    type Err = ProtocolVersionError;
69
70    fn from_str(s: &str) -> Result<Self, Self::Err> {
71        let (major, minor) = s.split_once('.').ok_or(ProtocolVersionErrorKind::Parse)?;
72        let major = major.parse().map_err(|_| ProtocolVersionErrorKind::Parse)?;
73        let minor = minor.parse().map_err(|_| ProtocolVersionErrorKind::Parse)?;
74        Self::new(major, minor)
75    }
76}
77
78#[cfg(test)]
79mod test {
80    use super::ProtocolVersion;
81    use crate::error::ProtocolVersionErrorKind;
82
83    #[test]
84    fn parse_protocol_version() {
85        assert_eq!("1.14".parse(), Ok(ProtocolVersion::V1_14));
86        assert_eq!("1.15".parse(), Ok(ProtocolVersion::V1_15));
87        assert_eq!("1.16".parse(), Ok(ProtocolVersion::V1_16));
88        assert_eq!("1.17".parse(), Ok(ProtocolVersion::V1_17));
89        assert_eq!("1.18".parse(), Ok(ProtocolVersion::V1_18));
90        assert_eq!("1.19".parse(), Ok(ProtocolVersion::V1_19));
91
92        assert_eq!(
93            "1.13".parse::<ProtocolVersion>(),
94            Err(ProtocolVersionErrorKind::InvalidMinor.into())
95        );
96        assert_eq!(
97            "1.20".parse::<ProtocolVersion>(),
98            Err(ProtocolVersionErrorKind::InvalidMinor.into())
99        );
100
101        assert_eq!(
102            "0.14".parse::<ProtocolVersion>(),
103            Err(ProtocolVersionErrorKind::InvalidMajor.into())
104        );
105        assert_eq!(
106            "1.0".parse::<ProtocolVersion>(),
107            Err(ProtocolVersionErrorKind::InvalidMinor.into())
108        );
109        assert_eq!(
110            "1.4294967295".parse::<ProtocolVersion>(),
111            Err(ProtocolVersionErrorKind::InvalidMinor.into())
112        );
113
114        assert_eq!(
115            "1.".parse::<ProtocolVersion>(),
116            Err(ProtocolVersionErrorKind::Parse.into())
117        );
118        assert_eq!(
119            ".14".parse::<ProtocolVersion>(),
120            Err(ProtocolVersionErrorKind::Parse.into())
121        );
122        assert_eq!(
123            "".parse::<ProtocolVersion>(),
124            Err(ProtocolVersionErrorKind::Parse.into())
125        );
126    }
127}