@@ -109,9 +109,7 @@ impl From<VersionReq> for OptVersionReq {
109
109
}
110
110
}
111
111
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 ) ]
115
113
#[ serde( transparent) ]
116
114
pub struct RustVersion ( PartialVersion ) ;
117
115
@@ -127,7 +125,26 @@ impl std::str::FromStr for RustVersion {
127
125
type Err = anyhow:: Error ;
128
126
129
127
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)
131
148
}
132
149
}
133
150
@@ -142,6 +159,8 @@ pub struct PartialVersion {
142
159
pub major : u64 ,
143
160
pub minor : Option < u64 > ,
144
161
pub patch : Option < u64 > ,
162
+ pub pre : Option < semver:: Prerelease > ,
163
+ pub build : Option < semver:: BuildMetadata > ,
145
164
}
146
165
147
166
impl PartialVersion {
@@ -152,26 +171,31 @@ impl PartialVersion {
152
171
major: self . major,
153
172
minor: self . minor,
154
173
patch: self . patch,
155
- pre: Default :: default ( ) ,
174
+ pre: self . pre . as_ref ( ) . cloned ( ) . unwrap_or_default ( ) ,
156
175
} ] ,
157
176
}
158
177
}
159
178
}
160
179
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,
169
198
}
170
- Ok ( Self {
171
- major : value. major ,
172
- minor : Some ( value. minor ) ,
173
- patch : Some ( value. patch ) ,
174
- } )
175
199
}
176
200
}
177
201
@@ -183,7 +207,7 @@ impl std::str::FromStr for PartialVersion {
183
207
anyhow:: bail!( "unexpected version requirement, expected a version like \" 1.32\" " )
184
208
}
185
209
match semver:: Version :: parse ( value) {
186
- Ok ( ver) => ver. try_into ( ) ,
210
+ Ok ( ver) => Ok ( ver. into ( ) ) ,
187
211
Err ( _) => {
188
212
// HACK: Leverage `VersionReq` for partial version parsing
189
213
let mut version_req = match semver:: VersionReq :: parse ( value) {
@@ -201,15 +225,17 @@ impl std::str::FromStr for PartialVersion {
201
225
assert_eq ! ( version_req. comparators. len( ) , 1 , "guarenteed by is_req" ) ;
202
226
let comp = version_req. comparators . pop ( ) . unwrap ( ) ;
203
227
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
+ } ;
209
233
Ok ( Self {
210
234
major : comp. major ,
211
235
minor : comp. minor ,
212
236
patch : comp. patch ,
237
+ pre,
238
+ build : None ,
213
239
} )
214
240
}
215
241
}
@@ -226,6 +252,12 @@ impl Display for PartialVersion {
226
252
if let Some ( patch) = self . patch {
227
253
write ! ( f, ".{patch}" ) ?;
228
254
}
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
+ }
229
261
Ok ( ( ) )
230
262
}
231
263
}
0 commit comments