vulkano/
version.rs

1// The `Version` object is reexported from the `instance` module.
2
3use std::{
4    fmt::{Debug, Display, Error as FmtError, Formatter},
5    num::ParseIntError,
6    str::FromStr,
7};
8
9// Generated by build.rs
10include!(concat!(env!("OUT_DIR"), "/version.rs"));
11
12/// Represents an API version of Vulkan.
13#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
14pub struct Version {
15    /// Major version number.
16    pub major: u32,
17    /// Minor version number.
18    pub minor: u32,
19    /// Patch version number.
20    pub patch: u32,
21}
22
23impl Version {
24    pub const V1_0: Version = Version::major_minor(1, 0);
25    pub const V1_1: Version = Version::major_minor(1, 1);
26    pub const V1_2: Version = Version::major_minor(1, 2);
27    pub const V1_3: Version = Version::major_minor(1, 3);
28    pub const V1_4: Version = Version::major_minor(1, 4);
29    pub const V1_5: Version = Version::major_minor(1, 5);
30    pub const V1_6: Version = Version::major_minor(1, 6);
31
32    /// Constructs a `Version` from the given major and minor version numbers.
33    #[inline]
34    pub const fn major_minor(major: u32, minor: u32) -> Version {
35        Version {
36            major,
37            minor,
38            patch: 0,
39        }
40    }
41}
42
43impl Default for Version {
44    #[inline]
45    fn default() -> Self {
46        Self::V1_0
47    }
48}
49
50impl From<u32> for Version {
51    #[inline]
52    fn from(val: u32) -> Self {
53        Version {
54            major: ash::vk::api_version_major(val),
55            minor: ash::vk::api_version_minor(val),
56            patch: ash::vk::api_version_patch(val),
57        }
58    }
59}
60
61impl TryFrom<Version> for u32 {
62    type Error = ();
63
64    #[inline]
65    fn try_from(val: Version) -> Result<Self, Self::Error> {
66        if val.major <= 0x3ff && val.minor <= 0x3ff && val.patch <= 0xfff {
67            Ok(ash::vk::make_api_version(
68                0, val.major, val.minor, val.patch,
69            ))
70        } else {
71            Err(())
72        }
73    }
74}
75
76impl FromStr for Version {
77    type Err = ParseIntError;
78
79    #[inline]
80    fn from_str(s: &str) -> Result<Self, Self::Err> {
81        let mut iter = s.splitn(3, '.');
82        let major: u32 = iter.next().unwrap().parse()?;
83        let minor: u32 = iter.next().map_or(Ok(0), |n| n.parse())?;
84        let patch: u32 = iter.next().map_or(Ok(0), |n| n.parse())?;
85
86        Ok(Version {
87            major,
88            minor,
89            patch,
90        })
91    }
92}
93
94impl Debug for Version {
95    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
96        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
97    }
98}
99
100impl Display for Version {
101    #[inline]
102    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
103        Debug::fmt(self, f)
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::Version;
110
111    #[test]
112    fn into_vk_version() {
113        let version = Version {
114            major: 1,
115            minor: 0,
116            patch: 0,
117        };
118        assert_eq!(u32::try_from(version).unwrap(), 0x400000);
119    }
120
121    #[test]
122    fn greater_major() {
123        let v1 = Version {
124            major: 1,
125            minor: 0,
126            patch: 0,
127        };
128        let v2 = Version {
129            major: 2,
130            minor: 0,
131            patch: 0,
132        };
133        assert!(v2 > v1);
134    }
135
136    #[test]
137    fn greater_minor() {
138        let v1 = Version {
139            major: 1,
140            minor: 1,
141            patch: 0,
142        };
143        let v2 = Version {
144            major: 1,
145            minor: 3,
146            patch: 0,
147        };
148        assert!(v2 > v1);
149    }
150
151    #[test]
152    fn greater_patch() {
153        let v1 = Version {
154            major: 1,
155            minor: 0,
156            patch: 4,
157        };
158        let v2 = Version {
159            major: 1,
160            minor: 0,
161            patch: 5,
162        };
163        assert!(v2 > v1);
164    }
165
166    #[test]
167    fn version_parse() {
168        assert!(matches!(
169            "1.1.1".parse::<Version>(),
170            Ok(Version {
171                major: 1,
172                minor: 1,
173                patch: 1,
174            })
175        ));
176        assert!(matches!(
177            "1.1".parse::<Version>(),
178            Ok(Version {
179                major: 1,
180                minor: 1,
181                patch: 0,
182            })
183        ));
184        assert!(matches!(
185            "1".parse::<Version>(),
186            Ok(Version {
187                major: 1,
188                minor: 0,
189                patch: 0,
190            })
191        ));
192
193        assert!("".parse::<Version>().is_err());
194        assert!("1.1.1.1".parse::<Version>().is_err());
195        assert!("foobar".parse::<Version>().is_err());
196        assert!("1.bar".parse::<Version>().is_err());
197    }
198}