1 | use std::fmt; |
2 | |
3 | #[derive (Debug, PartialEq, Eq, Copy, Clone)] |
4 | enum Kind { |
5 | Dev, |
6 | Nightly, |
7 | Beta, |
8 | Stable, |
9 | } |
10 | |
11 | /// Release channel: "dev", "nightly", "beta", or "stable". |
12 | #[derive (Debug, PartialEq, Eq, Copy, Clone)] |
13 | pub struct Channel(Kind); |
14 | |
15 | impl Channel { |
16 | /// Reads the release channel of the running compiler. If it cannot be |
17 | /// determined (see the [top-level documentation](crate)), returns `None`. |
18 | /// |
19 | /// # Example |
20 | /// |
21 | /// ```rust |
22 | /// use version_check::Channel; |
23 | /// |
24 | /// match Channel::read() { |
25 | /// Some(c) => format!("The channel is: {}" , c), |
26 | /// None => format!("Failed to read the release channel." ) |
27 | /// }; |
28 | /// ``` |
29 | pub fn read() -> Option<Channel> { |
30 | ::get_version_and_date() |
31 | .and_then(|(version, _)| version) |
32 | .and_then(|version| Channel::parse(&version)) |
33 | } |
34 | |
35 | /// Parse a Rust release channel from a Rust release version string (of the |
36 | /// form `major[.minor[.patch[-channel]]]`). Returns `None` if `version` is |
37 | /// not a valid Rust version string. |
38 | /// |
39 | /// # Example |
40 | /// |
41 | /// ```rust |
42 | /// use version_check::Channel; |
43 | /// |
44 | /// let dev = Channel::parse("1.3.0-dev" ).unwrap(); |
45 | /// assert!(dev.is_dev()); |
46 | /// |
47 | /// let nightly = Channel::parse("1.42.2-nightly" ).unwrap(); |
48 | /// assert!(nightly.is_nightly()); |
49 | /// |
50 | /// let beta = Channel::parse("1.32.0-beta" ).unwrap(); |
51 | /// assert!(beta.is_beta()); |
52 | /// |
53 | /// let stable = Channel::parse("1.4.0" ).unwrap(); |
54 | /// assert!(stable.is_stable()); |
55 | /// ``` |
56 | pub fn parse(version: &str) -> Option<Channel> { |
57 | let version = version.trim(); |
58 | if version.contains("-dev" ) || version == "dev" { |
59 | Some(Channel(Kind::Dev)) |
60 | } else if version.contains("-nightly" ) || version == "nightly" { |
61 | Some(Channel(Kind::Nightly)) |
62 | } else if version.contains("-beta" ) || version == "beta" { |
63 | Some(Channel(Kind::Beta)) |
64 | } else if !version.contains("-" ) { |
65 | Some(Channel(Kind::Stable)) |
66 | } else { |
67 | None |
68 | } |
69 | } |
70 | |
71 | /// Returns the name of the release channel. |
72 | fn as_str(&self) -> &'static str { |
73 | match self.0 { |
74 | Kind::Dev => "dev" , |
75 | Kind::Beta => "beta" , |
76 | Kind::Nightly => "nightly" , |
77 | Kind::Stable => "stable" , |
78 | } |
79 | } |
80 | |
81 | /// Returns `true` if this channel supports feature flags. In other words, |
82 | /// returns `true` if the channel is either `dev` or `nightly`. |
83 | /// |
84 | /// # Example |
85 | /// |
86 | /// ```rust |
87 | /// use version_check::Channel; |
88 | /// |
89 | /// let dev = Channel::parse("1.3.0-dev" ).unwrap(); |
90 | /// assert!(dev.supports_features()); |
91 | /// |
92 | /// let nightly = Channel::parse("1.42.2-nightly" ).unwrap(); |
93 | /// assert!(nightly.supports_features()); |
94 | /// |
95 | /// let beta = Channel::parse("1.32.0-beta" ).unwrap(); |
96 | /// assert!(!beta.supports_features()); |
97 | /// |
98 | /// let stable = Channel::parse("1.4.0" ).unwrap(); |
99 | /// assert!(!stable.supports_features()); |
100 | /// ``` |
101 | pub fn supports_features(&self) -> bool { |
102 | match self.0 { |
103 | Kind::Dev | Kind::Nightly => true, |
104 | Kind::Beta | Kind::Stable => false |
105 | } |
106 | } |
107 | |
108 | /// Returns `true` if this channel is `dev` and `false` otherwise. |
109 | /// |
110 | /// # Example |
111 | /// |
112 | /// ```rust |
113 | /// use version_check::Channel; |
114 | /// |
115 | /// let dev = Channel::parse("1.3.0-dev" ).unwrap(); |
116 | /// assert!(dev.is_dev()); |
117 | /// |
118 | /// let stable = Channel::parse("1.0.0" ).unwrap(); |
119 | /// assert!(!stable.is_dev()); |
120 | /// ``` |
121 | pub fn is_dev(&self) -> bool { |
122 | match self.0 { |
123 | Kind::Dev => true, |
124 | _ => false |
125 | } |
126 | } |
127 | |
128 | /// Returns `true` if this channel is `nightly` and `false` otherwise. |
129 | /// |
130 | /// # Example |
131 | /// |
132 | /// ```rust |
133 | /// use version_check::Channel; |
134 | /// |
135 | /// let nightly = Channel::parse("1.3.0-nightly" ).unwrap(); |
136 | /// assert!(nightly.is_nightly()); |
137 | /// |
138 | /// let stable = Channel::parse("1.0.0" ).unwrap(); |
139 | /// assert!(!stable.is_nightly()); |
140 | /// ``` |
141 | pub fn is_nightly(&self) -> bool { |
142 | match self.0 { |
143 | Kind::Nightly => true, |
144 | _ => false |
145 | } |
146 | } |
147 | |
148 | /// Returns `true` if this channel is `beta` and `false` otherwise. |
149 | /// |
150 | /// # Example |
151 | /// |
152 | /// ```rust |
153 | /// use version_check::Channel; |
154 | /// |
155 | /// let beta = Channel::parse("1.3.0-beta" ).unwrap(); |
156 | /// assert!(beta.is_beta()); |
157 | /// |
158 | /// let stable = Channel::parse("1.0.0" ).unwrap(); |
159 | /// assert!(!stable.is_beta()); |
160 | /// ``` |
161 | pub fn is_beta(&self) -> bool { |
162 | match self.0 { |
163 | Kind::Beta => true, |
164 | _ => false |
165 | } |
166 | } |
167 | |
168 | /// Returns `true` if this channel is `stable` and `false` otherwise. |
169 | /// |
170 | /// # Example |
171 | /// |
172 | /// ```rust |
173 | /// use version_check::Channel; |
174 | /// |
175 | /// let stable = Channel::parse("1.0.0" ).unwrap(); |
176 | /// assert!(stable.is_stable()); |
177 | /// |
178 | /// let beta = Channel::parse("1.3.0-beta" ).unwrap(); |
179 | /// assert!(!beta.is_stable()); |
180 | /// ``` |
181 | pub fn is_stable(&self) -> bool { |
182 | match self.0 { |
183 | Kind::Stable => true, |
184 | _ => false |
185 | } |
186 | } |
187 | } |
188 | |
189 | impl fmt::Display for Channel { |
190 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
191 | write!(f, " {}" , self.as_str()) |
192 | } |
193 | } |
194 | |