Coverage Report

Created: 2021-12-20 10:48

/home/runner/work/rustc-semver/rustc-semver/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
1
#![no_std]#![no_std]
2
3
use core::{cmp::Ordering, fmt::Display, num::ParseIntError};
4
5
/// `Error` represents an Error during parsing of a [`RustcVersion`].
6
14
#[derive(
D0
ebu
g0
, Eq, PartialEq, Copy,
Clone0
)]
7
pub enum Error {
8
    /// A version was passed that has too many elements seperated by `'.'`.
9
    TooManyElements,
10
    /// A version was passed that neither is a [`SpecialVersion`], nor a
11
    /// normal [`RustcVersion`].
12
    NotASpecialVersion,
13
    /// A version was passed, that was either an empty string or a part of the
14
    /// version was left out, e.g. `1.  .3`
15
    EmptyVersionPart,
16
    /// A version was passed that has unallowed chracters.
17
    ParseIntError,
18
}
19
20
impl From<ParseIntError> for Error {
21
2
    fn from(_: ParseIntError) -> Self {
22
2
        Self::ParseIntError
23
2
    }
24
}
25
26
/// Result type for this crate
27
pub type Result<T> = core::result::Result<T, Error>;
28
29
/// `RustcVersion` represents a version of the Rust Compiler.
30
///
31
/// This struct only supports the [`NormalVersion`] format
32
/// ```text
33
/// major.minor.patch
34
/// ```
35
/// and 3 special formats represented by the [`SpecialVersion`] enum.
36
///
37
/// A version can be created with one of the functions [`RustcVersion::new`] or
38
/// [`RustcVersion::parse`]. The [`RustcVersion::new`] method only supports the
39
/// normal version format.
40
///
41
/// You can compare two versions, just as you would expect:
42
///
43
/// ```rust
44
/// use rustc_semver::RustcVersion;
45
///
46
/// assert!(RustcVersion::new(1, 34, 0) > RustcVersion::parse("1.10").unwrap());
47
/// assert!(RustcVersion::new(1, 34, 0) > RustcVersion::parse("0.9").unwrap());
48
/// ```
49
///
50
/// This comparison is semver conform according to the [semver definition of
51
/// precedence]. However, if you want to check whether one version meets
52
/// another version according to the [Caret Requirements], you should use
53
/// [`RustcVersion::meets`].
54
///
55
/// [Caret Requirements]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements
56
/// [semver definition of precedence]: https://semver.org/#spec-item-11
57
22
#[derive(
D0
ebu
g0
, Eq, PartialEq, Copy,
Clone0
)]
Unexecuted instantiation: <rustc_semver::RustcVersion as core::cmp::PartialEq>::ne
<rustc_semver::RustcVersion as core::cmp::PartialEq>::eq
Line
Count
Source
57
22
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
58
pub enum RustcVersion {
59
    Normal(NormalVersion),
60
    Special(SpecialVersion),
61
}
62
63
/// `NormalVersion` represents a normal version used for all releases since
64
/// Rust 1.0.0.
65
///
66
/// This struct supports versions in the format
67
/// ```test
68
/// major.minor.patch
69
/// ```
70
0
#[derive(Debug, Copy, Clone)]
71
pub struct NormalVersion {
72
    major: u32,
73
    minor: u32,
74
    patch: u32,
75
    omitted: OmittedParts,
76
}
77
78
0
#[derive(Debug, Copy, Clone)]
79
enum OmittedParts {
80
    None,
81
    Minor,
82
    Patch,
83
}
84
85
impl From<usize> for OmittedParts {
86
39
    fn from(parts: usize) -> Self {
87
39
        match parts {
88
11
            1 => Self::Minor,
89
18
            2 => Self::Patch,
90
8
            3 => Self::None,
91
2
            _ => unreachable!(
92
2
                "This function should never be called with `parts == 0` or `parts > 3`"
93
2
            ),
94
        }
95
37
    }
96
}
97
98
/// `SpecialVersion` represents a special version from the first releases.
99
///
100
/// Before Rust 1.0.0, there were two alpha and one beta release, namely
101
///
102
/// - `1.0.0-alpha`
103
/// - `1.0.0-alpha.2`
104
/// - `1.0.0-beta`
105
///
106
/// This enum represents those releases.
107
9
#[derive(
D0
ebu
g0
, Eq, PartialEq, Copy,
Clone0
)]
108
pub enum SpecialVersion {
109
    Alpha,
110
    Alpha2,
111
    Beta,
112
}
113
114
impl PartialOrd for RustcVersion {
115
18
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
116
18
        Some(self.cmp(other))
117
18
    }
