os_info/
bitness.rs

1// spell-checker:ignore getconf
2
3use std::fmt::{self, Display, Formatter};
4#[cfg(any(
5    target_os = "aix",
6    target_os = "dragonfly",
7    target_os = "freebsd",
8    target_os = "illumos",
9    target_os = "linux",
10    target_os = "macos",
11    target_os = "netbsd",
12    target_os = "openbsd"
13))]
14use std::process::{Command, Output};
15
16/// Operating system architecture in terms of how many bits compose the basic values it can deal with.
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[non_exhaustive]
20pub enum Bitness {
21    /// Unknown bitness (unable to determine).
22    Unknown,
23    /// 32-bit.
24    X32,
25    /// 64-bit.
26    X64,
27}
28
29impl Display for Bitness {
30    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
31        match *self {
32            Bitness::Unknown => write!(f, "unknown bitness"),
33            Bitness::X32 => write!(f, "32-bit"),
34            Bitness::X64 => write!(f, "64-bit"),
35        }
36    }
37}
38
39#[cfg(any(
40    target_os = "dragonfly",
41    target_os = "freebsd",
42    target_os = "linux",
43    target_os = "macos",
44))]
45pub fn get() -> Bitness {
46    match &Command::new("getconf").arg("LONG_BIT").output() {
47        Ok(Output { stdout, .. }) if stdout == b"32\n" => Bitness::X32,
48        Ok(Output { stdout, .. }) if stdout == b"64\n" => Bitness::X64,
49        _ => Bitness::Unknown,
50    }
51}
52
53#[cfg(target_os = "netbsd")]
54pub fn get() -> Bitness {
55    match &Command::new("sysctl")
56        .arg("-n")
57        .arg("hw.machine_arch")
58        .output()
59    {
60        Ok(Output { stdout, .. }) if stdout == b"amd64\n" => Bitness::X64,
61        Ok(Output { stdout, .. }) if stdout == b"x86_64\n" => Bitness::X64,
62        Ok(Output { stdout, .. }) if stdout == b"i386\n" => Bitness::X32,
63        Ok(Output { stdout, .. }) if stdout == b"aarch64\n" => Bitness::X64,
64        Ok(Output { stdout, .. }) if stdout == b"earmv7hf\n" => Bitness::X32,
65        Ok(Output { stdout, .. }) if stdout == b"sparc64\n" => Bitness::X64,
66        _ => Bitness::Unknown,
67    }
68}
69
70#[cfg(target_os = "openbsd")]
71pub fn get() -> Bitness {
72    match &Command::new("sysctl").arg("-n").arg("hw.machine").output() {
73        Ok(Output { stdout, .. }) if stdout == b"amd64\n" => Bitness::X64,
74        Ok(Output { stdout, .. }) if stdout == b"x86_64\n" => Bitness::X64,
75        Ok(Output { stdout, .. }) if stdout == b"i386\n" => Bitness::X32,
76        Ok(Output { stdout, .. }) if stdout == b"aarch64\n" => Bitness::X64,
77        Ok(Output { stdout, .. }) if stdout == b"earmv7hf\n" => Bitness::X32,
78        Ok(Output { stdout, .. }) if stdout == b"sparc64\n" => Bitness::X64,
79        _ => Bitness::Unknown,
80    }
81}
82
83#[cfg(target_os = "illumos")]
84pub fn get() -> Bitness {
85    match &Command::new("isainfo").arg("-b").output() {
86        Ok(Output { stdout, .. }) if stdout == b"64\n" => Bitness::X64,
87        Ok(Output { stdout, .. }) if stdout == b"32\n" => Bitness::X32,
88        _ => Bitness::Unknown,
89    }
90}
91
92#[cfg(target_os = "aix")]
93pub fn get() -> Bitness {
94    match &Command::new("prtconf").arg("-c").output() {
95        Ok(Output { stdout, .. }) if stdout == b"CPU Type: 64-bit\n" => Bitness::X64,
96        Ok(Output { stdout, .. }) if stdout == b"CPU Type: 32-bit\n" => Bitness::X32,
97        _ => Bitness::Unknown,
98    }
99}
100
101#[cfg(all(
102    test,
103    any(
104        target_os = "aix",
105        target_os = "dragonfly",
106        target_os = "freebsd",
107        target_os = "linux",
108        target_os = "macos",
109        target_os = "netbsd",
110        target_os = "openbsd"
111    )
112))]
113mod tests {
114    use super::*;
115    use pretty_assertions::assert_ne;
116
117    #[test]
118    fn get_bitness() {
119        let b = get();
120        assert_ne!(b, Bitness::Unknown);
121    }
122
123    #[test]
124    fn display() {
125        let data = [
126            (Bitness::Unknown, "unknown bitness"),
127            (Bitness::X32, "32-bit"),
128            (Bitness::X64, "64-bit"),
129        ];
130
131        for (bitness, expected) in &data {
132            assert_eq!(&bitness.to_string(), expected);
133        }
134    }
135}