1use semver::VersionReq;
4use std::cmp::Ordering;
5use std::fmt::{Display, Formatter};
6
7#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
9pub struct Version {
10 name: String,
11 version: String,
12}
13
14impl Version {
15 fn instance() -> Self {
17 let name = env!("CARGO_PKG_NAME");
18 let version = env!("CARGO_PKG_VERSION");
19 Self {
20 name: name.to_string(),
21 version: version.to_string(),
22 }
23 }
24
25 pub fn new(build: &str, version: &str) -> Self {
27 Self {
28 name: build.to_string(),
29 version: version.to_string(),
30 }
31 }
32
33 pub fn with_version(version: &str) -> Self {
35 Self::new(env!("CARGO_PKG_NAME"), version)
36 }
37
38 pub fn name(&self) -> &str {
40 &self.name
41 }
42
43 pub fn version(&self) -> &str {
45 &self.version
46 }
47
48 pub fn match_requirement(&self, req: &str) -> bool {
50 let req = VersionReq::parse(req)
51 .unwrap_or_else(|_| panic!("Invalid requirement string: {req:?}"));
52 let semver = semver::Version::parse(&self.version)
53 .unwrap_or_else(|_| panic!("Invalid version string: {:?}", self.version));
54 req.matches(&semver)
55 }
56}
57
58impl Display for Version {
59 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
60 write!(f, "v{}", self.version)
61 }
62}
63
64pub fn version() -> Version {
66 Version::instance()
67}
68
69impl PartialOrd for Version {
70 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
71 if self.name != other.name {
72 return None;
73 }
74
75 let this_version = semver::Version::parse(&self.version).ok()?;
76 let other_version = semver::Version::parse(&other.version).ok()?;
77 this_version.partial_cmp(&other_version)
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn get_version_info() {
87 let version = version();
88 assert_eq!(version.name(), "assemble-core");
89 let semver = semver::Version::parse(version.version()).unwrap();
90 let added = semver::Version::new(0, 1, 2);
91 assert!(semver >= added);
92 }
93}