118
}
119
120
impl Ord for RustcVersion {
121
    fn cmp(&self, other: &Self) -> Ordering {
122
21
        match (self, other) {
123
8
            (Self::Normal(ver), Self::Normal(o_ver)) => ver.cmp(o_ver),
124
2
            (Self::Normal(NormalVersion { major, .. }), Self::Special(_)) => {
125
2
                if *major >= 1 {
126
1
                    Ordering::Greater
127
                } else {
128
1
                    Ordering::Less
129
                }
130
            }
131
2
            (Self::Special(_), Self::Normal(NormalVersion { major, .. })) => {
132
2
                if *major >= 1 {
133
1
                    Ordering::Less
134
                } else {
135
1
                    Ordering::Greater
136
                }
137
            }
138
9
            (Self::Special(s_ver), Self::Special(o_s_ver)) => s_ver.cmp(o_s_ver),
139
        }
140
21
    }
141
}
142
143
impl PartialOrd for NormalVersion {
144
34
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
145
34
        Some(self.cmp(other))
146
34
    }
147
}
148
149
impl Ord for NormalVersion {
150
42
    fn cmp(&self, other: &Self) -> Ordering {
151
42
        match self.major.cmp(&other.major) {
152
32
            Ordering::Equal => match self.minor.cmp(&other.minor) {
153
19
                Ordering::Equal => self.patch.cmp(&other.patch),
154
13
                ord => ord,
155
            },
156
10
            ord => ord,
157
        }
158
42
    }
159
}
160
161
impl PartialEq for NormalVersion {
162
7
    fn eq(&self, other: &Self) -> bool {
163
7
        self.major == other.major && self.minor == other.minor && self.patch == other.patch
164
7
    }
165
}
166
167
impl Eq for NormalVersion {}
168
169
impl PartialOrd for SpecialVersion {
170
0
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
171
0
        Some(self.cmp(other))
172
0
    }
173
}
174
175
impl Ord for SpecialVersion {
176
    fn cmp(&self, other: &Self) -> Ordering {
177
9
        match (self, other) {
178
            (Self::Alpha, Self::Alpha)
179
            | (Self::Alpha2, Self::Alpha2)
180
3
            | (Self::Beta, Self::Beta) => Ordering::Equal,
181
3
            (Self::Alpha, _) | (Self::Alpha2, Self::Beta) => Ordering::Less,
182
3
            (Self::Beta, _) | (Self::Alpha2, Self::Alpha) => Ordering::Greater,
183
        }
184
9
    }
185
}
186
187
impl Display for RustcVersion {
188
4
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
189
4
        match self {
190
            Self::Normal(NormalVersion {
191
1
                major,
192
1
                minor,
193
1
                patch,
194
1
                ..
195
1
            }) => write!(f, "{}.{}.{}", major, minor, patch),
196
3
            Self::Special(special) => write!(f, "{}", special),
197
        }
198
4
    }
199
}
200
201
impl Display for SpecialVersion {
202
3
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
203
3
        match self {
204
1
            Self::Alpha => write!(f, "1.0.0-alpha"),
205
1
            Self::Alpha2 => write!(f, "1.0.0-alpha.2"),
206
1
            Self::Beta => write!(f, "1.0.0-beta"),
207
        }
208
3
    }
