1- use semver:: { Comparator , Op , Version , VersionReq } ;
2- use serde_untagged:: UntaggedEnumVisitor ;
31use std:: fmt:: { self , Display } ;
42
3+ use semver:: { Op , Version , VersionReq } ;
4+ use serde_untagged:: UntaggedEnumVisitor ;
5+
6+ use crate :: util_semver:: PartialVersion ;
7+ use crate :: util_semver:: VersionExt as _;
8+
59#[ derive( PartialEq , Eq , Hash , Clone , Debug ) ]
610pub enum OptVersionReq {
711 Any ,
@@ -12,30 +16,6 @@ pub enum OptVersionReq {
1216 UpdatePrecise ( Version , VersionReq ) ,
1317}
1418
15- pub trait VersionExt {
16- fn is_prerelease ( & self ) -> bool ;
17-
18- fn to_exact_req ( & self ) -> VersionReq ;
19- }
20-
21- impl VersionExt for Version {
22- fn is_prerelease ( & self ) -> bool {
23- !self . pre . is_empty ( )
24- }
25-
26- fn to_exact_req ( & self ) -> VersionReq {
27- VersionReq {
28- comparators : vec ! [ Comparator {
29- op: Op :: Exact ,
30- major: self . major,
31- minor: Some ( self . minor) ,
32- patch: Some ( self . patch) ,
33- pre: self . pre. clone( ) ,
34- } ] ,
35- }
36- }
37- }
38-
3919impl OptVersionReq {
4020 pub fn exact ( version : & Version ) -> Self {
4121 OptVersionReq :: Req ( version. to_exact_req ( ) )
@@ -190,170 +170,3 @@ impl Display for RustVersion {
190170 self . 0 . fmt ( f)
191171 }
192172}
193-
194- #[ derive( PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Debug ) ]
195- pub struct PartialVersion {
196- pub major : u64 ,
197- pub minor : Option < u64 > ,
198- pub patch : Option < u64 > ,
199- pub pre : Option < semver:: Prerelease > ,
200- pub build : Option < semver:: BuildMetadata > ,
201- }
202-
203- impl PartialVersion {
204- pub fn to_version ( & self ) -> Option < Version > {
205- Some ( Version {
206- major : self . major ,
207- minor : self . minor ?,
208- patch : self . patch ?,
209- pre : self . pre . clone ( ) . unwrap_or_default ( ) ,
210- build : self . build . clone ( ) . unwrap_or_default ( ) ,
211- } )
212- }
213-
214- pub fn to_caret_req ( & self ) -> VersionReq {
215- VersionReq {
216- comparators : vec ! [ Comparator {
217- op: semver:: Op :: Caret ,
218- major: self . major,
219- minor: self . minor,
220- patch: self . patch,
221- pre: self . pre. as_ref( ) . cloned( ) . unwrap_or_default( ) ,
222- } ] ,
223- }
224- }
225-
226- /// Check if this matches a version, including build metadata
227- ///
228- /// Build metadata does not affect version precedence but may be necessary for uniquely
229- /// identifying a package.
230- pub fn matches ( & self , version : & Version ) -> bool {
231- if !version. pre . is_empty ( ) && self . pre . is_none ( ) {
232- // Pre-release versions must be explicitly opted into, if for no other reason than to
233- // give us room to figure out and define the semantics
234- return false ;
235- }
236- self . major == version. major
237- && self . minor . map ( |f| f == version. minor ) . unwrap_or ( true )
238- && self . patch . map ( |f| f == version. patch ) . unwrap_or ( true )
239- && self . pre . as_ref ( ) . map ( |f| f == & version. pre ) . unwrap_or ( true )
240- && self
241- . build
242- . as_ref ( )
243- . map ( |f| f == & version. build )
244- . unwrap_or ( true )
245- }
246- }
247-
248- impl From < semver:: Version > for PartialVersion {
249- fn from ( ver : semver:: Version ) -> Self {
250- let pre = if ver. pre . is_empty ( ) {
251- None
252- } else {
253- Some ( ver. pre )
254- } ;
255- let build = if ver. build . is_empty ( ) {
256- None
257- } else {
258- Some ( ver. build )
259- } ;
260- Self {
261- major : ver. major ,
262- minor : Some ( ver. minor ) ,
263- patch : Some ( ver. patch ) ,
264- pre,
265- build,
266- }
267- }
268- }
269-
270- impl std:: str:: FromStr for PartialVersion {
271- type Err = anyhow:: Error ;
272-
273- fn from_str ( value : & str ) -> Result < Self , Self :: Err > {
274- if is_req ( value) {
275- anyhow:: bail!( "unexpected version requirement, expected a version like \" 1.32\" " )
276- }
277- match semver:: Version :: parse ( value) {
278- Ok ( ver) => Ok ( ver. into ( ) ) ,
279- Err ( _) => {
280- // HACK: Leverage `VersionReq` for partial version parsing
281- let mut version_req = match semver:: VersionReq :: parse ( value) {
282- Ok ( req) => req,
283- Err ( _) if value. contains ( '-' ) => {
284- anyhow:: bail!(
285- "unexpected prerelease field, expected a version like \" 1.32\" "
286- )
287- }
288- Err ( _) if value. contains ( '+' ) => {
289- anyhow:: bail!( "unexpected build field, expected a version like \" 1.32\" " )
290- }
291- Err ( _) => anyhow:: bail!( "expected a version like \" 1.32\" " ) ,
292- } ;
293- assert_eq ! ( version_req. comparators. len( ) , 1 , "guaranteed by is_req" ) ;
294- let comp = version_req. comparators . pop ( ) . unwrap ( ) ;
295- assert_eq ! ( comp. op, semver:: Op :: Caret , "guaranteed by is_req" ) ;
296- let pre = if comp. pre . is_empty ( ) {
297- None
298- } else {
299- Some ( comp. pre )
300- } ;
301- Ok ( Self {
302- major : comp. major ,
303- minor : comp. minor ,
304- patch : comp. patch ,
305- pre,
306- build : None ,
307- } )
308- }
309- }
310- }
311- }
312-
313- impl Display for PartialVersion {
314- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
315- let major = self . major ;
316- write ! ( f, "{major}" ) ?;
317- if let Some ( minor) = self . minor {
318- write ! ( f, ".{minor}" ) ?;
319- }
320- if let Some ( patch) = self . patch {
321- write ! ( f, ".{patch}" ) ?;
322- }
323- if let Some ( pre) = self . pre . as_ref ( ) {
324- write ! ( f, "-{pre}" ) ?;
325- }
326- if let Some ( build) = self . build . as_ref ( ) {
327- write ! ( f, "+{build}" ) ?;
328- }
329- Ok ( ( ) )
330- }
331- }
332-
333- impl serde:: Serialize for PartialVersion {
334- fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
335- where
336- S : serde:: Serializer ,
337- {
338- serializer. collect_str ( self )
339- }
340- }
341-
342- impl < ' de > serde:: Deserialize < ' de > for PartialVersion {
343- fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
344- where
345- D : serde:: Deserializer < ' de > ,
346- {
347- UntaggedEnumVisitor :: new ( )
348- . expecting ( "SemVer version" )
349- . string ( |value| value. parse ( ) . map_err ( serde:: de:: Error :: custom) )
350- . deserialize ( deserializer)
351- }
352- }
353-
354- fn is_req ( value : & str ) -> bool {
355- let Some ( first) = value. chars ( ) . next ( ) else {
356- return false ;
357- } ;
358- "<>=^~" . contains ( first) || value. contains ( '*' ) || value. contains ( ',' )
359- }
0 commit comments