Skip to content

Commit 4676e87

Browse files
committed
refactor(manifest): Shift pre/build validation from PartialVersion to RustVersion
1 parent 67fa43d commit 4676e87

File tree

1 file changed

+56
-24
lines changed

1 file changed

+56
-24
lines changed

src/cargo/util/semver_ext.rs

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,7 @@ impl From<VersionReq> for OptVersionReq {
109109
}
110110
}
111111

112-
#[derive(
113-
PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug, serde::Serialize, serde::Deserialize,
114-
)]
112+
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug, serde::Serialize)]
115113
#[serde(transparent)]
116114
pub struct RustVersion(PartialVersion);
117115

@@ -127,7 +125,26 @@ impl std::str::FromStr for RustVersion {
127125
type Err = anyhow::Error;
128126

129127
fn from_str(value: &str) -> Result<Self, Self::Err> {
130-
value.parse::<PartialVersion>().map(Self)
128+
let partial = value.parse::<PartialVersion>()?;
129+
if partial.pre.is_some() {
130+
anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
131+
}
132+
if partial.build.is_some() {
133+
anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
134+
}
135+
Ok(Self(partial))
136+
}
137+
}
138+
139+
impl<'de> serde::Deserialize<'de> for RustVersion {
140+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
141+
where
142+
D: serde::Deserializer<'de>,
143+
{
144+
UntaggedEnumVisitor::new()
145+
.expecting("SemVer version")
146+
.string(|value| value.parse().map_err(serde::de::Error::custom))
147+
.deserialize(deserializer)
131148
}
132149
}
133150

@@ -142,6 +159,8 @@ pub struct PartialVersion {
142159
pub major: u64,
143160
pub minor: Option<u64>,
144161
pub patch: Option<u64>,
162+
pub pre: Option<semver::Prerelease>,
163+
pub build: Option<semver::BuildMetadata>,
145164
}
146165

147166
impl PartialVersion {
@@ -152,26 +171,31 @@ impl PartialVersion {
152171
major: self.major,
153172
minor: self.minor,
154173
patch: self.patch,
155-
pre: Default::default(),
174+
pre: self.pre.as_ref().cloned().unwrap_or_default(),
156175
}],
157176
}
158177
}
159178
}
160179

161-
impl TryFrom<semver::Version> for PartialVersion {
162-
type Error = anyhow::Error;
163-
fn try_from(value: semver::Version) -> Result<Self, Self::Error> {
164-
if !value.pre.is_empty() {
165-
anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
166-
}
167-
if !value.build.is_empty() {
168-
anyhow::bail!("unexpected build field, expected a version like \"1.32\"")
180+
impl From<semver::Version> for PartialVersion {
181+
fn from(ver: semver::Version) -> Self {
182+
let pre = if ver.pre.is_empty() {
183+
None
184+
} else {
185+
Some(ver.pre)
186+
};
187+
let build = if ver.build.is_empty() {
188+
None
189+
} else {
190+
Some(ver.build)
191+
};
192+
Self {
193+
major: ver.major,
194+
minor: Some(ver.minor),
195+
patch: Some(ver.patch),
196+
pre,
197+
build,
169198
}
170-
Ok(Self {
171-
major: value.major,
172-
minor: Some(value.minor),
173-
patch: Some(value.patch),
174-
})
175199
}
176200
}
177201

@@ -183,7 +207,7 @@ impl std::str::FromStr for PartialVersion {
183207
anyhow::bail!("unexpected version requirement, expected a version like \"1.32\"")
184208
}
185209
match semver::Version::parse(value) {
186-
Ok(ver) => ver.try_into(),
210+
Ok(ver) => Ok(ver.into()),
187211
Err(_) => {
188212
// HACK: Leverage `VersionReq` for partial version parsing
189213
let mut version_req = match semver::VersionReq::parse(value) {
@@ -201,15 +225,17 @@ impl std::str::FromStr for PartialVersion {
201225
assert_eq!(version_req.comparators.len(), 1, "guarenteed by is_req");
202226
let comp = version_req.comparators.pop().unwrap();
203227
assert_eq!(comp.op, semver::Op::Caret, "guarenteed by is_req");
204-
assert_eq!(
205-
comp.pre,
206-
semver::Prerelease::EMPTY,
207-
"guarenteed by `Version::parse` failing"
208-
);
228+
let pre = if comp.pre.is_empty() {
229+
None
230+
} else {
231+
Some(comp.pre)
232+
};
209233
Ok(Self {
210234
major: comp.major,
211235
minor: comp.minor,
212236
patch: comp.patch,
237+
pre,
238+
build: None,
213239
})
214240
}
215241
}
@@ -226,6 +252,12 @@ impl Display for PartialVersion {
226252
if let Some(patch) = self.patch {
227253
write!(f, ".{patch}")?;
228254
}
255+
if let Some(pre) = self.pre.as_ref() {
256+
write!(f, "-{pre}")?;
257+
}
258+
if let Some(build) = self.build.as_ref() {
259+
write!(f, "+{build}")?;
260+
}
229261
Ok(())
230262
}
231263
}

0 commit comments

Comments
 (0)