209
}
210
211
impl From<[u32; 3]> for NormalVersion {
212
37
    fn from(arr: [u32; 3]) -> Self {
213
37
        NormalVersion {
214
37
            major: arr[0],
215
37
            minor: arr[1],
216
37
            patch: arr[2],
217
37
            omitted: OmittedParts::None,
218
37
        }
219
37
    }
220
}
221
222
const ACCEPTED_SPECIAL_VERSIONS: [(&str, SpecialVersion); 3] = [
223
    ("1.0.0-alpha", SpecialVersion::Alpha),
224
    ("1.0.0-alpha.2", SpecialVersion::Alpha2),
225
    ("1.0.0-beta", SpecialVersion::Beta),
226
];
227
228
impl RustcVersion {
229
    /// `RustcVersion::new` is a `const` constructor for a `RustcVersion`.
230
    ///
231
    /// This function is primarily used to construct constants, for everything
232
    /// else use [`RustcVersion::parse`].
233
    ///
234
    /// This function only allows to construct normal versions. For special
235
    /// versions, construct them directly with the [`SpecialVersion`] enum.
236
    ///
237
    /// # Examples
238
    ///
239
    /// ```rust
240
    /// use rustc_semver::RustcVersion;
241
    ///
242
    /// const MY_FAVORITE_RUST: RustcVersion = RustcVersion::new(1, 48, 0);
243
    ///
244
    /// assert!(MY_FAVORITE_RUST > RustcVersion::new(1, 0, 0))
245
    /// ```
246
65
    pub const fn new(major: u32, minor: u32, patch: u32) -> Self {
247
65
        Self::Normal(NormalVersion {
248
65
            major,
249
65
            minor,
250
65
            patch,
251
65
            omitted: OmittedParts::None,
252
65
        })
253
65
    }
254
255
    /// `RustcVersion::parse` parses a [`RustcVersion`].
256
    ///
257
    /// This function can parse all normal and special versions. It is possbile
258
    /// to omit parts of the version, like the patch or minor version part. So
259
    /// `1`, `1.0`, and `1.0.0` are all valid inputs and will result in the
260
    /// same version.
261
    ///
262
    /// # Errors
263
    ///
264
    /// This function returns an [`Error`], if the passed string is not a valid
265
    /// [`RustcVersion`]
266
    ///
267
    /// # Examples
268
    ///
269
    /// ```rust
270
    /// use rustc_semver::{SpecialVersion, RustcVersion};
271
    ///
272
    /// let ver = RustcVersion::new(1, 0, 0);
273
    ///
274
    /// assert_eq!(RustcVersion::parse("1").unwrap(), ver);
275
    /// assert_eq!(RustcVersion::parse("1.0").unwrap(), ver);
276
    /// assert_eq!(RustcVersion::parse("1.0.0").unwrap(), ver);
277
    /// assert_eq!(
278
    ///     RustcVersion::parse("1.0.0-alpha").unwrap(),
279
    ///     RustcVersion::Special(SpecialVersion::Alpha)
280
    /// );
281
    /// ```
282
65
    pub fn parse(version: &str) -> Result<Self> {
283
182
        let special_version = ACCEPTED_SPECIAL_VERSIONS.iter().find_map(|sv| {
284
182
            if version == sv.0 {
285
14
                Some(sv.1)
286
            } else {
287
168
                None
288
            }
289
182
        }
)65
;
290
65
        if let Some(
special_version14
) = special_version {
291
14
            return Ok(RustcVersion::Special(special_version));
292
51
        }
293
51
294
51
        let mut rustc_version = [0_u32; 3];
295
51
        let mut parts = 0;
296
101
        for (i, part) in 
version.split('.').enumerate()51
{
297
101
            let part = part.trim();
298
101
            if part.is_empty() {
299
7
                return Err(Error::EmptyVersionPart);
300
94
            }
301
94
            if i == 3 {
302
1
                return Err(Error::TooManyElements);
303
93
            }
304
93
            match str::parse(part) {
305
87
                Ok(part) => rustc_version[i] = part,
306
6
                Err(e) => {
307
6
                    if i == 2 {
308
4
                        return Err(Error::NotASpecialVersion);
309
                    } else {
310
2
                        return Err(e.into());
311
                    }
312
                }
313
            }
314
315
87
            parts = i + 1;
316
        }
317
318
37
        let mut ver = NormalVersion::from(rustc_version);
319
37
        ver.omitted = OmittedParts::from(parts);
320
37
        Ok(RustcVersion::Normal(ver))
321
65
    }
322
323
    /// `RustcVersion::meets` implements a semver conform version check
324
    /// according to the [Caret Requirements].
325
    ///
326
    /// Note that [`SpecialVersion`]s only meet themself and no other version
327
    /// meets a [`SpecialVersion`]. This is because [according to semver],
328
    /// special versions are considered unstable and "might not satisfy the
329
    /// intended compatibility requirements as denoted by \[their\] associated
330
    /// normal version".
331
    ///
332
    /// # Examples
333
    ///
334
    /// ```rust
335
    /// use rustc_semver::RustcVersion;
336
    ///
337
    /// assert!(RustcVersion::new(1, 30, 0).meets(RustcVersion::parse("1.29").unwrap()));
338
    /// assert!(!RustcVersion::new(1, 30, 0).meets(RustcVersion::parse("1.31").unwrap()));
339
    ///
340
    /// assert!(RustcVersion::new(0, 2, 1).meets(RustcVersion::parse("0.2").unwrap()));
341
    /// assert!(!RustcVersion::new(0, 3, 0).meets(RustcVersion::parse("0.2").unwrap()));
342
    /// ```
343
    ///
344
    /// [Caret Requirements]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements
345
    /// [according to semver]: https://semver.org/#spec-item-9
346
    pub fn meets(self, other: Self) -> bool {
347
46
        match (self, other) {
348
12
            (RustcVersion::Special(_), _) | (_, RustcVersion::Special(_)) => self == other,
349
34
            (RustcVersion::Normal(ver), RustcVersion::Normal(o_ver)) => {
350
                // In any case must `self` be bigger than `other`, with the major part matching
351
                // the other version.
352
34
                let mut meets = ver >= o_ver && 
ver.major == o_ver.major31
;
353
354
                // In addition, the left-most non-zero digit must not be modified.
355
34
                match o_ver.omitted {
356
                    OmittedParts::None => {
357
                        // Nothing was omitted, this means that everything must match in case of
358
                        // leading zeros.
359
14
                        if o_ver.major == 0 {
360
                            // Leading 0 in major position, check for
361
                            // `self.minor == other.minor`
362
9
                            meets &= ver.minor == o_ver.minor;
363
9
364
9
                            if o_ver.minor == 0 {
365
5
                                // Leading 0 in minor position, check for
366
5
                                // `self.patch == other.patch`.
367
5
                                meets &= ver.patch == o_ver.patch;
368
5
                            }
4
369
5
                        }
370
                    }
371
                    OmittedParts::Patch => {
372
                        // The patch version was omitted, this means the patch version of `self`
373
                        // does not have to match the patch version of `other`.
374
12
                        if o_ver.major == 0 {
375
7
                            meets &= ver.minor == o_ver.minor;
376
7
                        }
5
377
                    }
378
8
                    OmittedParts::Minor => {
379
8
                        // The minor (and patch) version was omitted, this means
380
8
                        // the minor and patch version of `self` do not have to
381
8
                        // match the minor and patch version of `other`
382
8
                    }
383
                }
384
385
34
                meets
386
            }
387
        }
388
46
    }
389
}
390
391
#[cfg(test)]
392
mod test {
393
    use super::*;
394
395
1
    #[test]
396
1
    fn omitted_parts() {
397
1
        assert_eq!(
398
1
            RustcVersion::parse("1.0.0").unwrap(),
399
1
            RustcVersion::new(1, 0, 0)
400
1
        );
401
1
        assert_eq!(
402
1
            RustcVersion::parse("1.0").unwrap(),
403
1
            RustcVersion::new(1, 0, 0)
404
1
        );
405
1
        assert_eq!(
406
1
            RustcVersion::parse("1").unwrap(),
407
1
            RustcVersion::new(1, 0, 0)
408
1
        );
409
1
    }
410
411
1
    #[test]
412
1
    fn special_versions() {
413
1
        assert_eq!(
414
1
            RustcVersion::parse("1.0.0-alpha").unwrap(),
415
1
            RustcVersion::Special(SpecialVersion::Alpha)
416
1
        );
417
1
        assert_eq!(
418
1
            RustcVersion::parse("1.0.0-alpha.2").unwrap(),
419
1
            RustcVersion::Special(SpecialVersion::Alpha2)
420
1
        );
421
1
        assert_eq!(
422
1
            RustcVersion::parse("1.0.0-beta").unwrap(),
423
1
            RustcVersion::Special(SpecialVersion::Beta)
424
1
        );
425
1
        assert_eq!(
426
1
            RustcVersion::parse("1.0.0-sigma"),
427
1
            Err(Error::NotASpecialVersion)
428
1
        );
429
1
        assert_eq!(
430
1
            RustcVersion::parse("1.0.0beta"),
431
1
            Err(Error::NotASpecialVersion)
432
1
        );
433
1
        assert_eq!(
434
1
            RustcVersion::parse("1.1.0-beta"),
435
1
            Err(Error::NotASpecialVersion)
436
1
        );
437
1
    }
438
439
1
    #[test]
440
1
    fn less_than() {
441
1
        let bigger = RustcVersion::new(1, 30, 1);
442
1
        assert!(RustcVersion::parse("1.0.0").unwrap() < bigger);
443
1
        assert!(RustcVersion::parse("1.0").unwrap() < bigger);
444
1
        assert!(RustcVersion::parse("1").unwrap() < bigger);
445
1
        assert!(RustcVersion::parse("1.30").unwrap() < bigger);
446
1
        assert!(RustcVersion::parse("1.0.0-beta").unwrap() < bigger);
447
1
        assert!(RustcVersion::parse("0.9").unwrap() < RustcVersion::Special(SpecialVersion::Alpha));
448
1
        assert!(
449
1
            RustcVersion::parse("1.0.0-alpha").unwrap()
450
1
                < RustcVersion::Special(SpecialVersion::Alpha2)
451
1
        );
452
1
        assert!(
453
1
            RustcVersion::parse("1.0.0-alpha").unwrap()
454
1
                < RustcVersion::Special(SpecialVersion::Beta)
455
1
        );
456
1
        assert!(
457
1
            RustcVersion::parse("1.0.0-alpha.2").unwrap()
458
1
                < RustcVersion::Special(SpecialVersion::Beta)
459
1
        );
460
1
    }
461
462
1
    #[test]
463
1
    fn equal() {
464
1
        assert_eq!(
465
1
            RustcVersion::parse("1.22.0").unwrap(),
466
1
            RustcVersion::new(1, 22, 0)
467
1
        );
468
1
        assert_eq!(
469
1
            RustcVersion::parse("1.22").unwrap(),
470
1
            RustcVersion::new(1, 22, 0)
471
1
        );
472
1
        assert_eq!(
473
1
            RustcVersion::parse("1.48.1").unwrap(),
474
1
            RustcVersion::new(1, 48, 1)
475
1
        );
476
1
        assert_eq!(
477
1
            RustcVersion::parse("1.0.0-alpha")
478
1
                .unwrap()
479
1
                .cmp(&RustcVersion::Special(SpecialVersion::Alpha)),
480
1
            Ordering::Equal
481
1
        );
482
1
        assert_eq!(
483
1
            RustcVersion::parse("1.0.0-alpha.2")
484
1
                .unwrap()
485
1
                .cmp(&RustcVersion::Special(SpecialVersion::Alpha2)),
486
1
            Ordering::Equal
487
1
        );
488
1
        assert_eq!(
489
1
            RustcVersion::parse("1.0.0-beta")
490
1
                .unwrap()
491
1
                .cmp(&RustcVersion::Special(SpecialVersion::Beta)),
492
1
            Ordering::Equal
493
1
        );
494
1
    }
495
496
1
    #[test]
497
1
    fn greater_than() {
498
1
        let less = RustcVersion::new(1, 15, 1);
499
1
        assert!(RustcVersion::parse("1.16.0").unwrap() > less);
500
1
        assert!(RustcVersion::parse("1.16").unwrap() > less);
501
1
        assert!(RustcVersion::parse("2").unwrap() > less);
502
1
        assert!(RustcVersion::parse("1.15.2").unwrap() > less);
503
1
        assert!(
504
1
            RustcVersion::parse("1.0.0-beta").unwrap()
505
1
                > RustcVersion::Special(SpecialVersion::Alpha2)
506
1
        );
507
1
        assert!(
508
1
            RustcVersion::parse("1.0.0-beta").unwrap()
509
1
                > RustcVersion::Special(SpecialVersion::Alpha)
510
1
        );
511
1
        assert!(
512
1
            RustcVersion::parse("1.0.0-alpha.2").unwrap()
513
1
                > RustcVersion::Special(SpecialVersion::Alpha)
514
1
        );
515
1
        assert!(RustcVersion::parse("1.0.0-alpha.2").unwrap() > RustcVersion::new(0, 8, 0));
516
1
        assert!(
517
1
            RustcVersion::parse("1.45.2").unwrap() > RustcVersion::Special(SpecialVersion::Alpha2)
518
1
        );
519
1
    }
520
521
1
    #[test]
522
1
    fn edge_cases() {
523
1
        assert_eq!(RustcVersion::parse(""), Err(Error::EmptyVersionPart));
524
1
        assert_eq!(RustcVersion::parse(" "), Err(Error::EmptyVersionPart));
525
1
        assert_eq!(RustcVersion::parse("\t"), Err(Error::EmptyVersionPart));
526
1
        assert_eq!(RustcVersion::parse("1."), Err(Error::EmptyVersionPart));
527
1
        assert_eq!(RustcVersion::parse("1. "), Err(Error::EmptyVersionPart));
528
1
        assert_eq!(RustcVersion::parse("1.\t"), Err(Error::EmptyVersionPart));
529
1
        assert_eq!(RustcVersion::parse("1. \t.3"), Err(Error::EmptyVersionPart));
530
1
        assert_eq!(
531
1
            RustcVersion::parse(" 1  . \t 3.\r 5").unwrap(),
532
1
            RustcVersion::new(1, 3, 5)
533
1
        );
534
1
    }
535
536
1
    #[test]
537
1
    fn formatting() {
538
1
        extern crate alloc;
539
1
        use alloc::string::{String, ToString};
540
1
        assert_eq!(
541
1
            RustcVersion::new(1, 42, 28).to_string(),
542
1
            String::from("1.42.28")
543
1
        );
544
1
        assert_eq!(
545
1
            RustcVersion::Special(SpecialVersion::Alpha).to_string(),
546
1
            String::from("1.0.0-alpha")
547
1
        );
548
1
        assert_eq!(
549
1
            RustcVersion::Special(SpecialVersion::Alpha2).to_string(),
550
1
            String::from("1.0.0-alpha.2")
551
1
        );
552
1
        assert_eq!(
553
1
            RustcVersion::Special(SpecialVersion::Beta).to_string(),
554
1
            String::from("1.0.0-beta")
555
1
        );
556
1
    }
557
558
1
    #[test]
559
1
    fn too_many_elements() {
560
1
        assert_eq!(
561
1
            RustcVersion::parse("1.0.0.100"),
562
1
            Err(Error::TooManyElements)
563
1
        );
564
1
    }
565
566
1
    #[test]
567
1
    fn alpha_numeric_version() {
568
1
        assert_eq!(RustcVersion::parse("a.0.1"), Err(Error::ParseIntError));
569
1
        assert_eq!(RustcVersion::parse("2.x.1"), Err(Error::ParseIntError));
570
1
        assert_eq!(RustcVersion::parse("0.2.s"), Err(Error::NotASpecialVersion));
571
1
    }
572
573
1
    #[test]
574
1
    fn meets_full() {
575
1
        // Nothing was omitted
576
1
        assert!(RustcVersion::new(1, 2, 3).meets(RustcVersion::new(1, 2, 3)));
577
1
        assert!(RustcVersion::new(1, 2, 5).meets(RustcVersion::new(1, 2, 3)));
578
1
        assert!(RustcVersion::new(1, 3, 0).meets(RustcVersion::new(1, 2, 3)));
579
1
        assert!(!RustcVersion::new(2, 0, 0).meets(RustcVersion::new(1, 2, 3)));
580
1
        assert!(!RustcVersion::new(0, 9, 0).meets(RustcVersion::new(1, 0, 0)));
581
582
1
        assert!(RustcVersion::new(0, 2, 3).meets(RustcVersion::new(0, 2, 3)));
583
1
        assert!(RustcVersion::new(0, 2, 5).meets(RustcVersion::new(0, 2, 3)));
584
1
        assert!(!RustcVersion::new(0, 3, 0).meets(RustcVersion::new(0, 2, 3)));
585
1
        assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::new(0, 2, 3)));
