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