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 | /// **Please see the note on [feature detection](crate#feature-detection).** |
85 | /// |
86 | /// # Example |
87 | /// |
88 | /// ```rust |
89 | /// use version_check::Channel; |
90 | /// |
91 | /// let dev = Channel::parse("1.3.0-dev" ).unwrap(); |
92 | /// assert!(dev.supports_features()); |
93 | /// |
94 | /// let nightly = Channel::parse("1.42.2-nightly" ).unwrap(); |
95 | /// assert!(nightly.supports_features()); |
96 | /// |
97 | /// let beta = Channel::parse("1.32.0-beta" ).unwrap(); |
98 | /// assert!(!beta.supports_features()); |
99 | /// |
100 | /// let stable = Channel::parse("1.4.0" ).unwrap(); |
101 | /// assert!(!stable.supports_features()); |
102 | /// ``` |
103 | pub fn supports_features(&self) -> bool { |
104 | match self.0 { |
105 | Kind::Dev | Kind::Nightly => true, |
106 | Kind::Beta | Kind::Stable => false |
107 | } |
108 | } |
109 | |
110 | /// Returns `true` if this channel is `dev` and `false` otherwise. |
111 | /// |
112 | /// # Example |
113 | /// |
114 | /// ```rust |
115 | /// use version_check::Channel; |
116 | /// |
117 | /// let dev = Channel::parse("1.3.0-dev" ).unwrap(); |
118 | /// assert!(dev.is_dev()); |
119 | /// |
120 | /// let stable = Channel::parse("1.0.0" ).unwrap(); |
121 | /// assert!(!stable.is_dev()); |
122 | /// ``` |
123 | pub fn is_dev(&self) -> bool { |
124 | match self.0 { |
125 | Kind::Dev => true, |
126 | _ => false |
127 | } |
128 | } |
129 | |
130 | /// Returns `true` if this channel is `nightly` and `false` otherwise. |
131 | /// |
132 | /// # Example |
133 | /// |
134 | /// ```rust |
135 | /// use version_check::Channel; |
136 | /// |
137 | /// let nightly = Channel::parse("1.3.0-nightly" ).unwrap(); |
138 | /// assert!(nightly.is_nightly()); |
139 | /// |
140 | /// let stable = Channel::parse("1.0.0" ).unwrap(); |
141 | /// assert!(!stable.is_nightly()); |
142 | /// ``` |
143 | pub fn is_nightly(&self) -> bool { |
144 | match self.0 { |
145 | Kind::Nightly => true, |
146 | _ => false |
147 | } |
148 | } |
149 | |
150 | /// Returns `true` if this channel is `beta` and `false` otherwise. |
151 | /// |
152 | /// # Example |
153 | /// |
154 | /// ```rust |
155 | /// use version_check::Channel; |
156 | /// |
157 | /// let beta = Channel::parse("1.3.0-beta" ).unwrap(); |
158 | /// assert!(beta.is_beta()); |
159 | /// |
160 | /// let stable = Channel::parse("1.0.0" ).unwrap(); |
161 | /// assert!(!stable.is_beta()); |
162 | /// ``` |
163 | pub fn is_beta(&self) -> bool { |
164 | match self.0 { |
165 | Kind::Beta => true, |
166 | _ => false |
167 | } |
168 | } |
169 | |
170 | /// Returns `true` if this channel is `stable` and `false` otherwise. |
171 | /// |
172 | /// # Example |
173 | /// |
174 | /// ```rust |
175 | /// use version_check::Channel; |
176 | /// |
177 | /// let stable = Channel::parse("1.0.0" ).unwrap(); |
178 | /// assert!(stable.is_stable()); |
179 | /// |
180 | /// let beta = Channel::parse("1.3.0-beta" ).unwrap(); |
181 | /// assert!(!beta.is_stable()); |
182 | /// ``` |
183 | pub fn is_stable(&self) -> bool { |
184 | match self.0 { |
185 | Kind::Stable => true, |
186 | _ => false |
187 | } |
188 | } |
189 | } |
190 | |
191 | impl fmt::Display for Channel { |
192 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
193 | write!(f, " {}" , self.as_str()) |
194 | } |
195 | } |
196 | |