586
587
1
        assert!(RustcVersion::new(0, 0, 3).meets(RustcVersion::new(0, 0, 3)));
588
1
        assert!(!RustcVersion::new(0, 0, 5).meets(RustcVersion::new(0, 0, 3)));
589
1
        assert!(!RustcVersion::new(0, 1, 0).meets(RustcVersion::new(0, 0, 3)));
590
591
1
        assert!(RustcVersion::new(0, 0, 0).meets(RustcVersion::new(0, 0, 0)));
592
1
        assert!(!RustcVersion::new(0, 0, 1).meets(RustcVersion::new(0, 0, 0)));
593
1
    }
594
595
1
    #[test]
596
1
    fn meets_no_patch() {
597
1
        // Patch was omitted
598
1
        assert!(RustcVersion::new(1, 2, 0).meets(RustcVersion::parse("1.2").unwrap()));
599
1
        assert!(RustcVersion::new(1, 2, 5).meets(RustcVersion::parse("1.2").unwrap()));
600
1
        assert!(RustcVersion::new(1, 3, 0).meets(RustcVersion::parse("1.2").unwrap()));
601
1
        assert!(!RustcVersion::new(2, 0, 0).meets(RustcVersion::parse("1.2").unwrap()));
602
1
        assert!(!RustcVersion::new(0, 9, 0).meets(RustcVersion::parse("1.0").unwrap()));
603
604
1
        assert!(RustcVersion::new(0, 2, 0).meets(RustcVersion::parse("0.2").unwrap()));
605
1
        assert!(RustcVersion::new(0, 2, 5).meets(RustcVersion::parse("0.2").unwrap()));
606
1
        assert!(!RustcVersion::new(0, 3, 0).meets(RustcVersion::parse("0.2").unwrap()));
607
1
        assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::parse("0.2").unwrap()));
