Skip to main content

node_js_release_info/
ext.rs

1use crate::error::NodeJsRelInfoError;
2#[cfg(feature = "json")]
3use serde::{Deserialize, Serialize};
4use std::fmt::{Display, Formatter};
5use std::str::FromStr;
6
7/// The file extension of a Node.js distributable
8///
9/// Non-exhaustive: Node.js has added and removed package formats over time,
10/// so new variants may appear in a minor release
11#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
12#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
13#[non_exhaustive]
14pub enum NodeJsPkgExt {
15    /// gzip-compressed tarball (`tar.gz`)
16    #[default]
17    #[cfg_attr(feature = "json", serde(rename = "tar.gz"))]
18    Targz,
19    /// xz-compressed tarball (`tar.xz`)
20    #[cfg_attr(feature = "json", serde(rename = "tar.xz"))]
21    Tarxz,
22    /// zip archive (`zip`) - Windows only
23    #[cfg_attr(feature = "json", serde(rename = "zip"))]
24    Zip,
25    /// Windows installer package (`msi`)
26    #[cfg_attr(feature = "json", serde(rename = "msi"))]
27    Msi,
28    /// 7-Zip archive (`7z`) - Windows only
29    #[cfg_attr(feature = "json", serde(rename = "7z"))]
30    S7z, // can't start w/ a number (X_x)
31}
32
33impl NodeJsPkgExt {
34    /// Creates a new instance using the default extension ([`Targz`](NodeJsPkgExt::Targz))
35    ///
36    /// # Examples
37    ///
38    /// ```rust
39    /// use node_js_release_info::NodeJsPkgExt;
40    /// assert_eq!(NodeJsPkgExt::new(), NodeJsPkgExt::Targz);
41    /// ```
42    pub fn new() -> NodeJsPkgExt {
43        NodeJsPkgExt::default()
44    }
45}
46impl Display for NodeJsPkgExt {
47    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
48        let arch = match self {
49            NodeJsPkgExt::Targz => "tar.gz",
50            NodeJsPkgExt::Tarxz => "tar.xz",
51            NodeJsPkgExt::Zip => "zip",
52            NodeJsPkgExt::Msi => "msi",
53            NodeJsPkgExt::S7z => "7z",
54        };
55
56        write!(f, "{arch}")
57    }
58}
59
60impl FromStr for NodeJsPkgExt {
61    type Err = NodeJsRelInfoError;
62
63    fn from_str(s: &str) -> Result<NodeJsPkgExt, NodeJsRelInfoError> {
64        match s {
65            "tar.gz" => Ok(NodeJsPkgExt::Targz),
66            "tar.xz" => Ok(NodeJsPkgExt::Tarxz),
67            "zip" => Ok(NodeJsPkgExt::Zip),
68            "msi" => Ok(NodeJsPkgExt::Msi),
69            "7z" => Ok(NodeJsPkgExt::S7z),
70            _ => Err(NodeJsRelInfoError::UnrecognizedExt(s.to_string())),
71        }
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn it_initializes() {
81        let ext = NodeJsPkgExt::new();
82        assert_eq!(ext, NodeJsPkgExt::Targz);
83    }
84
85    #[test]
86    fn it_initializes_with_defaults() {
87        let ext = NodeJsPkgExt::default();
88        assert_eq!(ext, NodeJsPkgExt::Targz);
89    }
90
91    #[test]
92    fn it_initializes_from_str() {
93        let ext = NodeJsPkgExt::from_str("tar.gz").unwrap();
94
95        assert_eq!(ext, NodeJsPkgExt::Targz);
96
97        let ext = NodeJsPkgExt::from_str("tar.xz").unwrap();
98
99        assert_eq!(ext, NodeJsPkgExt::Tarxz);
100
101        let ext = NodeJsPkgExt::from_str("zip").unwrap();
102
103        assert_eq!(ext, NodeJsPkgExt::Zip);
104
105        let ext = NodeJsPkgExt::from_str("msi").unwrap();
106
107        assert_eq!(ext, NodeJsPkgExt::Msi);
108
109        let ext = NodeJsPkgExt::from_str("7z").unwrap();
110
111        assert_eq!(ext, NodeJsPkgExt::S7z);
112    }
113
114    #[test]
115    fn it_serializes_to_str() {
116        let text = format!("{}", NodeJsPkgExt::Targz);
117
118        assert_eq!(text, "tar.gz");
119
120        let text = format!("{}", NodeJsPkgExt::Tarxz);
121
122        assert_eq!(text, "tar.xz");
123
124        let text = format!("{}", NodeJsPkgExt::Zip);
125
126        assert_eq!(text, "zip");
127
128        let text = format!("{}", NodeJsPkgExt::Msi);
129
130        assert_eq!(text, "msi");
131
132        let text = format!("{}", NodeJsPkgExt::S7z);
133
134        assert_eq!(text, "7z");
135    }
136
137    #[test]
138    fn it_fails_when_ext_is_unrecognized() {
139        let err = NodeJsPkgExt::from_str("NOPE!").unwrap_err();
140        assert!(matches!(err, NodeJsRelInfoError::UnrecognizedExt(x) if x == "NOPE!"));
141    }
142
143    #[test]
144    #[cfg(feature = "json")]
145    fn it_serializes_and_deserializes() {
146        let ext_json = serde_json::to_string(&NodeJsPkgExt::Tarxz).unwrap();
147        let ext: NodeJsPkgExt = serde_json::from_str(&ext_json).unwrap();
148        assert_eq!(ext, NodeJsPkgExt::Tarxz);
149    }
150}