1use 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#[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,
23 X32,
25 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}