608
609
1
        assert!(RustcVersion::new(0, 0, 0).meets(RustcVersion::parse("0.0").unwrap()));
610
1
        assert!(RustcVersion::new(0, 0, 5).meets(RustcVersion::parse("0.0").unwrap()));
611
1
        assert!(!RustcVersion::new(0, 1, 0).meets(RustcVersion::parse("0.0").unwrap()));
612
1
    }
613
614
1
    #[test]
615
1
    fn meets_no_minor() {
616
1
        // Minor was omitted
617
1
        assert!(RustcVersion::new(1, 0, 0).meets(RustcVersion::parse("1").unwrap()));
618
1
        assert!(RustcVersion::new(1, 3, 0).meets(RustcVersion::parse("1").unwrap()));
619
1
        assert!(!RustcVersion::new(2, 0, 0).meets(RustcVersion::parse("1").unwrap()));
620
1
        assert!(!RustcVersion::new(0, 9, 0).meets(RustcVersion::parse("1").unwrap()));
621
622
1
        assert!(RustcVersion::new(0, 0, 0).meets(RustcVersion::parse("0").unwrap()));
623
1
        assert!(RustcVersion::new(0, 0, 1).meets(RustcVersion::parse("0").unwrap()));
624
1
        assert!(RustcVersion::new(0, 2, 5).meets(RustcVersion::parse("0").unwrap()));
625
1
        assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::parse("0").unwrap()));
