Skip to main content

node_js_release_info/
arch.rs

1use crate::error::NodeJsRelInfoError;
2#[cfg(feature = "json")]
3use serde::{Deserialize, Serialize};
4use std::env::consts::ARCH;
5use std::fmt::{Display, Formatter};
6use std::str::FromStr;
7
8/// The CPU architecture a Node.js distributable targets
9///
10/// Non-exhaustive: Node.js has added and removed target architectures over
11/// time, so new variants may appear in a minor release
12#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
13#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
14#[non_exhaustive]
15pub enum NodeJsArch {
16    /// 64-bit x86 (`x64`)
17    #[default]
18    #[cfg_attr(feature = "json", serde(rename = "x64"))]
19    X64,
20    /// 32-bit x86 (`x86`)
21    #[cfg_attr(feature = "json", serde(rename = "x86"))]
22    X86,
23    /// 64-bit ARM (`arm64`)
24    #[cfg_attr(feature = "json", serde(rename = "arm64"))]
25    Arm64,
26    /// 32-bit ARMv6 with hardware floating point (`armv6l`) - shipped up to
27    /// Node.js v11
28    #[cfg_attr(feature = "json", serde(rename = "armv6l"))]
29    Armv6l,
30    /// 32-bit ARMv7 with hardware floating point (`armv7l`) - shipped up to
31    /// Node.js v23
32    #[cfg_attr(feature = "json", serde(rename = "armv7l"))]
33    Armv7l,
34    /// 64-bit PowerPC, big-endian (`ppc64`)
35    #[cfg_attr(feature = "json", serde(rename = "ppc64"))]
36    Ppc64,
37    /// 64-bit PowerPC, little-endian (`ppc64le`)
38    #[cfg_attr(feature = "json", serde(rename = "ppc64le"))]
39    Ppc64le,
40    /// 64-bit IBM Z (`s390x`)
41    #[cfg_attr(feature = "json", serde(rename = "s390x"))]
42    S390x,
43}
44
45impl NodeJsArch {
46    /// Creates a new instance using the default architecture ([`X64`](NodeJsArch::X64))
47    ///
48    /// # Examples
49    ///
50    /// ```rust
51    /// use node_js_release_info::NodeJsArch;
52    /// assert_eq!(NodeJsArch::new(), NodeJsArch::X64);
53    /// ```
54    pub fn new() -> NodeJsArch {
55        NodeJsArch::default()
56    }
57
58    /// Determines the architecture of the current environment via
59    /// [`std::env::consts::ARCH`]
60    ///
61    /// # Errors
62    ///
63    /// Returns [`NodeJsRelInfoError::UnrecognizedArch`] when the current
64    /// architecture has no corresponding Node.js distributable
65    pub fn from_env() -> Result<NodeJsArch, NodeJsRelInfoError> {
66        NodeJsArch::from_str(ARCH)
67    }
68}
69
70impl Display for NodeJsArch {
71    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
72        let arch = match self {
73            NodeJsArch::X64 => "x64",
74            NodeJsArch::X86 => "x86",
75            NodeJsArch::Arm64 => "arm64",
76            NodeJsArch::Armv6l => "armv6l",
77            NodeJsArch::Armv7l => "armv7l",
78            NodeJsArch::Ppc64 => "ppc64",
79            NodeJsArch::Ppc64le => "ppc64le",
80            NodeJsArch::S390x => "s390x",
81        };
82
83        write!(f, "{arch}")
84    }
85}
86
87impl FromStr for NodeJsArch {
88    type Err = NodeJsRelInfoError;
89
90    fn from_str(s: &str) -> Result<NodeJsArch, NodeJsRelInfoError> {
91        match s {
92            "x64" | "x86_64" => Ok(NodeJsArch::X64),
93            "x86" => Ok(NodeJsArch::X86),
94            "arm64" | "aarch64" => Ok(NodeJsArch::Arm64),
95            "armv6l" => Ok(NodeJsArch::Armv6l),
96            "arm" | "armv7l" => Ok(NodeJsArch::Armv7l),
97            "ppc64" | "powerpc64" => Ok(NodeJsArch::Ppc64),
98            "ppc64le" => Ok(NodeJsArch::Ppc64le),
99            "s390x" => Ok(NodeJsArch::S390x),
100            _ => Err(NodeJsRelInfoError::UnrecognizedArch(s.to_string())),
101        }
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108
109    #[test]
110    fn it_initializes() {
111        let arch = NodeJsArch::new();
112        assert_eq!(arch, NodeJsArch::X64);
113    }
114
115    #[test]
116    fn it_initializes_with_defaults() {
117        let arch = NodeJsArch::default();
118        assert_eq!(arch, NodeJsArch::X64);
119    }
120
121    #[test]
122    fn it_initializes_from_str() {
123        let arch = NodeJsArch::from_str("x64").unwrap();
124
125        assert_eq!(arch, NodeJsArch::X64);
126
127        let arch = NodeJsArch::from_str("x86_64").unwrap();
128
129        assert_eq!(arch, NodeJsArch::X64);
130
131        let arch = NodeJsArch::from_str("x86").unwrap();
132
133        assert_eq!(arch, NodeJsArch::X86);
134
135        let arch = NodeJsArch::from_str("arm64").unwrap();
136
137        assert_eq!(arch, NodeJsArch::Arm64);
138
139        let arch = NodeJsArch::from_str("aarch64").unwrap();
140
141        assert_eq!(arch, NodeJsArch::Arm64);
142
143        let arch = NodeJsArch::from_str("arm").unwrap();
144
145        assert_eq!(arch, NodeJsArch::Armv7l);
146
147        let arch = NodeJsArch::from_str("armv6l").unwrap();
148
149        assert_eq!(arch, NodeJsArch::Armv6l);
150
151        let arch = NodeJsArch::from_str("ppc64").unwrap();
152
153        assert_eq!(arch, NodeJsArch::Ppc64);
154
155        let arch = NodeJsArch::from_str("ppc64le").unwrap();
156
157        assert_eq!(arch, NodeJsArch::Ppc64le);
158
159        let arch = NodeJsArch::from_str("powerpc64").unwrap();
160
161        assert_eq!(arch, NodeJsArch::Ppc64);
162
163        let arch = NodeJsArch::from_str("s390x").unwrap();
164
165        assert_eq!(arch, NodeJsArch::S390x);
166    }
167
168    #[test]
169    fn it_serializes_to_str() {
170        let text = format!("{}", NodeJsArch::X64);
171
172        assert_eq!(text, "x64");
173
174        let text = format!("{}", NodeJsArch::X86);
175
176        assert_eq!(text, "x86");
177
178        let text = format!("{}", NodeJsArch::Arm64);
179
180        assert_eq!(text, "arm64");
181
182        let text = format!("{}", NodeJsArch::Armv7l);
183
184        assert_eq!(text, "armv7l");
185
186        let text = format!("{}", NodeJsArch::Armv6l);
187
188        assert_eq!(text, "armv6l");
189
190        let text = format!("{}", NodeJsArch::Ppc64);
191
192        assert_eq!(text, "ppc64");
193
194        let text = format!("{}", NodeJsArch::Ppc64le);
195
196        assert_eq!(text, "ppc64le");
197
198        let text = format!("{}", NodeJsArch::S390x);
199
200        assert_eq!(text, "s390x");
201    }
202
203    #[test]
204    fn it_initializes_using_current_environment() {
205        NodeJsArch::from_env().unwrap();
206    }
207
208    #[test]
209    fn it_fails_when_arch_is_unrecognized() {
210        let err = NodeJsArch::from_str("NOPE!").unwrap_err();
211        assert!(matches!(err, NodeJsRelInfoError::UnrecognizedArch(x) if x == "NOPE!"));
212    }
213
214    #[test]
215    #[cfg(feature = "json")]
216    fn it_serializes_and_deserializes() {
217        let arch_json = serde_json::to_string(&NodeJsArch::X64).unwrap();
218        let arch: NodeJsArch = serde_json::from_str(&arch_json).unwrap();
219        assert_eq!(arch, NodeJsArch::X64);
220    }
221}