1use std::fmt;
2
3#[derive(Debug, PartialEq, Eq, Copy, Clone)]
4enum 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)]
13pub struct Channel(Kind);
14
15impl 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
189impl fmt::Display for Channel {
190 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191 write!(f, "{}", self.as_str())
192 }
193}
194