626
1
    }
627
628
1
    #[test]
629
1
    fn meets_special() {
630
1
        assert!(RustcVersion::Special(SpecialVersion::Alpha)
631
1
            .meets(RustcVersion::Special(SpecialVersion::Alpha)));
632
1
        assert!(RustcVersion::Special(SpecialVersion::Alpha2)
633
1
            .meets(RustcVersion::Special(SpecialVersion::Alpha2)));
634
1
        assert!(RustcVersion::Special(SpecialVersion::Beta)
635
1
            .meets(RustcVersion::Special(SpecialVersion::Beta)));
636
1
        assert!(!RustcVersion::Special(SpecialVersion::Alpha)
637
1
            .meets(RustcVersion::Special(SpecialVersion::Alpha2)));
638
1
        assert!(!RustcVersion::Special(SpecialVersion::Alpha)
639
1
            .meets(RustcVersion::Special(SpecialVersion::Beta)));
640
1
        assert!(!RustcVersion::Special(SpecialVersion::Alpha2)
641
1
            .meets(RustcVersion::Special(SpecialVersion::Beta)));
642
1
        assert!(!RustcVersion::Special(SpecialVersion::Alpha).meets(RustcVersion::new(1, 0, 0)));
643
1
        assert!(!RustcVersion::Special(SpecialVersion::Alpha2).meets(RustcVersion::new(1, 0, 0)));
644
1
        assert!(!RustcVersion::Special(SpecialVersion::Beta).meets(RustcVersion::new(1, 0, 0)));
645
1
        assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::Special(SpecialVersion::Alpha)));
646
1
        assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::Special(SpecialVersion::Alpha2)));
647
1
        assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::Special(SpecialVersion::Beta)));
648
1
    }
649
650
1
    #[test]
651
    #[should_panic(
652
        expected = "This function should never be called with `parts == 0` or `parts > 3`"
653
    )]
654
1
    fn omitted_parts_with_zero() {
655
1
        let _ = OmittedParts::from(0);
656
1
    }
657
658
1
    #[test]
659
    #[should_panic(
660
        expected = "This function should never be called with `parts == 0` or `parts > 3`"
661
    )]
662
1
    fn omitted_parts_with_four() {
663
1
        let _ = OmittedParts::from(4);
664
1
    }
665
}