1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use alloc::string::ToString;
use core::{fmt, str::FromStr};
pub use semver::{self, VersionReq};
use crate::{
AttrPrinter, derive::DialectAttribute, dialects::builtin::BuiltinDialect, formatter,
print::AsmPrinter,
};
/// Represents a Semantic Versioning version string.
///
/// This is a newtype wrapper around [semver::Version], in order to make it representable as an
/// attribute value in the IR.
#[derive(DialectAttribute, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[attribute(dialect = BuiltinDialect, implements(AttrPrinter))]
pub struct Version(semver::Version);
impl AttrPrinter for VersionAttr {
fn print(&self, printer: &mut AsmPrinter<'_>) {
printer.print_string(self.value.to_string());
}
}
impl Version {
/// Create a new [Version] from the given components, with empty pre-release and build metadata.
pub const fn new(major: u64, minor: u64, patch: u64) -> Self {
Self(semver::Version::new(major, minor, patch))
}
/// Create Version by parsing from string representation.
///
/// # Errors
///
/// Possible reasons for the parse to fail include:
///
/// * `1.0` — too few numeric components. A SemVer version must have exactly three. If you are
/// looking at something that has fewer than three numbers in it, it’s possible it is a
/// [semver::VersionReq] instead (with an implicit default ^ comparison operator).
/// * `1.0.01` — a numeric component has a leading zero.
/// * `1.0.unknown` — unexpected character in one of the components.
/// * `1.0.0- or 1.0.0+` — the pre-release or build metadata are indicated present but empty.
/// * `1.0.0-alpha_123` — pre-release or build metadata have something outside the allowed characters, which are 0-9, A-Z, a-z, -, and . (dot).
/// * `23456789999999999999.0.0` — overflow of a u64.
pub fn parse(version: impl AsRef<str>) -> Result<Self, semver::Error> {
semver::Version::parse(version.as_ref()).map(Self)
}
}
impl Default for Version {
fn default() -> Self {
Self(semver::Version::new(0, 0, 0))
}
}
impl FromStr for Version {
type Err = semver::Error;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::parse(s)
}
}
impl core::ops::Deref for Version {
type Target = semver::Version;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl core::ops::DerefMut for Version {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl fmt::Debug for Version {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl fmt::Display for Version {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl formatter::PrettyPrint for Version {
fn render(&self) -> formatter::Document {
use formatter::*;
display(&self.0)
}
}