1#[cfg(target_os = "ios")]
2pub mod ios;
3#[cfg(target_os = "linux")]
4pub mod linux;
5#[cfg(target_os = "macos")]
6pub mod macos;
7#[cfg(target_os = "windows")]
8pub mod windows;
9
10use std::sync::OnceLock;
11
12use cfg_if::cfg_if;
13
14#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
15pub struct Version {
16 pub major: u32,
17 pub minor: u32,
18 pub patch: u32,
19 pub build: u32,
20}
21
22type VersionTuple = (u32, u32, u32, u32);
23
24static OS_VERSION: OnceLock<Version> = OnceLock::new();
25
26pub fn os_version() -> &'static Version {
27 OS_VERSION.get_or_init(|| {
28 cfg_if! {
29 if #[cfg(target_os = "ios")] {
30 ios::get_version()
31 } else if #[cfg(target_os = "linux")] {
32 linux::get_version()
33 } else if #[cfg(target_os = "macos")] {
34 macos::get_version()
35 } else if #[cfg(target_os = "windows")] {
36 windows::get_version()
37 } else {
38 Version::default()
39 }
40 }
41 })
42}
43
44impl Version {
45 pub const fn new(major: u32, minor: u32, patch: u32, build: u32) -> Self {
46 Self {
47 major,
48 minor,
49 patch,
50 build,
51 }
52 }
53
54 pub const fn from((major, minor, patch, build): VersionTuple) -> Self {
55 Self {
56 major,
57 minor,
58 patch,
59 build,
60 }
61 }
62}
63
64impl From<Version> for VersionTuple {
65 fn from(version: Version) -> Self {
66 (version.major, version.minor, version.patch, version.build)
67 }
68}
69
70impl From<VersionTuple> for Version {
71 fn from(tuple: VersionTuple) -> Self {
72 Self::from(tuple)
73 }
74}
75
76#[macro_export]
77macro_rules! if_greater_than {
78 {($major:expr) => $block:block $(else $else_block:block)?} => {
79 if_greater_than!{($major, 0, 0, 0) => $block $(else {$else_block})?}
80 };
81 {($major:expr, $minor:expr) => $block:block $(else $else_block:block)?} => {
82 if_greater_than!{($major, $minor, 0, 0) => $block $(else {$else_block})?}
83 };
84 {($major:expr, $minor:expr, $patch:expr) => $block:block $(else $else_block:block)?} => {
85 if_greater_than!{($major, $minor, $patch, 0) => $block $(else {$else_block})?}
86 };
87 {($major:expr, $minor:expr, $patch:expr, $build:expr) => $block:block $(else $else_block:block)?} => {
88 if_greater_than!{os_ver::Version { major: $major, minor: $minor, patch: $patch, build: $build } => $block $(else {$else_block})?}
89 };
90 {$version:expr => $block:block $(else $else_block:block)?} => {
91 if os_ver::os_version() >= &$version {
92 $block
93 } $(else {
94 $else_block
95 })?
96 };
97}