python_marshal/
magic.rs

1#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Debug, Ord)]
2pub struct PyVersion {
3    pub major: u8,
4    pub minor: u8,
5    pub patch: u8, // Not used, here for completeness
6}
7
8impl PyVersion {
9    pub fn new(major: u8, minor: u8) -> Self {
10        Self {
11            major,
12            minor,
13            patch: 0,
14        }
15    }
16}
17
18impl Into<String> for PyVersion {
19    fn into(self) -> String {
20        format!("{}.{}.{}", self.major, self.minor, self.patch)
21    }
22}
23
24impl From<(u8, u8)> for PyVersion {
25    fn from(vers: (u8, u8)) -> Self {
26        Self {
27            major: vers.0,
28            minor: vers.1,
29            patch: 0,
30        }
31    }
32}
33
34impl From<(u8, u8, u8)> for PyVersion {
35    fn from(vers: (u8, u8, u8)) -> Self {
36        Self {
37            major: vers.0,
38            minor: vers.1,
39            patch: vers.2,
40        }
41    }
42}
43
44impl PyVersion {
45    const MAGIC_NUMBERS: &'static [(u32, PyVersion)] = &[
46        (
47            0x0A0D0C3B,
48            PyVersion {
49                major: 3,
50                minor: 0,
51                patch: 0,
52            },
53        ),
54        (
55            0x0A0D0C4F,
56            PyVersion {
57                major: 3,
58                minor: 1,
59                patch: 0,
60            },
61        ),
62        (
63            0x0A0D0C6C,
64            PyVersion {
65                major: 3,
66                minor: 2,
67                patch: 0,
68            },
69        ),
70        (
71            0x0A0D0C9E,
72            PyVersion {
73                major: 3,
74                minor: 3,
75                patch: 0,
76            },
77        ),
78        (
79            0x0A0D0CEE,
80            PyVersion {
81                major: 3,
82                minor: 4,
83                patch: 0,
84            },
85        ),
86        (
87            0x0A0D0D16,
88            PyVersion {
89                major: 3,
90                minor: 5,
91                patch: 0,
92            },
93        ),
94        (
95            0x0A0D0D33,
96            PyVersion {
97                major: 3,
98                minor: 6,
99                patch: 0,
100            },
101        ),
102        (
103            0x0A0D0D42,
104            PyVersion {
105                major: 3,
106                minor: 7,
107                patch: 0,
108            },
109        ),
110        (
111            0x0A0D0D55,
112            PyVersion {
113                major: 3,
114                minor: 8,
115                patch: 0,
116            },
117        ),
118        (
119            0x0A0D0D61,
120            PyVersion {
121                major: 3,
122                minor: 9,
123                patch: 0,
124            },
125        ),
126        (
127            0x0A0D0D6F,
128            PyVersion {
129                major: 3,
130                minor: 10,
131                patch: 0,
132            },
133        ),
134        (
135            0x0A0D0DA7,
136            PyVersion {
137                major: 3,
138                minor: 11,
139                patch: 0,
140            },
141        ),
142        (
143            0x0A0D0DCB,
144            PyVersion {
145                major: 3,
146                minor: 12,
147                patch: 0,
148            },
149        ),
150        (
151            0x0A0D0DF3,
152            PyVersion {
153                major: 3,
154                minor: 13,
155                patch: 0,
156            },
157        ),
158    ];
159
160    pub fn from_magic(magic: u32) -> Result<Self, crate::Error> {
161        Self::MAGIC_NUMBERS
162            .iter()
163            .find(|&&(num, _)| num == magic)
164            .map(|&(_, version)| version)
165            .ok_or(crate::Error::UnsupportedMagicNumber(magic))
166    }
167
168    pub fn to_magic(&self) -> Result<u32, crate::Error> {
169        Self::MAGIC_NUMBERS
170            .iter()
171            .find(|&&(_, ref version)| version == self)
172            .map(|&(num, _)| num)
173            .ok_or(crate::Error::UnsupportedPyVersion(self.clone()))
174    }
175}
176
177impl TryFrom<u32> for PyVersion {
178    type Error = crate::Error;
179
180    fn try_from(vers: u32) -> Result<Self, Self::Error> {
181        PyVersion::from_magic(vers)
182    }
183}
184
185impl TryFrom<PyVersion> for u32 {
186    type Error = crate::Error;
187
188    fn try_from(vers: PyVersion) -> Result<Self, Self::Error> {
189        vers.to_magic()
190    }
191}
192
193impl PartialEq<(u8, u8)> for PyVersion {
194    fn eq(&self, other: &(u8, u8)) -> bool {
195        self.major == other.0 && self.minor == other.1
196    }
197}
198
199impl PartialOrd<(u8, u8)> for PyVersion {
200    fn partial_cmp(&self, other: &(u8, u8)) -> Option<std::cmp::Ordering> {
201        Some(self.cmp(&PyVersion::new(other.0, other.1)))
202    }
203}
204
205impl std::fmt::Display for PyVersion {
206    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
208    }
209}