1use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
2use std::fmt::Formatter;
3use std::num::NonZero;
4use std::ops::Deref;
5use std::sync::LazyLock;
6use std::{
7 borrow::Borrow,
8 cmp::Ordering,
9 hash::{Hash, Hasher},
10 str::FromStr,
11 sync::Arc,
12};
13use uv_cache_key::{CacheKey, CacheKeyHasher};
14
15#[derive(Eq, Ord, PartialEq, PartialOrd, Debug, Hash, Clone, Copy)]
17#[cfg_attr(
18 feature = "rkyv",
19 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
20)]
21#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
22pub enum Operator {
23 Equal,
25 EqualStar,
27 ExactEqual,
34 NotEqual,
36 NotEqualStar,
38 TildeEqual,
42 LessThan,
44 LessThanEqual,
46 GreaterThan,
48 GreaterThanEqual,
50}
51
52impl Operator {
53 pub fn negate(self) -> Option<Self> {
67 Some(match self {
68 Self::Equal => Self::NotEqual,
69 Self::EqualStar => Self::NotEqualStar,
70 Self::ExactEqual => Self::NotEqual,
71 Self::NotEqual => Self::Equal,
72 Self::NotEqualStar => Self::EqualStar,
73 Self::TildeEqual => return None,
74 Self::LessThan => Self::GreaterThanEqual,
75 Self::LessThanEqual => Self::GreaterThan,
76 Self::GreaterThan => Self::LessThanEqual,
77 Self::GreaterThanEqual => Self::LessThan,
78 })
79 }
80
81 pub(crate) fn is_local_compatible(self) -> bool {
90 !matches!(
91 self,
92 Self::GreaterThan
93 | Self::GreaterThanEqual
94 | Self::LessThan
95 | Self::LessThanEqual
96 | Self::TildeEqual
97 | Self::EqualStar
98 | Self::NotEqualStar
99 )
100 }
101
102 pub(crate) fn to_star(self) -> Option<Self> {
107 match self {
108 Self::Equal => Some(Self::EqualStar),
109 Self::NotEqual => Some(Self::NotEqualStar),
110 _ => None,
111 }
112 }
113
114 pub fn is_star(self) -> bool {
116 matches!(self, Self::EqualStar | Self::NotEqualStar)
117 }
118
119 pub fn as_str(self) -> &'static str {
121 match self {
122 Self::Equal => "==",
123 Self::EqualStar => "==",
125 #[allow(deprecated)]
126 Self::ExactEqual => "===",
127 Self::NotEqual => "!=",
128 Self::NotEqualStar => "!=",
129 Self::TildeEqual => "~=",
130 Self::LessThan => "<",
131 Self::LessThanEqual => "<=",
132 Self::GreaterThan => ">",
133 Self::GreaterThanEqual => ">=",
134 }
135 }
136}
137
138impl FromStr for Operator {
139 type Err = OperatorParseError;
140
141 fn from_str(s: &str) -> Result<Self, Self::Err> {
143 let operator = match s {
144 "==" => Self::Equal,
145 "===" => {
146 #[cfg(feature = "tracing")]
147 {
148 tracing::warn!("Using arbitrary equality (`===`) is discouraged");
149 }
150 #[allow(deprecated)]
151 Self::ExactEqual
152 }
153 "!=" => Self::NotEqual,
154 "~=" => Self::TildeEqual,
155 "<" => Self::LessThan,
156 "<=" => Self::LessThanEqual,
157 ">" => Self::GreaterThan,
158 ">=" => Self::GreaterThanEqual,
159 other => {
160 return Err(OperatorParseError {
161 got: other.to_string(),
162 });
163 }
164 };
165 Ok(operator)
166 }
167}
168
169impl std::fmt::Display for Operator {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 let operator = self.as_str();
173 write!(f, "{operator}")
174 }
175}
176
177#[derive(Clone, Debug, Eq, PartialEq)]
179pub struct OperatorParseError {
180 pub(crate) got: String,
181}
182
183impl std::error::Error for OperatorParseError {}
184
185impl std::fmt::Display for OperatorParseError {
186 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
187 write!(
188 f,
189 "no such comparison operator {:?}, must be one of ~= == != <= >= < > ===",
190 self.got
191 )
192 }
193}
194
195#[derive(Clone)]
272#[cfg_attr(
273 feature = "rkyv",
274 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
275)]
276#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
277pub struct Version {
278 inner: VersionInner,
279}
280
281#[derive(Clone, Debug)]
282#[cfg_attr(
283 feature = "rkyv",
284 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
285)]
286#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
287enum VersionInner {
288 Small { small: VersionSmall },
289 Full { full: Arc<VersionFull> },
290}
291
292impl Version {
293 #[inline]
300 pub fn new<I, R>(release_numbers: I) -> Self
301 where
302 I: IntoIterator<Item = R>,
303 R: Borrow<u64>,
304 {
305 Self {
306 inner: VersionInner::Small {
307 small: VersionSmall::new(),
308 },
309 }
310 .with_release(release_numbers)
311 }
312
313 #[inline]
315 pub fn any_prerelease(&self) -> bool {
316 self.is_pre() || self.is_dev()
317 }
318
319 #[inline]
321 pub fn is_stable(&self) -> bool {
322 !self.is_pre() && !self.is_dev()
323 }
324
325 #[inline]
327 pub fn is_pre(&self) -> bool {
328 self.pre().is_some()
329 }
330
331 #[inline]
333 pub fn is_dev(&self) -> bool {
334 self.dev().is_some()
335 }
336
337 #[inline]
339 pub fn is_post(&self) -> bool {
340 self.post().is_some()
341 }
342
343 #[inline]
348 pub fn is_local(&self) -> bool {
349 !self.local().is_empty()
350 }
351
352 #[inline]
354 pub fn epoch(&self) -> u64 {
355 match self.inner {
356 VersionInner::Small { ref small } => small.epoch(),
357 VersionInner::Full { ref full } => full.epoch,
358 }
359 }
360
361 #[inline]
363 pub fn release(&self) -> Release<'_> {
364 let inner = match &self.inner {
365 VersionInner::Small { small } => {
366 match small.len {
371 0 => ReleaseInner::Small0([]),
372 1 => ReleaseInner::Small1([(small.repr >> 0o60) & 0xFFFF]),
373 2 => ReleaseInner::Small2([
374 (small.repr >> 0o60) & 0xFFFF,
375 (small.repr >> 0o50) & 0xFF,
376 ]),
377 3 => ReleaseInner::Small3([
378 (small.repr >> 0o60) & 0xFFFF,
379 (small.repr >> 0o50) & 0xFF,
380 (small.repr >> 0o40) & 0xFF,
381 ]),
382 4 => ReleaseInner::Small4([
383 (small.repr >> 0o60) & 0xFFFF,
384 (small.repr >> 0o50) & 0xFF,
385 (small.repr >> 0o40) & 0xFF,
386 (small.repr >> 0o30) & 0xFF,
387 ]),
388 _ => unreachable!("{}", small.len),
389 }
390 }
391 VersionInner::Full { full } => ReleaseInner::Full(&full.release),
392 };
393
394 Release { inner }
395 }
396
397 #[inline]
399 pub fn pre(&self) -> Option<Prerelease> {
400 match self.inner {
401 VersionInner::Small { ref small } => small.pre(),
402 VersionInner::Full { ref full } => full.pre,
403 }
404 }
405
406 #[inline]
408 pub fn post(&self) -> Option<u64> {
409 match self.inner {
410 VersionInner::Small { ref small } => small.post(),
411 VersionInner::Full { ref full } => full.post,
412 }
413 }
414
415 #[inline]
417 pub fn dev(&self) -> Option<u64> {
418 match self.inner {
419 VersionInner::Small { ref small } => small.dev(),
420 VersionInner::Full { ref full } => full.dev,
421 }
422 }
423
424 #[inline]
426 pub fn local(&self) -> LocalVersionSlice<'_> {
427 match self.inner {
428 VersionInner::Small { ref small } => small.local_slice(),
429 VersionInner::Full { ref full } => full.local.as_slice(),
430 }
431 }
432
433 #[inline]
439 pub fn min(&self) -> Option<u64> {
440 match self.inner {
441 VersionInner::Small { ref small } => small.min(),
442 VersionInner::Full { ref full } => full.min,
443 }
444 }
445
446 #[inline]
452 pub fn max(&self) -> Option<u64> {
453 match self.inner {
454 VersionInner::Small { ref small } => small.max(),
455 VersionInner::Full { ref full } => full.max,
456 }
457 }
458
459 #[inline]
470 #[must_use]
471 pub fn with_release<I, R>(mut self, release_numbers: I) -> Self
472 where
473 I: IntoIterator<Item = R>,
474 R: Borrow<u64>,
475 {
476 self.clear_release();
477 for n in release_numbers {
478 self.push_release(*n.borrow());
479 }
480 assert!(
481 !self.release().is_empty(),
482 "release must have non-zero size"
483 );
484 self
485 }
486
487 #[inline]
490 fn push_release(&mut self, n: u64) {
491 if let VersionInner::Small { small } = &mut self.inner {
492 if small.push_release(n) {
493 return;
494 }
495 }
496 self.make_full().release.push(n);
497 }
498
499 #[inline]
504 fn clear_release(&mut self) {
505 match &mut self.inner {
506 VersionInner::Small { small } => small.clear_release(),
507 VersionInner::Full { full } => {
508 Arc::make_mut(full).release.clear();
509 }
510 }
511 }
512
513 #[inline]
515 #[must_use]
516 pub fn with_epoch(mut self, value: u64) -> Self {
517 if let VersionInner::Small { small } = &mut self.inner {
518 if small.set_epoch(value) {
519 return self;
520 }
521 }
522 self.make_full().epoch = value;
523 self
524 }
525
526 #[inline]
528 #[must_use]
529 pub fn with_pre(mut self, value: Option<Prerelease>) -> Self {
530 if let VersionInner::Small { small } = &mut self.inner {
531 if small.set_pre(value) {
532 return self;
533 }
534 }
535 self.make_full().pre = value;
536 self
537 }
538
539 #[inline]
541 #[must_use]
542 pub fn with_post(mut self, value: Option<u64>) -> Self {
543 if let VersionInner::Small { small } = &mut self.inner {
544 if small.set_post(value) {
545 return self;
546 }
547 }
548 self.make_full().post = value;
549 self
550 }
551
552 #[inline]
554 #[must_use]
555 pub fn with_dev(mut self, value: Option<u64>) -> Self {
556 if let VersionInner::Small { small } = &mut self.inner {
557 if small.set_dev(value) {
558 return self;
559 }
560 }
561 self.make_full().dev = value;
562 self
563 }
564
565 #[inline]
567 #[must_use]
568 pub fn with_local_segments(mut self, value: Vec<LocalSegment>) -> Self {
569 if value.is_empty() {
570 self.without_local()
571 } else {
572 self.make_full().local = LocalVersion::Segments(value);
573 self
574 }
575 }
576
577 #[inline]
579 #[must_use]
580 pub fn with_local(mut self, value: LocalVersion) -> Self {
581 match value {
582 LocalVersion::Segments(segments) => self.with_local_segments(segments),
583 LocalVersion::Max => {
584 if let VersionInner::Small { small } = &mut self.inner {
585 if small.set_local(LocalVersion::Max) {
586 return self;
587 }
588 }
589 self.make_full().local = value;
590 self
591 }
592 }
593 }
594
595 #[inline]
600 #[must_use]
601 pub fn without_local(mut self) -> Self {
602 if let VersionInner::Small { small } = &mut self.inner {
603 if small.set_local(LocalVersion::empty()) {
604 return self;
605 }
606 }
607 self.make_full().local = LocalVersion::empty();
608 self
609 }
610
611 #[inline]
613 #[must_use]
614 pub fn only_release(&self) -> Self {
615 Self::new(self.release().iter().copied())
616 }
617
618 #[inline]
620 #[must_use]
621 pub fn only_minor_release(&self) -> Self {
622 Self::new(self.release().iter().take(2).copied())
623 }
624
625 #[inline]
628 #[must_use]
629 pub fn only_release_trimmed(&self) -> Self {
630 if let Some(last_non_zero) = self.release().iter().rposition(|segment| *segment != 0) {
631 if last_non_zero + 1 == self.release().len()
632 && self.epoch() == 0
633 && self.pre().is_none()
634 && self.post().is_none()
635 && self.dev().is_none()
636 && self.local().is_empty()
637 && self.min().is_none()
638 && self.max().is_none()
639 {
640 self.clone()
642 } else {
643 Self::new(self.release().iter().take(last_non_zero + 1).copied())
644 }
645 } else {
646 Self::new([0])
648 }
649 }
650
651 #[inline]
657 #[must_use]
658 pub fn without_trailing_zeros(self) -> Self {
659 let mut release = self.release().to_vec();
660 while let Some(0) = release.last() {
661 release.pop();
662 }
663 self.with_release(release)
664 }
665
666 pub fn bump(&mut self, bump: BumpCommand) {
668 let full = self.make_full();
685
686 match bump {
687 BumpCommand::BumpRelease { index, value } => {
688 full.pre = None;
690 full.post = None;
691 full.dev = None;
692
693 let old_parts = &full.release;
695 let len = old_parts.len().max(index + 1);
696 let new_release_vec = (0..len)
697 .map(|i| match i.cmp(&index) {
698 Ordering::Less => old_parts.get(i).copied().unwrap_or(0),
700 Ordering::Equal => {
702 value.unwrap_or_else(|| old_parts.get(i).copied().unwrap_or(0) + 1)
703 }
704 Ordering::Greater => 0,
706 })
707 .collect::<Vec<u64>>();
708 full.release = new_release_vec;
709 }
710 BumpCommand::MakeStable => {
711 full.pre = None;
713 full.post = None;
714 full.dev = None;
715 }
716 BumpCommand::BumpPrerelease { kind, value } => {
717 full.post = None;
719 full.dev = None;
720 if let Some(value) = value {
721 full.pre = Some(Prerelease {
722 kind,
723 number: value,
724 });
725 } else {
726 if let Some(prerelease) = &mut full.pre {
728 if prerelease.kind == kind {
729 prerelease.number += 1;
730 return;
731 }
732 }
733 full.pre = Some(Prerelease { kind, number: 1 });
734 }
735 }
736 BumpCommand::BumpPost { value } => {
737 full.dev = None;
739 if let Some(value) = value {
740 full.post = Some(value);
741 } else {
742 if let Some(post) = &mut full.post {
744 *post += 1;
745 } else {
746 full.post = Some(1);
747 }
748 }
749 }
750 BumpCommand::BumpDev { value } => {
751 if let Some(value) = value {
752 full.dev = Some(value);
753 } else {
754 if let Some(dev) = &mut full.dev {
756 *dev += 1;
757 } else {
758 full.dev = Some(1);
759 }
760 }
761 }
762 }
763 }
764
765 #[inline]
771 #[must_use]
772 pub fn with_min(mut self, value: Option<u64>) -> Self {
773 debug_assert!(!self.is_pre(), "min is not allowed on pre-release versions");
774 debug_assert!(!self.is_dev(), "min is not allowed on dev versions");
775 if let VersionInner::Small { small } = &mut self.inner {
776 if small.set_min(value) {
777 return self;
778 }
779 }
780 self.make_full().min = value;
781 self
782 }
783
784 #[inline]
790 #[must_use]
791 pub fn with_max(mut self, value: Option<u64>) -> Self {
792 debug_assert!(
793 !self.is_post(),
794 "max is not allowed on post-release versions"
795 );
796 debug_assert!(!self.is_dev(), "max is not allowed on dev versions");
797 if let VersionInner::Small { small } = &mut self.inner {
798 if small.set_max(value) {
799 return self;
800 }
801 }
802 self.make_full().max = value;
803 self
804 }
805
806 fn make_full(&mut self) -> &mut VersionFull {
809 if let VersionInner::Small { ref small } = self.inner {
810 let full = VersionFull {
811 epoch: small.epoch(),
812 release: self.release().to_vec(),
813 min: small.min(),
814 max: small.max(),
815 pre: small.pre(),
816 post: small.post(),
817 dev: small.dev(),
818 local: small.local(),
819 };
820 *self = Self {
821 inner: VersionInner::Full {
822 full: Arc::new(full),
823 },
824 };
825 }
826 match &mut self.inner {
827 VersionInner::Full { full } => Arc::make_mut(full),
828 VersionInner::Small { .. } => unreachable!(),
829 }
830 }
831
832 #[cold]
839 #[inline(never)]
840 fn cmp_slow(&self, other: &Self) -> Ordering {
841 match self.epoch().cmp(&other.epoch()) {
842 Ordering::Less => {
843 return Ordering::Less;
844 }
845 Ordering::Equal => {}
846 Ordering::Greater => {
847 return Ordering::Greater;
848 }
849 }
850
851 match compare_release(&self.release(), &other.release()) {
852 Ordering::Less => {
853 return Ordering::Less;
854 }
855 Ordering::Equal => {}
856 Ordering::Greater => {
857 return Ordering::Greater;
858 }
859 }
860
861 sortable_tuple(self).cmp(&sortable_tuple(other))
863 }
864}
865
866impl<'de> Deserialize<'de> for Version {
867 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
868 where
869 D: Deserializer<'de>,
870 {
871 struct Visitor;
872
873 impl de::Visitor<'_> for Visitor {
874 type Value = Version;
875
876 fn expecting(&self, f: &mut Formatter) -> std::fmt::Result {
877 f.write_str("a string")
878 }
879
880 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
881 Version::from_str(v).map_err(de::Error::custom)
882 }
883 }
884
885 deserializer.deserialize_str(Visitor)
886 }
887}
888
889impl Serialize for Version {
891 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
892 where
893 S: Serializer,
894 {
895 serializer.collect_str(self)
896 }
897}
898
899impl std::fmt::Display for Version {
901 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
902 if self.epoch() != 0 {
903 write!(f, "{}!", self.epoch())?;
904 }
905 let release = self.release();
906 let mut release_iter = release.iter();
907 if let Some(first) = release_iter.next() {
908 write!(f, "{first}")?;
909 for n in release_iter {
910 write!(f, ".{n}")?;
911 }
912 }
913
914 if let Some(Prerelease { kind, number }) = self.pre() {
915 write!(f, "{kind}{number}")?;
916 }
917 if let Some(post) = self.post() {
918 write!(f, ".post{post}")?;
919 }
920 if let Some(dev) = self.dev() {
921 write!(f, ".dev{dev}")?;
922 }
923 if !self.local().is_empty() {
924 match self.local() {
925 LocalVersionSlice::Segments(_) => {
926 write!(f, "+{}", self.local())?;
927 }
928 LocalVersionSlice::Max => {
929 write!(f, "+")?;
930 }
931 }
932 }
933 Ok(())
934 }
935}
936
937impl std::fmt::Debug for Version {
938 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
939 write!(f, "\"{self}\"")
940 }
941}
942
943impl PartialEq<Self> for Version {
944 #[inline]
945 fn eq(&self, other: &Self) -> bool {
946 self.cmp(other) == Ordering::Equal
947 }
948}
949
950impl Eq for Version {}
951
952impl Hash for Version {
953 #[inline]
955 fn hash<H: Hasher>(&self, state: &mut H) {
956 self.epoch().hash(state);
957 for i in self.release().iter().rev().skip_while(|x| **x == 0) {
959 i.hash(state);
960 }
961 self.pre().hash(state);
962 self.dev().hash(state);
963 self.post().hash(state);
964 self.local().hash(state);
965 }
966}
967
968impl CacheKey for Version {
969 fn cache_key(&self, state: &mut CacheKeyHasher) {
970 self.epoch().cache_key(state);
971
972 let release = self.release();
973 release.len().cache_key(state);
974 for segment in release.iter() {
975 segment.cache_key(state);
976 }
977
978 if let Some(pre) = self.pre() {
979 1u8.cache_key(state);
980 match pre.kind {
981 PrereleaseKind::Alpha => 0u8.cache_key(state),
982 PrereleaseKind::Beta => 1u8.cache_key(state),
983 PrereleaseKind::Rc => 2u8.cache_key(state),
984 }
985 pre.number.cache_key(state);
986 } else {
987 0u8.cache_key(state);
988 }
989
990 if let Some(post) = self.post() {
991 1u8.cache_key(state);
992 post.cache_key(state);
993 } else {
994 0u8.cache_key(state);
995 }
996
997 if let Some(dev) = self.dev() {
998 1u8.cache_key(state);
999 dev.cache_key(state);
1000 } else {
1001 0u8.cache_key(state);
1002 }
1003
1004 self.local().cache_key(state);
1005 }
1006}
1007
1008impl PartialOrd<Self> for Version {
1009 #[inline]
1010 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1011 Some(self.cmp(other))
1012 }
1013}
1014
1015impl Ord for Version {
1016 #[inline]
1020 fn cmp(&self, other: &Self) -> Ordering {
1021 match (&self.inner, &other.inner) {
1022 (VersionInner::Small { small: small1 }, VersionInner::Small { small: small2 }) => {
1023 small1.repr.cmp(&small2.repr)
1024 }
1025 _ => self.cmp_slow(other),
1026 }
1027 }
1028}
1029
1030impl FromStr for Version {
1031 type Err = VersionParseError;
1032
1033 fn from_str(version: &str) -> Result<Self, Self::Err> {
1037 Parser::new(version.as_bytes()).parse()
1038 }
1039}
1040
1041#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1043pub enum BumpCommand {
1044 BumpRelease {
1046 index: usize,
1048 value: Option<u64>,
1050 },
1051 BumpPrerelease {
1053 kind: PrereleaseKind,
1055 value: Option<u64>,
1057 },
1058 MakeStable,
1060 BumpPost {
1062 value: Option<u64>,
1064 },
1065 BumpDev {
1067 value: Option<u64>,
1069 },
1070}
1071
1072#[derive(Clone, Debug)]
1147#[cfg_attr(
1148 feature = "rkyv",
1149 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
1150)]
1151#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
1152struct VersionSmall {
1153 len: u8,
1158 repr: u64,
1160 _force_niche: NonZero<u8>,
1162}
1163
1164impl VersionSmall {
1165 const SUFFIX_MIN: u64 = 0;
1180 const SUFFIX_DEV: u64 = 1;
1181 const SUFFIX_PRE_ALPHA: u64 = 2;
1182 const SUFFIX_PRE_BETA: u64 = 3;
1183 const SUFFIX_PRE_RC: u64 = 4;
1184 const SUFFIX_NONE: u64 = 5;
1185 const SUFFIX_LOCAL: u64 = 6;
1186 const SUFFIX_POST: u64 = 7;
1187 const SUFFIX_MAX: u64 = 8;
1188
1189 const SUFFIX_RELEASE_MASK: u64 = 0xFFFF_FFFF_FF00_0000;
1195 const SUFFIX_VERSION_MASK: u64 = 0x000F_FFFF;
1197 const SUFFIX_VERSION_BIT_LEN: u64 = 20;
1201 const SUFFIX_KIND_MASK: u64 = 0b1111;
1206
1207 #[inline]
1208 fn new() -> Self {
1209 Self {
1210 _force_niche: NonZero::<u8>::MIN,
1211 repr: Self::SUFFIX_NONE << Self::SUFFIX_VERSION_BIT_LEN,
1212 len: 0,
1213 }
1214 }
1215
1216 #[inline]
1217 #[expect(clippy::unused_self)]
1218 fn epoch(&self) -> u64 {
1219 0
1220 }
1221
1222 #[inline]
1223 #[expect(clippy::unused_self)]
1224 fn set_epoch(&mut self, value: u64) -> bool {
1225 if value != 0 {
1226 return false;
1227 }
1228 true
1229 }
1230
1231 #[inline]
1232 fn clear_release(&mut self) {
1233 self.repr &= !Self::SUFFIX_RELEASE_MASK;
1234 self.len = 0;
1235 }
1236
1237 #[inline]
1238 fn push_release(&mut self, n: u64) -> bool {
1239 if self.len == 0 {
1240 if n > u64::from(u16::MAX) {
1241 return false;
1242 }
1243 self.repr |= n << 48;
1244 self.len = 1;
1245 true
1246 } else {
1247 if n > u64::from(u8::MAX) {
1248 return false;
1249 }
1250 if self.len >= 4 {
1251 return false;
1252 }
1253 let shift = 48 - (usize::from(self.len) * 8);
1254 self.repr |= n << shift;
1255 self.len += 1;
1256 true
1257 }
1258 }
1259
1260 #[inline]
1261 fn post(&self) -> Option<u64> {
1262 if self.suffix_kind() == Self::SUFFIX_POST {
1263 Some(self.suffix_version())
1264 } else {
1265 None
1266 }
1267 }
1268
1269 #[inline]
1270 fn set_post(&mut self, value: Option<u64>) -> bool {
1271 let suffix_kind = self.suffix_kind();
1272 if !(suffix_kind == Self::SUFFIX_NONE || suffix_kind == Self::SUFFIX_POST) {
1273 return value.is_none();
1274 }
1275 match value {
1276 None => {
1277 self.set_suffix_kind(Self::SUFFIX_NONE);
1278 }
1279 Some(number) => {
1280 if number > Self::SUFFIX_VERSION_MASK {
1281 return false;
1282 }
1283 self.set_suffix_kind(Self::SUFFIX_POST);
1284 self.set_suffix_version(number);
1285 }
1286 }
1287 true
1288 }
1289
1290 #[inline]
1291 fn pre(&self) -> Option<Prerelease> {
1292 let (kind, number) = (self.suffix_kind(), self.suffix_version());
1293 if kind == Self::SUFFIX_PRE_ALPHA {
1294 Some(Prerelease {
1295 kind: PrereleaseKind::Alpha,
1296 number,
1297 })
1298 } else if kind == Self::SUFFIX_PRE_BETA {
1299 Some(Prerelease {
1300 kind: PrereleaseKind::Beta,
1301 number,
1302 })
1303 } else if kind == Self::SUFFIX_PRE_RC {
1304 Some(Prerelease {
1305 kind: PrereleaseKind::Rc,
1306 number,
1307 })
1308 } else {
1309 None
1310 }
1311 }
1312
1313 #[inline]
1314 fn set_pre(&mut self, value: Option<Prerelease>) -> bool {
1315 let suffix_kind = self.suffix_kind();
1316 if !(suffix_kind == Self::SUFFIX_NONE
1317 || suffix_kind == Self::SUFFIX_PRE_ALPHA
1318 || suffix_kind == Self::SUFFIX_PRE_BETA
1319 || suffix_kind == Self::SUFFIX_PRE_RC)
1320 {
1321 return value.is_none();
1322 }
1323 match value {
1324 None => {
1325 self.set_suffix_kind(Self::SUFFIX_NONE);
1326 }
1327 Some(Prerelease { kind, number }) => {
1328 if number > Self::SUFFIX_VERSION_MASK {
1329 return false;
1330 }
1331 match kind {
1332 PrereleaseKind::Alpha => {
1333 self.set_suffix_kind(Self::SUFFIX_PRE_ALPHA);
1334 }
1335 PrereleaseKind::Beta => {
1336 self.set_suffix_kind(Self::SUFFIX_PRE_BETA);
1337 }
1338 PrereleaseKind::Rc => {
1339 self.set_suffix_kind(Self::SUFFIX_PRE_RC);
1340 }
1341 }
1342 self.set_suffix_version(number);
1343 }
1344 }
1345 true
1346 }
1347
1348 #[inline]
1349 fn dev(&self) -> Option<u64> {
1350 if self.suffix_kind() == Self::SUFFIX_DEV {
1351 Some(self.suffix_version())
1352 } else {
1353 None
1354 }
1355 }
1356
1357 #[inline]
1358 fn set_dev(&mut self, value: Option<u64>) -> bool {
1359 let suffix_kind = self.suffix_kind();
1360 if !(suffix_kind == Self::SUFFIX_NONE || suffix_kind == Self::SUFFIX_DEV) {
1361 return value.is_none();
1362 }
1363 match value {
1364 None => {
1365 self.set_suffix_kind(Self::SUFFIX_NONE);
1366 }
1367 Some(number) => {
1368 if number > Self::SUFFIX_VERSION_MASK {
1369 return false;
1370 }
1371 self.set_suffix_kind(Self::SUFFIX_DEV);
1372 self.set_suffix_version(number);
1373 }
1374 }
1375 true
1376 }
1377
1378 #[inline]
1379 fn min(&self) -> Option<u64> {
1380 if self.suffix_kind() == Self::SUFFIX_MIN {
1381 Some(self.suffix_version())
1382 } else {
1383 None
1384 }
1385 }
1386
1387 #[inline]
1388 fn set_min(&mut self, value: Option<u64>) -> bool {
1389 let suffix_kind = self.suffix_kind();
1390 if !(suffix_kind == Self::SUFFIX_NONE || suffix_kind == Self::SUFFIX_MIN) {
1391 return value.is_none();
1392 }
1393 match value {
1394 None => {
1395 self.set_suffix_kind(Self::SUFFIX_NONE);
1396 }
1397 Some(number) => {
1398 if number > Self::SUFFIX_VERSION_MASK {
1399 return false;
1400 }
1401 self.set_suffix_kind(Self::SUFFIX_MIN);
1402 self.set_suffix_version(number);
1403 }
1404 }
1405 true
1406 }
1407
1408 #[inline]
1409 fn max(&self) -> Option<u64> {
1410 if self.suffix_kind() == Self::SUFFIX_MAX {
1411 Some(self.suffix_version())
1412 } else {
1413 None
1414 }
1415 }
1416
1417 #[inline]
1418 fn set_max(&mut self, value: Option<u64>) -> bool {
1419 let suffix_kind = self.suffix_kind();
1420 if !(suffix_kind == Self::SUFFIX_NONE || suffix_kind == Self::SUFFIX_MAX) {
1421 return value.is_none();
1422 }
1423 match value {
1424 None => {
1425 self.set_suffix_kind(Self::SUFFIX_NONE);
1426 }
1427 Some(number) => {
1428 if number > Self::SUFFIX_VERSION_MASK {
1429 return false;
1430 }
1431 self.set_suffix_kind(Self::SUFFIX_MAX);
1432 self.set_suffix_version(number);
1433 }
1434 }
1435 true
1436 }
1437
1438 #[inline]
1439 fn local(&self) -> LocalVersion {
1440 if self.suffix_kind() == Self::SUFFIX_LOCAL {
1441 LocalVersion::Max
1442 } else {
1443 LocalVersion::empty()
1444 }
1445 }
1446
1447 #[inline]
1448 fn local_slice(&self) -> LocalVersionSlice<'_> {
1449 if self.suffix_kind() == Self::SUFFIX_LOCAL {
1450 LocalVersionSlice::Max
1451 } else {
1452 LocalVersionSlice::empty()
1453 }
1454 }
1455
1456 #[inline]
1457 fn set_local(&mut self, value: LocalVersion) -> bool {
1458 let suffix_kind = self.suffix_kind();
1459 if !(suffix_kind == Self::SUFFIX_NONE || suffix_kind == Self::SUFFIX_LOCAL) {
1460 return value.is_empty();
1461 }
1462 match value {
1463 LocalVersion::Max => {
1464 self.set_suffix_kind(Self::SUFFIX_LOCAL);
1465 true
1466 }
1467 LocalVersion::Segments(segments) if segments.is_empty() => {
1468 self.set_suffix_kind(Self::SUFFIX_NONE);
1469 true
1470 }
1471 LocalVersion::Segments(_) => false,
1472 }
1473 }
1474
1475 #[inline]
1476 fn suffix_kind(&self) -> u64 {
1477 let kind = (self.repr >> Self::SUFFIX_VERSION_BIT_LEN) & Self::SUFFIX_KIND_MASK;
1478 debug_assert!(kind <= Self::SUFFIX_MAX);
1479 kind
1480 }
1481
1482 #[inline]
1483 fn set_suffix_kind(&mut self, kind: u64) {
1484 debug_assert!(kind <= Self::SUFFIX_MAX);
1485 self.repr &= !(Self::SUFFIX_KIND_MASK << Self::SUFFIX_VERSION_BIT_LEN);
1486 self.repr |= kind << Self::SUFFIX_VERSION_BIT_LEN;
1487 if kind == Self::SUFFIX_NONE || kind == Self::SUFFIX_LOCAL {
1488 self.set_suffix_version(0);
1489 }
1490 }
1491
1492 #[inline]
1493 fn suffix_version(&self) -> u64 {
1494 self.repr & Self::SUFFIX_VERSION_MASK
1495 }
1496
1497 #[inline]
1498 fn set_suffix_version(&mut self, value: u64) {
1499 debug_assert!(value <= Self::SUFFIX_VERSION_MASK);
1500 self.repr &= !Self::SUFFIX_VERSION_MASK;
1501 self.repr |= value;
1502 }
1503}
1504
1505#[derive(Clone, Debug)]
1514#[cfg_attr(
1515 feature = "rkyv",
1516 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
1517)]
1518#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
1519struct VersionFull {
1520 epoch: u64,
1525 release: Vec<u64>,
1531 pre: Option<Prerelease>,
1537 post: Option<u64>,
1541 dev: Option<u64>,
1545 local: LocalVersion,
1558 min: Option<u64>,
1562 max: Option<u64>,
1566}
1567
1568#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1587pub struct VersionPattern {
1588 version: Version,
1589 wildcard: bool,
1590}
1591
1592impl VersionPattern {
1593 #[inline]
1596 pub fn verbatim(version: Version) -> Self {
1597 Self {
1598 version,
1599 wildcard: false,
1600 }
1601 }
1602
1603 #[inline]
1606 pub fn wildcard(version: Version) -> Self {
1607 Self {
1608 version,
1609 wildcard: true,
1610 }
1611 }
1612
1613 #[inline]
1615 pub fn version(&self) -> &Version {
1616 &self.version
1617 }
1618
1619 #[inline]
1621 pub fn into_version(self) -> Version {
1622 self.version
1623 }
1624
1625 #[inline]
1627 pub fn is_wildcard(&self) -> bool {
1628 self.wildcard
1629 }
1630}
1631
1632impl FromStr for VersionPattern {
1633 type Err = VersionPatternParseError;
1634
1635 fn from_str(version: &str) -> Result<Self, VersionPatternParseError> {
1636 Parser::new(version.as_bytes()).parse_pattern()
1637 }
1638}
1639
1640pub struct Release<'a> {
1645 inner: ReleaseInner<'a>,
1646}
1647
1648enum ReleaseInner<'a> {
1649 Small0([u64; 0]),
1653 Small1([u64; 1]),
1654 Small2([u64; 2]),
1655 Small3([u64; 3]),
1656 Small4([u64; 4]),
1657 Full(&'a [u64]),
1658}
1659
1660impl Deref for Release<'_> {
1661 type Target = [u64];
1662
1663 fn deref(&self) -> &Self::Target {
1664 match &self.inner {
1665 ReleaseInner::Small0(v) => v,
1666 ReleaseInner::Small1(v) => v,
1667 ReleaseInner::Small2(v) => v,
1668 ReleaseInner::Small3(v) => v,
1669 ReleaseInner::Small4(v) => v,
1670 ReleaseInner::Full(v) => v,
1671 }
1672 }
1673}
1674
1675#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy, Ord, PartialOrd)]
1677#[cfg_attr(
1678 feature = "rkyv",
1679 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
1680)]
1681#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
1682pub struct Prerelease {
1683 pub kind: PrereleaseKind,
1685 pub number: u64,
1687}
1688
1689#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy, Ord, PartialOrd)]
1693#[cfg_attr(
1694 feature = "rkyv",
1695 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
1696)]
1697#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
1698pub enum PrereleaseKind {
1699 Alpha,
1701 Beta,
1703 Rc,
1705}
1706
1707impl std::fmt::Display for PrereleaseKind {
1708 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1709 match self {
1710 Self::Alpha => write!(f, "a"),
1711 Self::Beta => write!(f, "b"),
1712 Self::Rc => write!(f, "rc"),
1713 }
1714 }
1715}
1716
1717impl std::fmt::Display for Prerelease {
1718 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1719 write!(f, "{}{}", self.kind, self.number)
1720 }
1721}
1722
1723#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1726#[cfg_attr(
1727 feature = "rkyv",
1728 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
1729)]
1730#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
1731pub enum LocalVersion {
1732 Segments(Vec<LocalSegment>),
1734 Max,
1736}
1737
1738#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1740pub enum LocalVersionSlice<'a> {
1741 Segments(&'a [LocalSegment]),
1743 Max,
1745}
1746
1747impl LocalVersion {
1748 pub fn empty() -> Self {
1750 Self::Segments(Vec::new())
1751 }
1752
1753 pub fn is_empty(&self) -> bool {
1755 match self {
1756 Self::Segments(segments) => segments.is_empty(),
1757 Self::Max => false,
1758 }
1759 }
1760
1761 pub fn as_slice(&self) -> LocalVersionSlice<'_> {
1763 match self {
1764 Self::Segments(segments) => LocalVersionSlice::Segments(segments),
1765 Self::Max => LocalVersionSlice::Max,
1766 }
1767 }
1768
1769 pub fn clear(&mut self) {
1771 match self {
1772 Self::Segments(segments) => segments.clear(),
1773 Self::Max => *self = Self::Segments(Vec::new()),
1774 }
1775 }
1776}
1777
1778impl std::fmt::Display for LocalVersionSlice<'_> {
1783 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1784 match self {
1785 Self::Segments(segments) => {
1786 for (i, segment) in segments.iter().enumerate() {
1787 if i > 0 {
1788 write!(f, ".")?;
1789 }
1790 write!(f, "{segment}")?;
1791 }
1792 Ok(())
1793 }
1794 Self::Max => write!(f, "[max]"),
1795 }
1796 }
1797}
1798
1799impl CacheKey for LocalVersionSlice<'_> {
1800 fn cache_key(&self, state: &mut CacheKeyHasher) {
1801 match self {
1802 Self::Segments(segments) => {
1803 0u8.cache_key(state);
1804 segments.len().cache_key(state);
1805 for segment in *segments {
1806 segment.cache_key(state);
1807 }
1808 }
1809 Self::Max => {
1810 1u8.cache_key(state);
1811 }
1812 }
1813 }
1814}
1815
1816impl PartialOrd for LocalVersionSlice<'_> {
1817 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1818 Some(self.cmp(other))
1819 }
1820}
1821
1822impl Ord for LocalVersionSlice<'_> {
1823 fn cmp(&self, other: &Self) -> Ordering {
1824 match (self, other) {
1825 (LocalVersionSlice::Segments(lv1), LocalVersionSlice::Segments(lv2)) => lv1.cmp(lv2),
1826 (LocalVersionSlice::Segments(_), LocalVersionSlice::Max) => Ordering::Less,
1827 (LocalVersionSlice::Max, LocalVersionSlice::Segments(_)) => Ordering::Greater,
1828 (LocalVersionSlice::Max, LocalVersionSlice::Max) => Ordering::Equal,
1829 }
1830 }
1831}
1832
1833impl LocalVersionSlice<'_> {
1834 pub const fn empty() -> Self {
1836 Self::Segments(&[])
1837 }
1838
1839 pub fn is_empty(&self) -> bool {
1841 matches!(self, &Self::Segments(&[]))
1842 }
1843}
1844
1845#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1861#[cfg_attr(
1862 feature = "rkyv",
1863 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
1864)]
1865#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
1866pub enum LocalSegment {
1867 String(String),
1869 Number(u64),
1871}
1872
1873impl std::fmt::Display for LocalSegment {
1874 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1875 match self {
1876 Self::String(string) => write!(f, "{string}"),
1877 Self::Number(number) => write!(f, "{number}"),
1878 }
1879 }
1880}
1881
1882impl CacheKey for LocalSegment {
1883 fn cache_key(&self, state: &mut CacheKeyHasher) {
1884 match self {
1885 Self::String(string) => {
1886 0u8.cache_key(state);
1887 string.cache_key(state);
1888 }
1889 Self::Number(number) => {
1890 1u8.cache_key(state);
1891 number.cache_key(state);
1892 }
1893 }
1894 }
1895}
1896
1897impl PartialOrd for LocalSegment {
1898 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1899 Some(self.cmp(other))
1900 }
1901}
1902
1903impl Ord for LocalSegment {
1904 fn cmp(&self, other: &Self) -> Ordering {
1905 match (self, other) {
1907 (Self::Number(n1), Self::Number(n2)) => n1.cmp(n2),
1908 (Self::String(s1), Self::String(s2)) => s1.cmp(s2),
1909 (Self::Number(_), Self::String(_)) => Ordering::Greater,
1910 (Self::String(_), Self::Number(_)) => Ordering::Less,
1911 }
1912 }
1913}
1914
1915#[derive(Debug)]
1925struct Parser<'a> {
1926 v: &'a [u8],
1928 i: usize,
1930 epoch: u64,
1932 release: ReleaseNumbers,
1934 pre: Option<Prerelease>,
1936 post: Option<u64>,
1938 dev: Option<u64>,
1940 local: Vec<LocalSegment>,
1942 wildcard: bool,
1946}
1947
1948impl<'a> Parser<'a> {
1949 #[expect(clippy::byte_char_slices)]
1952 const SEPARATOR: ByteSet = ByteSet::new(&[b'.', b'_', b'-']);
1953
1954 fn new(version: &'a [u8]) -> Self {
1956 Parser {
1957 v: version,
1958 i: 0,
1959 epoch: 0,
1960 release: ReleaseNumbers::new(),
1961 pre: None,
1962 post: None,
1963 dev: None,
1964 local: vec![],
1965 wildcard: false,
1966 }
1967 }
1968
1969 fn parse(self) -> Result<Version, VersionParseError> {
1973 match self.parse_pattern() {
1974 Ok(vpat) => {
1975 if vpat.is_wildcard() {
1976 Err(ErrorKind::Wildcard.into())
1977 } else {
1978 Ok(vpat.into_version())
1979 }
1980 }
1981 Err(err) => match *err.kind {
1988 PatternErrorKind::Version(err) => Err(err),
1989 PatternErrorKind::WildcardNotTrailing => Err(ErrorKind::Wildcard.into()),
1990 },
1991 }
1992 }
1993
1994 fn parse_pattern(mut self) -> Result<VersionPattern, VersionPatternParseError> {
1996 if let Some(vpat) = self.parse_fast() {
1997 return Ok(vpat);
1998 }
1999 self.bump_while(|byte| byte.is_ascii_whitespace());
2000 self.bump_if("v");
2001 self.parse_epoch_and_initial_release()?;
2002 self.parse_rest_of_release()?;
2003 if self.parse_wildcard()? {
2004 return Ok(self.into_pattern());
2005 }
2006 self.parse_pre()?;
2007 self.parse_post()?;
2008 self.parse_dev()?;
2009 self.parse_local()?;
2010 self.bump_while(|byte| byte.is_ascii_whitespace());
2011 if !self.is_done() {
2012 let version = String::from_utf8_lossy(&self.v[..self.i]).into_owned();
2013 let remaining = String::from_utf8_lossy(&self.v[self.i..]).into_owned();
2014 return Err(ErrorKind::UnexpectedEnd { version, remaining }.into());
2015 }
2016 Ok(self.into_pattern())
2017 }
2018
2019 fn parse_fast(&self) -> Option<VersionPattern> {
2029 let (mut prev_digit, mut cur, mut release, mut len) = (false, 0u8, [0u8; 4], 0u8);
2030 for &byte in self.v {
2031 if byte == b'.' {
2032 if !prev_digit {
2033 return None;
2034 }
2035 prev_digit = false;
2036 *release.get_mut(usize::from(len))? = cur;
2037 len += 1;
2038 cur = 0;
2039 } else {
2040 let digit = byte.checked_sub(b'0')?;
2041 if digit > 9 {
2042 return None;
2043 }
2044 prev_digit = true;
2045 cur = cur.checked_mul(10)?.checked_add(digit)?;
2046 }
2047 }
2048 if !prev_digit {
2049 return None;
2050 }
2051 *release.get_mut(usize::from(len))? = cur;
2052 len += 1;
2053 let small = VersionSmall {
2054 _force_niche: NonZero::<u8>::MIN,
2055 repr: (u64::from(release[0]) << 48)
2056 | (u64::from(release[1]) << 40)
2057 | (u64::from(release[2]) << 32)
2058 | (u64::from(release[3]) << 24)
2059 | (VersionSmall::SUFFIX_NONE << VersionSmall::SUFFIX_VERSION_BIT_LEN),
2060
2061 len,
2062 };
2063 let inner = VersionInner::Small { small };
2064 let version = Version { inner };
2065 Some(VersionPattern {
2066 version,
2067 wildcard: false,
2068 })
2069 }
2070
2071 fn parse_epoch_and_initial_release(&mut self) -> Result<(), VersionPatternParseError> {
2082 let first_number = self.parse_number()?.ok_or(ErrorKind::NoLeadingNumber)?;
2083 let first_release_number = if self.bump_if("!") {
2084 self.epoch = first_number;
2085 self.parse_number()?
2086 .ok_or(ErrorKind::NoLeadingReleaseNumber)?
2087 } else {
2088 first_number
2089 };
2090 self.release.push(first_release_number);
2091 Ok(())
2092 }
2093
2094 fn parse_rest_of_release(&mut self) -> Result<(), VersionPatternParseError> {
2105 while self.bump_if(".") {
2106 let Some(n) = self.parse_number()? else {
2107 self.unbump();
2108 break;
2109 };
2110 self.release.push(n);
2111 }
2112 Ok(())
2113 }
2114
2115 fn parse_wildcard(&mut self) -> Result<bool, VersionPatternParseError> {
2124 if !self.bump_if(".*") {
2125 return Ok(false);
2126 }
2127 if !self.is_done() {
2128 return Err(PatternErrorKind::WildcardNotTrailing.into());
2129 }
2130 self.wildcard = true;
2131 Ok(true)
2132 }
2133
2134 fn parse_pre(&mut self) -> Result<(), VersionPatternParseError> {
2140 const SPELLINGS: StringSet =
2149 StringSet::new(&["alpha", "beta", "preview", "pre", "rc", "a", "b", "c"]);
2150 const MAP: &[PrereleaseKind] = &[
2151 PrereleaseKind::Alpha,
2152 PrereleaseKind::Beta,
2153 PrereleaseKind::Rc,
2154 PrereleaseKind::Rc,
2155 PrereleaseKind::Rc,
2156 PrereleaseKind::Alpha,
2157 PrereleaseKind::Beta,
2158 PrereleaseKind::Rc,
2159 ];
2160
2161 let oldpos = self.i;
2162 self.bump_if_byte_set(&Parser::SEPARATOR);
2163 let Some(spelling) = self.bump_if_string_set(&SPELLINGS) else {
2164 self.reset(oldpos);
2169 return Ok(());
2170 };
2171 let kind = MAP[spelling];
2172 self.bump_if_byte_set(&Parser::SEPARATOR);
2173 let number = self.parse_number()?.unwrap_or(0);
2176 self.pre = Some(Prerelease { kind, number });
2177 Ok(())
2178 }
2179
2180 fn parse_post(&mut self) -> Result<(), VersionPatternParseError> {
2186 const SPELLINGS: StringSet = StringSet::new(&["post", "rev", "r"]);
2187
2188 let oldpos = self.i;
2189 if self.bump_if("-") {
2190 if let Some(n) = self.parse_number()? {
2191 self.post = Some(n);
2192 return Ok(());
2193 }
2194 self.reset(oldpos);
2195 }
2196 self.bump_if_byte_set(&Parser::SEPARATOR);
2197 if self.bump_if_string_set(&SPELLINGS).is_none() {
2198 self.reset(oldpos);
2202 return Ok(());
2203 }
2204 self.bump_if_byte_set(&Parser::SEPARATOR);
2205 self.post = Some(self.parse_number()?.unwrap_or(0));
2208 Ok(())
2209 }
2210
2211 fn parse_dev(&mut self) -> Result<(), VersionPatternParseError> {
2217 let oldpos = self.i;
2218 self.bump_if_byte_set(&Parser::SEPARATOR);
2219 if !self.bump_if("dev") {
2220 self.reset(oldpos);
2224 return Ok(());
2225 }
2226 self.bump_if_byte_set(&Parser::SEPARATOR);
2227 self.dev = Some(self.parse_number()?.unwrap_or(0));
2230 Ok(())
2231 }
2232
2233 fn parse_local(&mut self) -> Result<(), VersionPatternParseError> {
2241 if !self.bump_if("+") {
2242 return Ok(());
2243 }
2244 let mut precursor = '+';
2245 loop {
2246 let first = self.bump_while(|byte| byte.is_ascii_alphanumeric());
2247 if first.is_empty() {
2248 return Err(ErrorKind::LocalEmpty { precursor }.into());
2249 }
2250 self.local.push(if let Ok(number) = parse_u64(first) {
2251 LocalSegment::Number(number)
2252 } else {
2253 let string = String::from_utf8(first.to_ascii_lowercase())
2254 .expect("ASCII alphanumerics are always valid UTF-8");
2255 LocalSegment::String(string)
2256 });
2257 let Some(byte) = self.bump_if_byte_set(&Parser::SEPARATOR) else {
2258 break;
2259 };
2260 precursor = char::from(byte);
2261 }
2262 Ok(())
2263 }
2264
2265 fn parse_number(&mut self) -> Result<Option<u64>, VersionPatternParseError> {
2273 let digits = self.bump_while(|ch| ch.is_ascii_digit());
2274 if digits.is_empty() {
2275 return Ok(None);
2276 }
2277 let n = parse_u64(digits)?;
2278 if n == u64::MAX {
2284 return Err(ErrorKind::NumberTooBig {
2285 bytes: digits.to_vec(),
2286 }
2287 .into());
2288 }
2289 Ok(Some(n))
2290 }
2291
2292 fn into_pattern(self) -> VersionPattern {
2300 assert!(
2301 self.release.len() > 0,
2302 "version with no release numbers is invalid"
2303 );
2304 let version = Version::new(self.release.as_slice())
2305 .with_epoch(self.epoch)
2306 .with_pre(self.pre)
2307 .with_post(self.post)
2308 .with_dev(self.dev)
2309 .with_local(LocalVersion::Segments(self.local));
2310 VersionPattern {
2311 version,
2312 wildcard: self.wildcard,
2313 }
2314 }
2315
2316 fn bump_while(&mut self, mut predicate: impl FnMut(u8) -> bool) -> &'a [u8] {
2323 let start = self.i;
2324 while !self.is_done() && predicate(self.byte()) {
2325 self.i = self.i.saturating_add(1);
2326 }
2327 &self.v[start..self.i]
2328 }
2329
2330 fn bump_if(&mut self, string: &str) -> bool {
2335 if self.is_done() {
2336 return false;
2337 }
2338 if starts_with_ignore_ascii_case(string.as_bytes(), &self.v[self.i..]) {
2339 self.i = self
2340 .i
2341 .checked_add(string.len())
2342 .expect("valid offset because of prefix");
2343 true
2344 } else {
2345 false
2346 }
2347 }
2348
2349 fn bump_if_string_set(&mut self, set: &StringSet) -> Option<usize> {
2353 let index = set.starts_with(&self.v[self.i..])?;
2354 let found = &set.strings[index];
2355 self.i = self
2356 .i
2357 .checked_add(found.len())
2358 .expect("valid offset because of prefix");
2359 Some(index)
2360 }
2361
2362 fn bump_if_byte_set(&mut self, set: &ByteSet) -> Option<u8> {
2366 let found = set.starts_with(&self.v[self.i..])?;
2367 self.i = self
2368 .i
2369 .checked_add(1)
2370 .expect("valid offset because of prefix");
2371 Some(found)
2372 }
2373
2374 fn unbump(&mut self) {
2383 self.i = self.i.checked_sub(1).expect("not at beginning of input");
2384 }
2385
2386 fn reset(&mut self, offset: usize) {
2392 assert!(offset <= self.v.len());
2393 self.i = offset;
2394 }
2395
2396 fn byte(&self) -> u8 {
2402 self.v[self.i]
2403 }
2404
2405 fn is_done(&self) -> bool {
2407 self.i >= self.v.len()
2408 }
2409}
2410
2411#[derive(Debug)]
2415enum ReleaseNumbers {
2416 Inline { numbers: [u64; 4], len: usize },
2417 Vec(Vec<u64>),
2418}
2419
2420impl ReleaseNumbers {
2421 fn new() -> Self {
2423 Self::Inline {
2424 numbers: [0; 4],
2425 len: 0,
2426 }
2427 }
2428
2429 fn push(&mut self, n: u64) {
2432 match *self {
2433 Self::Inline {
2434 ref mut numbers,
2435 ref mut len,
2436 } => {
2437 assert!(*len <= 4);
2438 if *len == 4 {
2439 let mut numbers = numbers.to_vec();
2440 numbers.push(n);
2441 *self = Self::Vec(numbers.clone());
2442 } else {
2443 numbers[*len] = n;
2444 *len += 1;
2445 }
2446 }
2447 Self::Vec(ref mut numbers) => {
2448 numbers.push(n);
2449 }
2450 }
2451 }
2452
2453 fn len(&self) -> usize {
2455 self.as_slice().len()
2456 }
2457
2458 fn as_slice(&self) -> &[u64] {
2460 match self {
2461 Self::Inline { numbers, len } => &numbers[..*len],
2462 Self::Vec(vec) => vec,
2463 }
2464 }
2465}
2466
2467struct StringSet {
2472 first_byte: ByteSet,
2476 strings: &'static [&'static str],
2478}
2479
2480impl StringSet {
2481 const fn new(strings: &'static [&'static str]) -> Self {
2487 assert!(
2488 strings.len() <= 20,
2489 "only a small number of strings are supported"
2490 );
2491 let (mut firsts, mut firsts_len) = ([0u8; 20], 0);
2492 let mut i = 0;
2493 while i < strings.len() {
2494 assert!(
2495 !strings[i].is_empty(),
2496 "every string in set should be non-empty",
2497 );
2498 firsts[firsts_len] = strings[i].as_bytes()[0];
2499 firsts_len += 1;
2500 i += 1;
2501 }
2502 let first_byte = ByteSet::new(&firsts);
2503 Self {
2504 first_byte,
2505 strings,
2506 }
2507 }
2508
2509 fn starts_with(&self, haystack: &[u8]) -> Option<usize> {
2512 let first_byte = self.first_byte.starts_with(haystack)?;
2513 for (i, &string) in self.strings.iter().enumerate() {
2514 let bytes = string.as_bytes();
2515 if bytes[0].eq_ignore_ascii_case(&first_byte)
2516 && starts_with_ignore_ascii_case(bytes, haystack)
2517 {
2518 return Some(i);
2519 }
2520 }
2521 None
2522 }
2523}
2524
2525struct ByteSet {
2527 set: [bool; 256],
2528}
2529
2530impl ByteSet {
2531 const fn new(bytes: &[u8]) -> Self {
2533 let mut set = [false; 256];
2534 let mut i = 0;
2535 while i < bytes.len() {
2536 set[bytes[i].to_ascii_uppercase() as usize] = true;
2537 set[bytes[i].to_ascii_lowercase() as usize] = true;
2538 i += 1;
2539 }
2540 Self { set }
2541 }
2542
2543 fn starts_with(&self, haystack: &[u8]) -> Option<u8> {
2546 let byte = *haystack.first()?;
2547 if self.contains(byte) {
2548 Some(byte)
2549 } else {
2550 None
2551 }
2552 }
2553
2554 fn contains(&self, byte: u8) -> bool {
2556 self.set[usize::from(byte)]
2557 }
2558}
2559
2560impl std::fmt::Debug for ByteSet {
2561 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2562 let mut set = f.debug_set();
2563 for byte in 0..=255 {
2564 if self.contains(byte) {
2565 set.entry(&char::from(byte));
2566 }
2567 }
2568 set.finish()
2569 }
2570}
2571
2572#[derive(Clone, Debug, Eq, PartialEq)]
2574pub struct VersionParseError {
2575 kind: Box<ErrorKind>,
2576}
2577
2578impl std::error::Error for VersionParseError {}
2579
2580impl std::fmt::Display for VersionParseError {
2581 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2582 match *self.kind {
2583 ErrorKind::Wildcard => write!(f, "wildcards are not allowed in a version"),
2584 ErrorKind::InvalidDigit { got } if got.is_ascii() => {
2585 write!(f, "expected ASCII digit, but found {:?}", char::from(got))
2586 }
2587 ErrorKind::InvalidDigit { got } => {
2588 write!(
2589 f,
2590 "expected ASCII digit, but found non-ASCII byte \\x{got:02X}"
2591 )
2592 }
2593 ErrorKind::NumberTooBig { ref bytes } => {
2594 let string = match std::str::from_utf8(bytes) {
2595 Ok(v) => v,
2596 Err(err) => {
2597 std::str::from_utf8(&bytes[..err.valid_up_to()]).expect("valid UTF-8")
2598 }
2599 };
2600 write!(
2601 f,
2602 "expected number less than or equal to {}, \
2603 but number found in {string:?} exceeds it",
2604 u64::MAX - 1,
2605 )
2606 }
2607 ErrorKind::NoLeadingNumber => {
2608 write!(
2609 f,
2610 "expected version to start with a number, \
2611 but no leading ASCII digits were found"
2612 )
2613 }
2614 ErrorKind::NoLeadingReleaseNumber => {
2615 write!(
2616 f,
2617 "expected version to have a non-empty release component after an epoch, \
2618 but no ASCII digits after the epoch were found"
2619 )
2620 }
2621 ErrorKind::LocalEmpty { precursor } => {
2622 write!(
2623 f,
2624 "found a `{precursor}` indicating the start of a local \
2625 component in a version, but did not find any alphanumeric \
2626 ASCII segment following the `{precursor}`",
2627 )
2628 }
2629 ErrorKind::UnexpectedEnd {
2630 ref version,
2631 ref remaining,
2632 } => {
2633 write!(
2634 f,
2635 "after parsing `{version}`, found `{remaining}`, \
2636 which is not part of a valid version",
2637 )
2638 }
2639 }
2640 }
2641}
2642
2643#[derive(Clone, Debug, Eq, PartialEq)]
2645pub(crate) enum ErrorKind {
2646 Wildcard,
2649 InvalidDigit {
2651 got: u8,
2653 },
2654 NumberTooBig {
2656 bytes: Vec<u8>,
2659 },
2660 NoLeadingNumber,
2662 NoLeadingReleaseNumber,
2664 LocalEmpty {
2668 precursor: char,
2671 },
2672 UnexpectedEnd {
2675 version: String,
2677 remaining: String,
2679 },
2680}
2681
2682impl From<ErrorKind> for VersionParseError {
2683 fn from(kind: ErrorKind) -> Self {
2684 Self {
2685 kind: Box::new(kind),
2686 }
2687 }
2688}
2689
2690#[derive(Clone, Debug, Eq, PartialEq)]
2692pub struct VersionPatternParseError {
2693 kind: Box<PatternErrorKind>,
2694}
2695
2696impl std::error::Error for VersionPatternParseError {}
2697
2698impl std::fmt::Display for VersionPatternParseError {
2699 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2700 match *self.kind {
2701 PatternErrorKind::Version(ref err) => err.fmt(f),
2702 PatternErrorKind::WildcardNotTrailing => {
2703 write!(f, "wildcards in versions must be at the end")
2704 }
2705 }
2706 }
2707}
2708
2709#[derive(Clone, Debug, Eq, PartialEq)]
2711pub(crate) enum PatternErrorKind {
2712 Version(VersionParseError),
2713 WildcardNotTrailing,
2714}
2715
2716impl From<PatternErrorKind> for VersionPatternParseError {
2717 fn from(kind: PatternErrorKind) -> Self {
2718 Self {
2719 kind: Box::new(kind),
2720 }
2721 }
2722}
2723
2724impl From<ErrorKind> for VersionPatternParseError {
2725 fn from(kind: ErrorKind) -> Self {
2726 Self::from(VersionParseError::from(kind))
2727 }
2728}
2729
2730impl From<VersionParseError> for VersionPatternParseError {
2731 fn from(err: VersionParseError) -> Self {
2732 Self {
2733 kind: Box::new(PatternErrorKind::Version(err)),
2734 }
2735 }
2736}
2737
2738pub(crate) fn compare_release(this: &[u64], other: &[u64]) -> Ordering {
2741 if this.len() == other.len() {
2742 return this.cmp(other);
2743 }
2744 for (this, other) in this.iter().chain(std::iter::repeat(&0)).zip(
2747 other
2748 .iter()
2749 .chain(std::iter::repeat(&0))
2750 .take(this.len().max(other.len())),
2751 ) {
2752 match this.cmp(other) {
2753 Ordering::Less => {
2754 return Ordering::Less;
2755 }
2756 Ordering::Equal => {}
2757 Ordering::Greater => {
2758 return Ordering::Greater;
2759 }
2760 }
2761 }
2762 Ordering::Equal
2763}
2764
2765fn sortable_tuple(version: &Version) -> (u64, u64, Option<u64>, u64, LocalVersionSlice<'_>) {
2781 let post = if version.max().is_some() {
2783 Some(u64::MAX)
2784 } else {
2785 version.post()
2786 };
2787 match (version.pre(), post, version.dev(), version.min()) {
2788 (_pre, post, _dev, Some(n)) => (0, 0, post, n, version.local()),
2790 (None, None, Some(n), None) => (1, 0, None, n, version.local()),
2792 (
2794 Some(Prerelease {
2795 kind: PrereleaseKind::Alpha,
2796 number: n,
2797 }),
2798 post,
2799 dev,
2800 None,
2801 ) => (2, n, post, dev.unwrap_or(u64::MAX), version.local()),
2802 (
2804 Some(Prerelease {
2805 kind: PrereleaseKind::Beta,
2806 number: n,
2807 }),
2808 post,
2809 dev,
2810 None,
2811 ) => (3, n, post, dev.unwrap_or(u64::MAX), version.local()),
2812 (
2814 Some(Prerelease {
2815 kind: PrereleaseKind::Rc,
2816 number: n,
2817 }),
2818 post,
2819 dev,
2820 None,
2821 ) => (4, n, post, dev.unwrap_or(u64::MAX), version.local()),
2822 (None, None, None, None) => (5, 0, None, 0, version.local()),
2824 (None, Some(post), dev, None) => {
2826 (6, 0, Some(post), dev.unwrap_or(u64::MAX), version.local())
2827 }
2828 }
2829}
2830
2831fn starts_with_ignore_ascii_case(needle: &[u8], haystack: &[u8]) -> bool {
2834 needle.len() <= haystack.len()
2835 && std::iter::zip(needle, haystack).all(|(b1, b2)| b1.eq_ignore_ascii_case(b2))
2836}
2837
2838fn parse_u64(bytes: &[u8]) -> Result<u64, VersionParseError> {
2853 let mut n: u64 = 0;
2854 for &byte in bytes {
2855 let digit = match byte.checked_sub(b'0') {
2856 None => return Err(ErrorKind::InvalidDigit { got: byte }.into()),
2857 Some(digit) if digit > 9 => return Err(ErrorKind::InvalidDigit { got: byte }.into()),
2858 Some(digit) => {
2859 debug_assert!((0..=9).contains(&digit));
2860 u64::from(digit)
2861 }
2862 };
2863 n = n
2864 .checked_mul(10)
2865 .and_then(|n| n.checked_add(digit))
2866 .ok_or_else(|| ErrorKind::NumberTooBig {
2867 bytes: bytes.to_vec(),
2868 })?;
2869 }
2870 Ok(n)
2871}
2872
2873pub static MIN_VERSION: LazyLock<Version> =
2875 LazyLock::new(|| Version::from_str("0a0.dev0").unwrap());
2876
2877#[cfg(test)]
2878mod tests {
2879 use std::str::FromStr;
2880
2881 use crate::VersionSpecifier;
2882
2883 use super::*;
2884
2885 #[test]
2887 fn test_packaging_versions() {
2888 let versions = [
2889 ("1.0.dev456", Version::new([1, 0]).with_dev(Some(456))),
2891 (
2892 "1.0a1",
2893 Version::new([1, 0]).with_pre(Some(Prerelease {
2894 kind: PrereleaseKind::Alpha,
2895 number: 1,
2896 })),
2897 ),
2898 (
2899 "1.0a2.dev456",
2900 Version::new([1, 0])
2901 .with_pre(Some(Prerelease {
2902 kind: PrereleaseKind::Alpha,
2903 number: 2,
2904 }))
2905 .with_dev(Some(456)),
2906 ),
2907 (
2908 "1.0a12.dev456",
2909 Version::new([1, 0])
2910 .with_pre(Some(Prerelease {
2911 kind: PrereleaseKind::Alpha,
2912 number: 12,
2913 }))
2914 .with_dev(Some(456)),
2915 ),
2916 (
2917 "1.0a12",
2918 Version::new([1, 0]).with_pre(Some(Prerelease {
2919 kind: PrereleaseKind::Alpha,
2920 number: 12,
2921 })),
2922 ),
2923 (
2924 "1.0b1.dev456",
2925 Version::new([1, 0])
2926 .with_pre(Some(Prerelease {
2927 kind: PrereleaseKind::Beta,
2928 number: 1,
2929 }))
2930 .with_dev(Some(456)),
2931 ),
2932 (
2933 "1.0b2",
2934 Version::new([1, 0]).with_pre(Some(Prerelease {
2935 kind: PrereleaseKind::Beta,
2936 number: 2,
2937 })),
2938 ),
2939 (
2940 "1.0b2.post345.dev456",
2941 Version::new([1, 0])
2942 .with_pre(Some(Prerelease {
2943 kind: PrereleaseKind::Beta,
2944 number: 2,
2945 }))
2946 .with_dev(Some(456))
2947 .with_post(Some(345)),
2948 ),
2949 (
2950 "1.0b2.post345",
2951 Version::new([1, 0])
2952 .with_pre(Some(Prerelease {
2953 kind: PrereleaseKind::Beta,
2954 number: 2,
2955 }))
2956 .with_post(Some(345)),
2957 ),
2958 (
2959 "1.0b2-346",
2960 Version::new([1, 0])
2961 .with_pre(Some(Prerelease {
2962 kind: PrereleaseKind::Beta,
2963 number: 2,
2964 }))
2965 .with_post(Some(346)),
2966 ),
2967 (
2968 "1.0c1.dev456",
2969 Version::new([1, 0])
2970 .with_pre(Some(Prerelease {
2971 kind: PrereleaseKind::Rc,
2972 number: 1,
2973 }))
2974 .with_dev(Some(456)),
2975 ),
2976 (
2977 "1.0c1",
2978 Version::new([1, 0]).with_pre(Some(Prerelease {
2979 kind: PrereleaseKind::Rc,
2980 number: 1,
2981 })),
2982 ),
2983 (
2984 "1.0rc2",
2985 Version::new([1, 0]).with_pre(Some(Prerelease {
2986 kind: PrereleaseKind::Rc,
2987 number: 2,
2988 })),
2989 ),
2990 (
2991 "1.0c3",
2992 Version::new([1, 0]).with_pre(Some(Prerelease {
2993 kind: PrereleaseKind::Rc,
2994 number: 3,
2995 })),
2996 ),
2997 ("1.0", Version::new([1, 0])),
2998 (
2999 "1.0.post456.dev34",
3000 Version::new([1, 0]).with_post(Some(456)).with_dev(Some(34)),
3001 ),
3002 ("1.0.post456", Version::new([1, 0]).with_post(Some(456))),
3003 ("1.1.dev1", Version::new([1, 1]).with_dev(Some(1))),
3004 (
3005 "1.2+123abc",
3006 Version::new([1, 2])
3007 .with_local_segments(vec![LocalSegment::String("123abc".to_string())]),
3008 ),
3009 (
3010 "1.2+123abc456",
3011 Version::new([1, 2])
3012 .with_local_segments(vec![LocalSegment::String("123abc456".to_string())]),
3013 ),
3014 (
3015 "1.2+abc",
3016 Version::new([1, 2])
3017 .with_local_segments(vec![LocalSegment::String("abc".to_string())]),
3018 ),
3019 (
3020 "1.2+abc123",
3021 Version::new([1, 2])
3022 .with_local_segments(vec![LocalSegment::String("abc123".to_string())]),
3023 ),
3024 (
3025 "1.2+abc123def",
3026 Version::new([1, 2])
3027 .with_local_segments(vec![LocalSegment::String("abc123def".to_string())]),
3028 ),
3029 (
3030 "1.2+1234.abc",
3031 Version::new([1, 2]).with_local_segments(vec![
3032 LocalSegment::Number(1234),
3033 LocalSegment::String("abc".to_string()),
3034 ]),
3035 ),
3036 (
3037 "1.2+123456",
3038 Version::new([1, 2]).with_local_segments(vec![LocalSegment::Number(123_456)]),
3039 ),
3040 (
3041 "1.2.r32+123456",
3042 Version::new([1, 2])
3043 .with_post(Some(32))
3044 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3045 ),
3046 (
3047 "1.2.rev33+123456",
3048 Version::new([1, 2])
3049 .with_post(Some(33))
3050 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3051 ),
3052 (
3054 "1!1.0.dev456",
3055 Version::new([1, 0]).with_epoch(1).with_dev(Some(456)),
3056 ),
3057 (
3058 "1!1.0a1",
3059 Version::new([1, 0])
3060 .with_epoch(1)
3061 .with_pre(Some(Prerelease {
3062 kind: PrereleaseKind::Alpha,
3063 number: 1,
3064 })),
3065 ),
3066 (
3067 "1!1.0a2.dev456",
3068 Version::new([1, 0])
3069 .with_epoch(1)
3070 .with_pre(Some(Prerelease {
3071 kind: PrereleaseKind::Alpha,
3072 number: 2,
3073 }))
3074 .with_dev(Some(456)),
3075 ),
3076 (
3077 "1!1.0a12.dev456",
3078 Version::new([1, 0])
3079 .with_epoch(1)
3080 .with_pre(Some(Prerelease {
3081 kind: PrereleaseKind::Alpha,
3082 number: 12,
3083 }))
3084 .with_dev(Some(456)),
3085 ),
3086 (
3087 "1!1.0a12",
3088 Version::new([1, 0])
3089 .with_epoch(1)
3090 .with_pre(Some(Prerelease {
3091 kind: PrereleaseKind::Alpha,
3092 number: 12,
3093 })),
3094 ),
3095 (
3096 "1!1.0b1.dev456",
3097 Version::new([1, 0])
3098 .with_epoch(1)
3099 .with_pre(Some(Prerelease {
3100 kind: PrereleaseKind::Beta,
3101 number: 1,
3102 }))
3103 .with_dev(Some(456)),
3104 ),
3105 (
3106 "1!1.0b2",
3107 Version::new([1, 0])
3108 .with_epoch(1)
3109 .with_pre(Some(Prerelease {
3110 kind: PrereleaseKind::Beta,
3111 number: 2,
3112 })),
3113 ),
3114 (
3115 "1!1.0b2.post345.dev456",
3116 Version::new([1, 0])
3117 .with_epoch(1)
3118 .with_pre(Some(Prerelease {
3119 kind: PrereleaseKind::Beta,
3120 number: 2,
3121 }))
3122 .with_post(Some(345))
3123 .with_dev(Some(456)),
3124 ),
3125 (
3126 "1!1.0b2.post345",
3127 Version::new([1, 0])
3128 .with_epoch(1)
3129 .with_pre(Some(Prerelease {
3130 kind: PrereleaseKind::Beta,
3131 number: 2,
3132 }))
3133 .with_post(Some(345)),
3134 ),
3135 (
3136 "1!1.0b2-346",
3137 Version::new([1, 0])
3138 .with_epoch(1)
3139 .with_pre(Some(Prerelease {
3140 kind: PrereleaseKind::Beta,
3141 number: 2,
3142 }))
3143 .with_post(Some(346)),
3144 ),
3145 (
3146 "1!1.0c1.dev456",
3147 Version::new([1, 0])
3148 .with_epoch(1)
3149 .with_pre(Some(Prerelease {
3150 kind: PrereleaseKind::Rc,
3151 number: 1,
3152 }))
3153 .with_dev(Some(456)),
3154 ),
3155 (
3156 "1!1.0c1",
3157 Version::new([1, 0])
3158 .with_epoch(1)
3159 .with_pre(Some(Prerelease {
3160 kind: PrereleaseKind::Rc,
3161 number: 1,
3162 })),
3163 ),
3164 (
3165 "1!1.0rc2",
3166 Version::new([1, 0])
3167 .with_epoch(1)
3168 .with_pre(Some(Prerelease {
3169 kind: PrereleaseKind::Rc,
3170 number: 2,
3171 })),
3172 ),
3173 (
3174 "1!1.0c3",
3175 Version::new([1, 0])
3176 .with_epoch(1)
3177 .with_pre(Some(Prerelease {
3178 kind: PrereleaseKind::Rc,
3179 number: 3,
3180 })),
3181 ),
3182 ("1!1.0", Version::new([1, 0]).with_epoch(1)),
3183 (
3184 "1!1.0.post456.dev34",
3185 Version::new([1, 0])
3186 .with_epoch(1)
3187 .with_post(Some(456))
3188 .with_dev(Some(34)),
3189 ),
3190 (
3191 "1!1.0.post456",
3192 Version::new([1, 0]).with_epoch(1).with_post(Some(456)),
3193 ),
3194 (
3195 "1!1.1.dev1",
3196 Version::new([1, 1]).with_epoch(1).with_dev(Some(1)),
3197 ),
3198 (
3199 "1!1.2+123abc",
3200 Version::new([1, 2])
3201 .with_epoch(1)
3202 .with_local_segments(vec![LocalSegment::String("123abc".to_string())]),
3203 ),
3204 (
3205 "1!1.2+123abc456",
3206 Version::new([1, 2])
3207 .with_epoch(1)
3208 .with_local_segments(vec![LocalSegment::String("123abc456".to_string())]),
3209 ),
3210 (
3211 "1!1.2+abc",
3212 Version::new([1, 2])
3213 .with_epoch(1)
3214 .with_local_segments(vec![LocalSegment::String("abc".to_string())]),
3215 ),
3216 (
3217 "1!1.2+abc123",
3218 Version::new([1, 2])
3219 .with_epoch(1)
3220 .with_local_segments(vec![LocalSegment::String("abc123".to_string())]),
3221 ),
3222 (
3223 "1!1.2+abc123def",
3224 Version::new([1, 2])
3225 .with_epoch(1)
3226 .with_local_segments(vec![LocalSegment::String("abc123def".to_string())]),
3227 ),
3228 (
3229 "1!1.2+1234.abc",
3230 Version::new([1, 2]).with_epoch(1).with_local_segments(vec![
3231 LocalSegment::Number(1234),
3232 LocalSegment::String("abc".to_string()),
3233 ]),
3234 ),
3235 (
3236 "1!1.2+123456",
3237 Version::new([1, 2])
3238 .with_epoch(1)
3239 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3240 ),
3241 (
3242 "1!1.2.r32+123456",
3243 Version::new([1, 2])
3244 .with_epoch(1)
3245 .with_post(Some(32))
3246 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3247 ),
3248 (
3249 "1!1.2.rev33+123456",
3250 Version::new([1, 2])
3251 .with_epoch(1)
3252 .with_post(Some(33))
3253 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3254 ),
3255 (
3256 "98765!1.2.rev33+123456",
3257 Version::new([1, 2])
3258 .with_epoch(98765)
3259 .with_post(Some(33))
3260 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3261 ),
3262 ];
3263 for (string, structured) in versions {
3264 match Version::from_str(string) {
3265 Err(err) => {
3266 unreachable!(
3267 "expected {string:?} to parse as {structured:?}, but got {err:?}",
3268 structured = structured.as_bloated_debug(),
3269 )
3270 }
3271 Ok(v) => assert!(
3272 v == structured,
3273 "for {string:?}, expected {structured:?} but got {v:?}",
3274 structured = structured.as_bloated_debug(),
3275 v = v.as_bloated_debug(),
3276 ),
3277 }
3278 let spec = format!("=={string}");
3279 match VersionSpecifier::from_str(&spec) {
3280 Err(err) => {
3281 unreachable!(
3282 "expected version in {spec:?} to parse as {structured:?}, but got {err:?}",
3283 structured = structured.as_bloated_debug(),
3284 )
3285 }
3286 Ok(v) => assert!(
3287 v.version() == &structured,
3288 "for {string:?}, expected {structured:?} but got {v:?}",
3289 structured = structured.as_bloated_debug(),
3290 v = v.version.as_bloated_debug(),
3291 ),
3292 }
3293 }
3294 }
3295
3296 #[test]
3298 fn test_packaging_failures() {
3299 let versions = [
3300 "1.0+a+",
3302 "1.0++",
3303 "1.0+_foobar",
3304 "1.0+foo&asd",
3305 "1.0+1+1",
3306 "french toast",
3308 "==french toast",
3309 ];
3310 for version in versions {
3311 assert!(Version::from_str(version).is_err());
3312 assert!(VersionSpecifier::from_str(&format!("=={version}")).is_err());
3313 }
3314 }
3315
3316 #[test]
3317 fn test_equality_and_normalization() {
3318 let versions = [
3319 ("1.0dev", "1.0.dev0"),
3321 ("1.0.dev", "1.0.dev0"),
3322 ("1.0dev1", "1.0.dev1"),
3323 ("1.0dev", "1.0.dev0"),
3324 ("1.0-dev", "1.0.dev0"),
3325 ("1.0-dev1", "1.0.dev1"),
3326 ("1.0DEV", "1.0.dev0"),
3327 ("1.0.DEV", "1.0.dev0"),
3328 ("1.0DEV1", "1.0.dev1"),
3329 ("1.0DEV", "1.0.dev0"),
3330 ("1.0.DEV1", "1.0.dev1"),
3331 ("1.0-DEV", "1.0.dev0"),
3332 ("1.0-DEV1", "1.0.dev1"),
3333 ("1.0a", "1.0a0"),
3335 ("1.0.a", "1.0a0"),
3336 ("1.0.a1", "1.0a1"),
3337 ("1.0-a", "1.0a0"),
3338 ("1.0-a1", "1.0a1"),
3339 ("1.0alpha", "1.0a0"),
3340 ("1.0.alpha", "1.0a0"),
3341 ("1.0.alpha1", "1.0a1"),
3342 ("1.0-alpha", "1.0a0"),
3343 ("1.0-alpha1", "1.0a1"),
3344 ("1.0A", "1.0a0"),
3345 ("1.0.A", "1.0a0"),
3346 ("1.0.A1", "1.0a1"),
3347 ("1.0-A", "1.0a0"),
3348 ("1.0-A1", "1.0a1"),
3349 ("1.0ALPHA", "1.0a0"),
3350 ("1.0.ALPHA", "1.0a0"),
3351 ("1.0.ALPHA1", "1.0a1"),
3352 ("1.0-ALPHA", "1.0a0"),
3353 ("1.0-ALPHA1", "1.0a1"),
3354 ("1.0b", "1.0b0"),
3356 ("1.0.b", "1.0b0"),
3357 ("1.0.b1", "1.0b1"),
3358 ("1.0-b", "1.0b0"),
3359 ("1.0-b1", "1.0b1"),
3360 ("1.0beta", "1.0b0"),
3361 ("1.0.beta", "1.0b0"),
3362 ("1.0.beta1", "1.0b1"),
3363 ("1.0-beta", "1.0b0"),
3364 ("1.0-beta1", "1.0b1"),
3365 ("1.0B", "1.0b0"),
3366 ("1.0.B", "1.0b0"),
3367 ("1.0.B1", "1.0b1"),
3368 ("1.0-B", "1.0b0"),
3369 ("1.0-B1", "1.0b1"),
3370 ("1.0BETA", "1.0b0"),
3371 ("1.0.BETA", "1.0b0"),
3372 ("1.0.BETA1", "1.0b1"),
3373 ("1.0-BETA", "1.0b0"),
3374 ("1.0-BETA1", "1.0b1"),
3375 ("1.0c", "1.0rc0"),
3377 ("1.0.c", "1.0rc0"),
3378 ("1.0.c1", "1.0rc1"),
3379 ("1.0-c", "1.0rc0"),
3380 ("1.0-c1", "1.0rc1"),
3381 ("1.0rc", "1.0rc0"),
3382 ("1.0.rc", "1.0rc0"),
3383 ("1.0.rc1", "1.0rc1"),
3384 ("1.0-rc", "1.0rc0"),
3385 ("1.0-rc1", "1.0rc1"),
3386 ("1.0C", "1.0rc0"),
3387 ("1.0.C", "1.0rc0"),
3388 ("1.0.C1", "1.0rc1"),
3389 ("1.0-C", "1.0rc0"),
3390 ("1.0-C1", "1.0rc1"),
3391 ("1.0RC", "1.0rc0"),
3392 ("1.0.RC", "1.0rc0"),
3393 ("1.0.RC1", "1.0rc1"),
3394 ("1.0-RC", "1.0rc0"),
3395 ("1.0-RC1", "1.0rc1"),
3396 ("1.0post", "1.0.post0"),
3398 ("1.0.post", "1.0.post0"),
3399 ("1.0post1", "1.0.post1"),
3400 ("1.0post", "1.0.post0"),
3401 ("1.0-post", "1.0.post0"),
3402 ("1.0-post1", "1.0.post1"),
3403 ("1.0POST", "1.0.post0"),
3404 ("1.0.POST", "1.0.post0"),
3405 ("1.0POST1", "1.0.post1"),
3406 ("1.0POST", "1.0.post0"),
3407 ("1.0r", "1.0.post0"),
3408 ("1.0rev", "1.0.post0"),
3409 ("1.0.POST1", "1.0.post1"),
3410 ("1.0.r1", "1.0.post1"),
3411 ("1.0.rev1", "1.0.post1"),
3412 ("1.0-POST", "1.0.post0"),
3413 ("1.0-POST1", "1.0.post1"),
3414 ("1.0-5", "1.0.post5"),
3415 ("1.0-r5", "1.0.post5"),
3416 ("1.0-rev5", "1.0.post5"),
3417 ("1.0+AbC", "1.0+abc"),
3419 ("1.01", "1.1"),
3421 ("1.0a05", "1.0a5"),
3422 ("1.0b07", "1.0b7"),
3423 ("1.0c056", "1.0rc56"),
3424 ("1.0rc09", "1.0rc9"),
3425 ("1.0.post000", "1.0.post0"),
3426 ("1.1.dev09000", "1.1.dev9000"),
3427 ("00!1.2", "1.2"),
3428 ("0100!0.0", "100!0.0"),
3429 ("v1.0", "1.0"),
3431 (" v1.0\t\n", "1.0"),
3432 ];
3433 for (version_str, normalized_str) in versions {
3434 let version = Version::from_str(version_str).unwrap();
3435 let normalized = Version::from_str(normalized_str).unwrap();
3436 assert_eq!(version, normalized, "{version_str} {normalized_str}");
3438 assert_eq!(
3440 version.to_string(),
3441 normalized.to_string(),
3442 "{version_str} {normalized_str}"
3443 );
3444 }
3445 }
3446
3447 #[test]
3449 fn test_equality_and_normalization2() {
3450 let versions = [
3451 ("1.0.dev456", "1.0.dev456"),
3452 ("1.0a1", "1.0a1"),
3453 ("1.0a2.dev456", "1.0a2.dev456"),
3454 ("1.0a12.dev456", "1.0a12.dev456"),
3455 ("1.0a12", "1.0a12"),
3456 ("1.0b1.dev456", "1.0b1.dev456"),
3457 ("1.0b2", "1.0b2"),
3458 ("1.0b2.post345.dev456", "1.0b2.post345.dev456"),
3459 ("1.0b2.post345", "1.0b2.post345"),
3460 ("1.0rc1.dev456", "1.0rc1.dev456"),
3461 ("1.0rc1", "1.0rc1"),
3462 ("1.0", "1.0"),
3463 ("1.0.post456.dev34", "1.0.post456.dev34"),
3464 ("1.0.post456", "1.0.post456"),
3465 ("1.0.1", "1.0.1"),
3466 ("0!1.0.2", "1.0.2"),
3467 ("1.0.3+7", "1.0.3+7"),
3468 ("0!1.0.4+8.0", "1.0.4+8.0"),
3469 ("1.0.5+9.5", "1.0.5+9.5"),
3470 ("1.2+1234.abc", "1.2+1234.abc"),
3471 ("1.2+123456", "1.2+123456"),
3472 ("1.2+123abc", "1.2+123abc"),
3473 ("1.2+123abc456", "1.2+123abc456"),
3474 ("1.2+abc", "1.2+abc"),
3475 ("1.2+abc123", "1.2+abc123"),
3476 ("1.2+abc123def", "1.2+abc123def"),
3477 ("1.1.dev1", "1.1.dev1"),
3478 ("7!1.0.dev456", "7!1.0.dev456"),
3479 ("7!1.0a1", "7!1.0a1"),
3480 ("7!1.0a2.dev456", "7!1.0a2.dev456"),
3481 ("7!1.0a12.dev456", "7!1.0a12.dev456"),
3482 ("7!1.0a12", "7!1.0a12"),
3483 ("7!1.0b1.dev456", "7!1.0b1.dev456"),
3484 ("7!1.0b2", "7!1.0b2"),
3485 ("7!1.0b2.post345.dev456", "7!1.0b2.post345.dev456"),
3486 ("7!1.0b2.post345", "7!1.0b2.post345"),
3487 ("7!1.0rc1.dev456", "7!1.0rc1.dev456"),
3488 ("7!1.0rc1", "7!1.0rc1"),
3489 ("7!1.0", "7!1.0"),
3490 ("7!1.0.post456.dev34", "7!1.0.post456.dev34"),
3491 ("7!1.0.post456", "7!1.0.post456"),
3492 ("7!1.0.1", "7!1.0.1"),
3493 ("7!1.0.2", "7!1.0.2"),
3494 ("7!1.0.3+7", "7!1.0.3+7"),
3495 ("7!1.0.4+8.0", "7!1.0.4+8.0"),
3496 ("7!1.0.5+9.5", "7!1.0.5+9.5"),
3497 ("7!1.1.dev1", "7!1.1.dev1"),
3498 ];
3499 for (version_str, normalized_str) in versions {
3500 let version = Version::from_str(version_str).unwrap();
3501 let normalized = Version::from_str(normalized_str).unwrap();
3502 assert_eq!(version, normalized, "{version_str} {normalized_str}");
3503 assert_eq!(
3505 version.to_string(),
3506 normalized_str,
3507 "{version_str} {normalized_str}"
3508 );
3509 assert_eq!(
3511 version.to_string(),
3512 normalized.to_string(),
3513 "{version_str} {normalized_str}"
3514 );
3515 }
3516 }
3517
3518 #[test]
3519 fn test_star_fixed_version() {
3520 let result = Version::from_str("0.9.1.*");
3521 assert_eq!(result.unwrap_err(), ErrorKind::Wildcard.into());
3522 }
3523
3524 #[test]
3525 fn test_invalid_word() {
3526 let result = Version::from_str("blergh");
3527 assert_eq!(result.unwrap_err(), ErrorKind::NoLeadingNumber.into());
3528 }
3529
3530 #[test]
3531 fn test_from_version_star() {
3532 let p = |s: &str| -> Result<VersionPattern, _> { s.parse() };
3533 assert!(!p("1.2.3").unwrap().is_wildcard());
3534 assert!(p("1.2.3.*").unwrap().is_wildcard());
3535 assert_eq!(
3536 p("1.2.*.4.*").unwrap_err(),
3537 PatternErrorKind::WildcardNotTrailing.into(),
3538 );
3539 assert_eq!(
3540 p("1.0-dev1.*").unwrap_err(),
3541 ErrorKind::UnexpectedEnd {
3542 version: "1.0-dev1".to_string(),
3543 remaining: ".*".to_string()
3544 }
3545 .into(),
3546 );
3547 assert_eq!(
3548 p("1.0a1.*").unwrap_err(),
3549 ErrorKind::UnexpectedEnd {
3550 version: "1.0a1".to_string(),
3551 remaining: ".*".to_string()
3552 }
3553 .into(),
3554 );
3555 assert_eq!(
3556 p("1.0.post1.*").unwrap_err(),
3557 ErrorKind::UnexpectedEnd {
3558 version: "1.0.post1".to_string(),
3559 remaining: ".*".to_string()
3560 }
3561 .into(),
3562 );
3563 assert_eq!(
3564 p("1.0+lolwat.*").unwrap_err(),
3565 ErrorKind::LocalEmpty { precursor: '.' }.into(),
3566 );
3567 }
3568
3569 #[test]
3575 fn parse_version_valid() {
3576 let p = |s: &str| match Parser::new(s.as_bytes()).parse() {
3577 Ok(v) => v,
3578 Err(err) => unreachable!("expected valid version, but got error: {err:?}"),
3579 };
3580
3581 assert_eq!(p("5"), Version::new([5]));
3583 assert_eq!(p("5.6"), Version::new([5, 6]));
3584 assert_eq!(p("5.6.7"), Version::new([5, 6, 7]));
3585 assert_eq!(p("512.623.734"), Version::new([512, 623, 734]));
3586 assert_eq!(p("1.2.3.4"), Version::new([1, 2, 3, 4]));
3587 assert_eq!(p("1.2.3.4.5"), Version::new([1, 2, 3, 4, 5]));
3588
3589 assert_eq!(p("4!5"), Version::new([5]).with_epoch(4));
3591 assert_eq!(p("4!5.6"), Version::new([5, 6]).with_epoch(4));
3592
3593 assert_eq!(
3595 p("5a1"),
3596 Version::new([5]).with_pre(Some(Prerelease {
3597 kind: PrereleaseKind::Alpha,
3598 number: 1
3599 }))
3600 );
3601 assert_eq!(
3602 p("5alpha1"),
3603 Version::new([5]).with_pre(Some(Prerelease {
3604 kind: PrereleaseKind::Alpha,
3605 number: 1
3606 }))
3607 );
3608 assert_eq!(
3609 p("5b1"),
3610 Version::new([5]).with_pre(Some(Prerelease {
3611 kind: PrereleaseKind::Beta,
3612 number: 1
3613 }))
3614 );
3615 assert_eq!(
3616 p("5beta1"),
3617 Version::new([5]).with_pre(Some(Prerelease {
3618 kind: PrereleaseKind::Beta,
3619 number: 1
3620 }))
3621 );
3622 assert_eq!(
3623 p("5rc1"),
3624 Version::new([5]).with_pre(Some(Prerelease {
3625 kind: PrereleaseKind::Rc,
3626 number: 1
3627 }))
3628 );
3629 assert_eq!(
3630 p("5c1"),
3631 Version::new([5]).with_pre(Some(Prerelease {
3632 kind: PrereleaseKind::Rc,
3633 number: 1
3634 }))
3635 );
3636 assert_eq!(
3637 p("5preview1"),
3638 Version::new([5]).with_pre(Some(Prerelease {
3639 kind: PrereleaseKind::Rc,
3640 number: 1
3641 }))
3642 );
3643 assert_eq!(
3644 p("5pre1"),
3645 Version::new([5]).with_pre(Some(Prerelease {
3646 kind: PrereleaseKind::Rc,
3647 number: 1
3648 }))
3649 );
3650 assert_eq!(
3651 p("5.6.7pre1"),
3652 Version::new([5, 6, 7]).with_pre(Some(Prerelease {
3653 kind: PrereleaseKind::Rc,
3654 number: 1
3655 }))
3656 );
3657 assert_eq!(
3658 p("5alpha789"),
3659 Version::new([5]).with_pre(Some(Prerelease {
3660 kind: PrereleaseKind::Alpha,
3661 number: 789
3662 }))
3663 );
3664 assert_eq!(
3665 p("5.alpha789"),
3666 Version::new([5]).with_pre(Some(Prerelease {
3667 kind: PrereleaseKind::Alpha,
3668 number: 789
3669 }))
3670 );
3671 assert_eq!(
3672 p("5-alpha789"),
3673 Version::new([5]).with_pre(Some(Prerelease {
3674 kind: PrereleaseKind::Alpha,
3675 number: 789
3676 }))
3677 );
3678 assert_eq!(
3679 p("5_alpha789"),
3680 Version::new([5]).with_pre(Some(Prerelease {
3681 kind: PrereleaseKind::Alpha,
3682 number: 789
3683 }))
3684 );
3685 assert_eq!(
3686 p("5alpha.789"),
3687 Version::new([5]).with_pre(Some(Prerelease {
3688 kind: PrereleaseKind::Alpha,
3689 number: 789
3690 }))
3691 );
3692 assert_eq!(
3693 p("5alpha-789"),
3694 Version::new([5]).with_pre(Some(Prerelease {
3695 kind: PrereleaseKind::Alpha,
3696 number: 789
3697 }))
3698 );
3699 assert_eq!(
3700 p("5alpha_789"),
3701 Version::new([5]).with_pre(Some(Prerelease {
3702 kind: PrereleaseKind::Alpha,
3703 number: 789
3704 }))
3705 );
3706 assert_eq!(
3707 p("5ALPHA789"),
3708 Version::new([5]).with_pre(Some(Prerelease {
3709 kind: PrereleaseKind::Alpha,
3710 number: 789
3711 }))
3712 );
3713 assert_eq!(
3714 p("5aLpHa789"),
3715 Version::new([5]).with_pre(Some(Prerelease {
3716 kind: PrereleaseKind::Alpha,
3717 number: 789
3718 }))
3719 );
3720 assert_eq!(
3721 p("5alpha"),
3722 Version::new([5]).with_pre(Some(Prerelease {
3723 kind: PrereleaseKind::Alpha,
3724 number: 0
3725 }))
3726 );
3727
3728 assert_eq!(p("5post2"), Version::new([5]).with_post(Some(2)));
3730 assert_eq!(p("5rev2"), Version::new([5]).with_post(Some(2)));
3731 assert_eq!(p("5r2"), Version::new([5]).with_post(Some(2)));
3732 assert_eq!(p("5.post2"), Version::new([5]).with_post(Some(2)));
3733 assert_eq!(p("5-post2"), Version::new([5]).with_post(Some(2)));
3734 assert_eq!(p("5_post2"), Version::new([5]).with_post(Some(2)));
3735 assert_eq!(p("5.post.2"), Version::new([5]).with_post(Some(2)));
3736 assert_eq!(p("5.post-2"), Version::new([5]).with_post(Some(2)));
3737 assert_eq!(p("5.post_2"), Version::new([5]).with_post(Some(2)));
3738 assert_eq!(
3739 p("5.6.7.post_2"),
3740 Version::new([5, 6, 7]).with_post(Some(2))
3741 );
3742 assert_eq!(p("5-2"), Version::new([5]).with_post(Some(2)));
3743 assert_eq!(p("5.6.7-2"), Version::new([5, 6, 7]).with_post(Some(2)));
3744 assert_eq!(p("5POST2"), Version::new([5]).with_post(Some(2)));
3745 assert_eq!(p("5PoSt2"), Version::new([5]).with_post(Some(2)));
3746 assert_eq!(p("5post"), Version::new([5]).with_post(Some(0)));
3747
3748 assert_eq!(p("5dev2"), Version::new([5]).with_dev(Some(2)));
3750 assert_eq!(p("5.dev2"), Version::new([5]).with_dev(Some(2)));
3751 assert_eq!(p("5-dev2"), Version::new([5]).with_dev(Some(2)));
3752 assert_eq!(p("5_dev2"), Version::new([5]).with_dev(Some(2)));
3753 assert_eq!(p("5.dev.2"), Version::new([5]).with_dev(Some(2)));
3754 assert_eq!(p("5.dev-2"), Version::new([5]).with_dev(Some(2)));
3755 assert_eq!(p("5.dev_2"), Version::new([5]).with_dev(Some(2)));
3756 assert_eq!(p("5.6.7.dev_2"), Version::new([5, 6, 7]).with_dev(Some(2)));
3757 assert_eq!(p("5DEV2"), Version::new([5]).with_dev(Some(2)));
3758 assert_eq!(p("5dEv2"), Version::new([5]).with_dev(Some(2)));
3759 assert_eq!(p("5DeV2"), Version::new([5]).with_dev(Some(2)));
3760 assert_eq!(p("5dev"), Version::new([5]).with_dev(Some(0)));
3761
3762 assert_eq!(
3764 p("5+2"),
3765 Version::new([5]).with_local_segments(vec![LocalSegment::Number(2)])
3766 );
3767 assert_eq!(
3768 p("5+a"),
3769 Version::new([5]).with_local_segments(vec![LocalSegment::String("a".to_string())])
3770 );
3771 assert_eq!(
3772 p("5+abc.123"),
3773 Version::new([5]).with_local_segments(vec![
3774 LocalSegment::String("abc".to_string()),
3775 LocalSegment::Number(123),
3776 ])
3777 );
3778 assert_eq!(
3779 p("5+123.abc"),
3780 Version::new([5]).with_local_segments(vec![
3781 LocalSegment::Number(123),
3782 LocalSegment::String("abc".to_string()),
3783 ])
3784 );
3785 assert_eq!(
3786 p("5+18446744073709551615.abc"),
3787 Version::new([5]).with_local_segments(vec![
3788 LocalSegment::Number(18_446_744_073_709_551_615),
3789 LocalSegment::String("abc".to_string()),
3790 ])
3791 );
3792 assert_eq!(
3793 p("5+18446744073709551616.abc"),
3794 Version::new([5]).with_local_segments(vec![
3795 LocalSegment::String("18446744073709551616".to_string()),
3796 LocalSegment::String("abc".to_string()),
3797 ])
3798 );
3799 assert_eq!(
3800 p("5+ABC.123"),
3801 Version::new([5]).with_local_segments(vec![
3802 LocalSegment::String("abc".to_string()),
3803 LocalSegment::Number(123),
3804 ])
3805 );
3806 assert_eq!(
3807 p("5+ABC-123.4_5_xyz-MNO"),
3808 Version::new([5]).with_local_segments(vec![
3809 LocalSegment::String("abc".to_string()),
3810 LocalSegment::Number(123),
3811 LocalSegment::Number(4),
3812 LocalSegment::Number(5),
3813 LocalSegment::String("xyz".to_string()),
3814 LocalSegment::String("mno".to_string()),
3815 ])
3816 );
3817 assert_eq!(
3818 p("5.6.7+abc-00123"),
3819 Version::new([5, 6, 7]).with_local_segments(vec![
3820 LocalSegment::String("abc".to_string()),
3821 LocalSegment::Number(123),
3822 ])
3823 );
3824 assert_eq!(
3825 p("5.6.7+abc-foo00123"),
3826 Version::new([5, 6, 7]).with_local_segments(vec![
3827 LocalSegment::String("abc".to_string()),
3828 LocalSegment::String("foo00123".to_string()),
3829 ])
3830 );
3831 assert_eq!(
3832 p("5.6.7+abc-00123a"),
3833 Version::new([5, 6, 7]).with_local_segments(vec![
3834 LocalSegment::String("abc".to_string()),
3835 LocalSegment::String("00123a".to_string()),
3836 ])
3837 );
3838
3839 assert_eq!(
3841 p("5a2post3"),
3842 Version::new([5])
3843 .with_pre(Some(Prerelease {
3844 kind: PrereleaseKind::Alpha,
3845 number: 2
3846 }))
3847 .with_post(Some(3))
3848 );
3849 assert_eq!(
3850 p("5.a-2_post-3"),
3851 Version::new([5])
3852 .with_pre(Some(Prerelease {
3853 kind: PrereleaseKind::Alpha,
3854 number: 2
3855 }))
3856 .with_post(Some(3))
3857 );
3858 assert_eq!(
3859 p("5a2-3"),
3860 Version::new([5])
3861 .with_pre(Some(Prerelease {
3862 kind: PrereleaseKind::Alpha,
3863 number: 2
3864 }))
3865 .with_post(Some(3))
3866 );
3867
3868 assert_eq!(p("v5"), Version::new([5]));
3870 assert_eq!(p("V5"), Version::new([5]));
3871 assert_eq!(p("v5.6.7"), Version::new([5, 6, 7]));
3872
3873 assert_eq!(p(" v5 "), Version::new([5]));
3875 assert_eq!(p(" 5 "), Version::new([5]));
3876 assert_eq!(
3877 p(" 5.6.7+abc.123.xyz "),
3878 Version::new([5, 6, 7]).with_local_segments(vec![
3879 LocalSegment::String("abc".to_string()),
3880 LocalSegment::Number(123),
3881 LocalSegment::String("xyz".to_string())
3882 ])
3883 );
3884 assert_eq!(p(" \n5\n \t"), Version::new([5]));
3885
3886 assert!(Parser::new("1.min0".as_bytes()).parse().is_err());
3888 }
3889
3890 #[test]
3898 fn parse_version_invalid() {
3899 let p = |s: &str| match Parser::new(s.as_bytes()).parse() {
3900 Err(err) => err,
3901 Ok(v) => unreachable!(
3902 "expected version parser error, but got: {v:?}",
3903 v = v.as_bloated_debug()
3904 ),
3905 };
3906
3907 assert_eq!(p(""), ErrorKind::NoLeadingNumber.into());
3908 assert_eq!(p("a"), ErrorKind::NoLeadingNumber.into());
3909 assert_eq!(p("v 5"), ErrorKind::NoLeadingNumber.into());
3910 assert_eq!(p("V 5"), ErrorKind::NoLeadingNumber.into());
3911 assert_eq!(p("x 5"), ErrorKind::NoLeadingNumber.into());
3912 assert_eq!(
3913 p("18446744073709551616"),
3914 ErrorKind::NumberTooBig {
3915 bytes: b"18446744073709551616".to_vec()
3916 }
3917 .into()
3918 );
3919 assert_eq!(p("5!"), ErrorKind::NoLeadingReleaseNumber.into());
3920 assert_eq!(
3921 p("5.6./"),
3922 ErrorKind::UnexpectedEnd {
3923 version: "5.6".to_string(),
3924 remaining: "./".to_string()
3925 }
3926 .into()
3927 );
3928 assert_eq!(
3929 p("5.6.-alpha2"),
3930 ErrorKind::UnexpectedEnd {
3931 version: "5.6".to_string(),
3932 remaining: ".-alpha2".to_string()
3933 }
3934 .into()
3935 );
3936 assert_eq!(
3937 p("1.2.3a18446744073709551616"),
3938 ErrorKind::NumberTooBig {
3939 bytes: b"18446744073709551616".to_vec()
3940 }
3941 .into()
3942 );
3943 assert_eq!(p("5+"), ErrorKind::LocalEmpty { precursor: '+' }.into());
3944 assert_eq!(p("5+ "), ErrorKind::LocalEmpty { precursor: '+' }.into());
3945 assert_eq!(p("5+abc."), ErrorKind::LocalEmpty { precursor: '.' }.into());
3946 assert_eq!(p("5+abc-"), ErrorKind::LocalEmpty { precursor: '-' }.into());
3947 assert_eq!(p("5+abc_"), ErrorKind::LocalEmpty { precursor: '_' }.into());
3948 assert_eq!(
3949 p("5+abc. "),
3950 ErrorKind::LocalEmpty { precursor: '.' }.into()
3951 );
3952 assert_eq!(
3953 p("5.6-"),
3954 ErrorKind::UnexpectedEnd {
3955 version: "5.6".to_string(),
3956 remaining: "-".to_string()
3957 }
3958 .into()
3959 );
3960 }
3961
3962 #[test]
3963 fn parse_version_pattern_valid() {
3964 let p = |s: &str| match Parser::new(s.as_bytes()).parse_pattern() {
3965 Ok(v) => v,
3966 Err(err) => unreachable!("expected valid version, but got error: {err:?}"),
3967 };
3968
3969 assert_eq!(p("5.*"), VersionPattern::wildcard(Version::new([5])));
3970 assert_eq!(p("5.6.*"), VersionPattern::wildcard(Version::new([5, 6])));
3971 assert_eq!(
3972 p("2!5.6.*"),
3973 VersionPattern::wildcard(Version::new([5, 6]).with_epoch(2))
3974 );
3975 }
3976
3977 #[test]
3978 fn parse_version_pattern_invalid() {
3979 let p = |s: &str| match Parser::new(s.as_bytes()).parse_pattern() {
3980 Err(err) => err,
3981 Ok(vpat) => unreachable!("expected version pattern parser error, but got: {vpat:?}"),
3982 };
3983
3984 assert_eq!(p("*"), ErrorKind::NoLeadingNumber.into());
3985 assert_eq!(p("2!*"), ErrorKind::NoLeadingReleaseNumber.into());
3986 }
3987
3988 #[test]
3993 fn ordering() {
3994 let versions = &[
3995 "1.dev0",
3996 "1.0.dev456",
3997 "1.0a1",
3998 "1.0a2.dev456",
3999 "1.0a12.dev456",
4000 "1.0a12",
4001 "1.0b1.dev456",
4002 "1.0b2",
4003 "1.0b2.post345.dev456",
4004 "1.0b2.post345",
4005 "1.0rc1.dev456",
4006 "1.0rc1",
4007 "1.0",
4008 "1.0+abc.5",
4009 "1.0+abc.7",
4010 "1.0+5",
4011 "1.0.post456.dev34",
4012 "1.0.post456",
4013 "1.0.15",
4014 "1.1.dev1",
4015 ];
4016 for (i, v1) in versions.iter().enumerate() {
4017 for v2 in &versions[i + 1..] {
4018 let less = v1.parse::<Version>().unwrap();
4019 let greater = v2.parse::<Version>().unwrap();
4020 assert_eq!(
4021 less.cmp(&greater),
4022 Ordering::Less,
4023 "less: {:?}\ngreater: {:?}",
4024 less.as_bloated_debug(),
4025 greater.as_bloated_debug()
4026 );
4027 }
4028 }
4029 }
4030
4031 #[test]
4032 fn local_sentinel_version() {
4033 let sentinel = Version::new([1, 0]).with_local(LocalVersion::Max);
4034
4035 let versions = &["1.0.post0", "1.1"];
4037
4038 for greater in versions {
4039 let greater = greater.parse::<Version>().unwrap();
4040 assert_eq!(
4041 sentinel.cmp(&greater),
4042 Ordering::Less,
4043 "less: {:?}\ngreater: {:?}",
4044 greater.as_bloated_debug(),
4045 sentinel.as_bloated_debug(),
4046 );
4047 }
4048
4049 let versions = &["1.0", "1.0.a0", "1.0+local"];
4051
4052 for less in versions {
4053 let less = less.parse::<Version>().unwrap();
4054 assert_eq!(
4055 sentinel.cmp(&less),
4056 Ordering::Greater,
4057 "less: {:?}\ngreater: {:?}",
4058 sentinel.as_bloated_debug(),
4059 less.as_bloated_debug()
4060 );
4061 }
4062 }
4063
4064 #[test]
4065 fn min_version() {
4066 let less = Version::new([1, 0]).with_min(Some(0));
4068
4069 let versions = &[
4070 "1.dev0",
4071 "1.0.dev456",
4072 "1.0a1",
4073 "1.0a2.dev456",
4074 "1.0a12.dev456",
4075 "1.0a12",
4076 "1.0b1.dev456",
4077 "1.0b2",
4078 "1.0b2.post345.dev456",
4079 "1.0b2.post345",
4080 "1.0rc1.dev456",
4081 "1.0rc1",
4082 "1.0",
4083 "1.0+abc.5",
4084 "1.0+abc.7",
4085 "1.0+5",
4086 "1.0.post456.dev34",
4087 "1.0.post456",
4088 "1.0.15",
4089 "1.1.dev1",
4090 ];
4091
4092 for greater in versions {
4093 let greater = greater.parse::<Version>().unwrap();
4094 assert_eq!(
4095 less.cmp(&greater),
4096 Ordering::Less,
4097 "less: {:?}\ngreater: {:?}",
4098 less.as_bloated_debug(),
4099 greater.as_bloated_debug()
4100 );
4101 }
4102 }
4103
4104 #[test]
4105 fn max_version() {
4106 let greater = Version::new([1, 0]).with_max(Some(0));
4108
4109 let versions = &[
4110 "1.dev0",
4111 "1.0.dev456",
4112 "1.0a1",
4113 "1.0a2.dev456",
4114 "1.0a12.dev456",
4115 "1.0a12",
4116 "1.0b1.dev456",
4117 "1.0b2",
4118 "1.0b2.post345.dev456",
4119 "1.0b2.post345",
4120 "1.0rc1.dev456",
4121 "1.0rc1",
4122 "1.0",
4123 "1.0+abc.5",
4124 "1.0+abc.7",
4125 "1.0+5",
4126 "1.0.post456.dev34",
4127 "1.0.post456",
4128 "1.0",
4129 ];
4130
4131 for less in versions {
4132 let less = less.parse::<Version>().unwrap();
4133 assert_eq!(
4134 less.cmp(&greater),
4135 Ordering::Less,
4136 "less: {:?}\ngreater: {:?}",
4137 less.as_bloated_debug(),
4138 greater.as_bloated_debug()
4139 );
4140 }
4141
4142 let greater = Version::new([1, 0])
4144 .with_pre(Some(Prerelease {
4145 kind: PrereleaseKind::Alpha,
4146 number: 1,
4147 }))
4148 .with_max(Some(0));
4149
4150 let versions = &["1.0a1", "1.0a1+local", "1.0a1.post1"];
4151
4152 for less in versions {
4153 let less = less.parse::<Version>().unwrap();
4154 assert_eq!(
4155 less.cmp(&greater),
4156 Ordering::Less,
4157 "less: {:?}\ngreater: {:?}",
4158 less.as_bloated_debug(),
4159 greater.as_bloated_debug()
4160 );
4161 }
4162
4163 let less = Version::new([1, 0])
4165 .with_pre(Some(Prerelease {
4166 kind: PrereleaseKind::Alpha,
4167 number: 1,
4168 }))
4169 .with_max(Some(0));
4170
4171 let versions = &["1.0b1", "1.0b1+local", "1.0b1.post1", "1.0"];
4172
4173 for greater in versions {
4174 let greater = greater.parse::<Version>().unwrap();
4175 assert_eq!(
4176 less.cmp(&greater),
4177 Ordering::Less,
4178 "less: {:?}\ngreater: {:?}",
4179 less.as_bloated_debug(),
4180 greater.as_bloated_debug()
4181 );
4182 }
4183 }
4184
4185 #[test]
4187 fn parse_number_u64() {
4188 let p = |s: &str| parse_u64(s.as_bytes());
4189 assert_eq!(p("0"), Ok(0));
4190 assert_eq!(p("00"), Ok(0));
4191 assert_eq!(p("1"), Ok(1));
4192 assert_eq!(p("01"), Ok(1));
4193 assert_eq!(p("9"), Ok(9));
4194 assert_eq!(p("10"), Ok(10));
4195 assert_eq!(p("18446744073709551615"), Ok(18_446_744_073_709_551_615));
4196 assert_eq!(p("018446744073709551615"), Ok(18_446_744_073_709_551_615));
4197 assert_eq!(
4198 p("000000018446744073709551615"),
4199 Ok(18_446_744_073_709_551_615)
4200 );
4201
4202 assert_eq!(p("10a"), Err(ErrorKind::InvalidDigit { got: b'a' }.into()));
4203 assert_eq!(p("10["), Err(ErrorKind::InvalidDigit { got: b'[' }.into()));
4204 assert_eq!(p("10/"), Err(ErrorKind::InvalidDigit { got: b'/' }.into()));
4205 assert_eq!(
4207 p("18446744073709551616"),
4208 Err(ErrorKind::NumberTooBig {
4209 bytes: b"18446744073709551616".to_vec()
4210 }
4211 .into())
4212 );
4213 assert_eq!(
4214 p("18446744073799551615abc"),
4215 Err(ErrorKind::NumberTooBig {
4216 bytes: b"18446744073799551615abc".to_vec()
4217 }
4218 .into())
4219 );
4220 assert_eq!(
4221 parse_u64(b"18446744073799551615\xFF"),
4222 Err(ErrorKind::NumberTooBig {
4223 bytes: b"18446744073799551615\xFF".to_vec()
4224 }
4225 .into())
4226 );
4227 }
4228
4229 impl Version {
4230 pub(crate) fn as_bloated_debug(&self) -> impl std::fmt::Debug + '_ {
4240 std::fmt::from_fn(|f| {
4241 f.debug_struct("Version")
4242 .field("epoch", &self.epoch())
4243 .field("release", &&*self.release())
4244 .field("pre", &self.pre())
4245 .field("post", &self.post())
4246 .field("dev", &self.dev())
4247 .field("local", &self.local())
4248 .field("min", &self.min())
4249 .field("max", &self.max())
4250 .finish()
4251 })
4252 }
4253 }
4254
4255 #[test]
4259 fn preserve_trailing_zeros() {
4260 let v1: Version = "1.2.0".parse().unwrap();
4261 assert_eq!(&*v1.release(), &[1, 2, 0]);
4262 assert_eq!(v1.to_string(), "1.2.0");
4263
4264 let v2: Version = "1.2".parse().unwrap();
4265 assert_eq!(&*v2.release(), &[1, 2]);
4266 assert_eq!(v2.to_string(), "1.2");
4267 }
4268
4269 #[test]
4270 fn only_release_trimmed_discards_non_release_segments() {
4271 for version in ["1.2a1", "1.2.post1", "1!1.2", "1.2+local", "1.2.dev1"] {
4272 let version = version.parse::<Version>().unwrap();
4273 assert_eq!(version.only_release_trimmed(), Version::new([1, 2]));
4274 }
4275
4276 assert_eq!(
4277 Version::new([1, 2])
4278 .with_min(Some(0))
4279 .only_release_trimmed(),
4280 Version::new([1, 2])
4281 );
4282 assert_eq!(
4283 Version::new([1, 2])
4284 .with_max(Some(0))
4285 .only_release_trimmed(),
4286 Version::new([1, 2])
4287 );
4288 assert_eq!(
4289 Version::new([1, 2, 0]).only_release_trimmed(),
4290 Version::new([1, 2])
4291 );
4292 assert_eq!(
4293 Version::new([1, 2]).only_release_trimmed(),
4294 Version::new([1, 2])
4295 );
4296 }
4297
4298 #[test]
4299 fn type_size() {
4300 assert_eq!(size_of::<VersionSmall>(), size_of::<usize>() * 2);
4301 assert_eq!(size_of::<Version>(), size_of::<usize>() * 2);
4302 }
4303
4304 #[test]
4307 fn bump_major() {
4308 let mut version = "0".parse::<Version>().unwrap();
4310 version.bump(BumpCommand::BumpRelease {
4311 index: 0,
4312 value: None,
4313 });
4314 assert_eq!(version.to_string().as_str(), "1");
4315
4316 let mut version = "1.5".parse::<Version>().unwrap();
4318 version.bump(BumpCommand::BumpRelease {
4319 index: 0,
4320 value: None,
4321 });
4322 assert_eq!(version.to_string().as_str(), "2.0");
4323
4324 let mut version = "0.1.2".parse::<Version>().unwrap();
4326 version.bump(BumpCommand::BumpRelease {
4327 index: 0,
4328 value: None,
4329 });
4330 assert_eq!(version.to_string().as_str(), "1.0.0");
4331
4332 let mut version = "1.2.3".parse::<Version>().unwrap();
4334 version.bump(BumpCommand::BumpRelease {
4335 index: 0,
4336 value: None,
4337 });
4338 assert_eq!(version.to_string().as_str(), "2.0.0");
4339
4340 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4342 version.bump(BumpCommand::BumpRelease {
4343 index: 0,
4344 value: None,
4345 });
4346 assert_eq!(version.to_string().as_str(), "2.0.0.0");
4347
4348 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4350 .parse::<Version>()
4351 .unwrap();
4352 version.bump(BumpCommand::BumpRelease {
4353 index: 0,
4354 value: None,
4355 });
4356 assert_eq!(version.to_string().as_str(), "5!2.0.0.0+local");
4357 version.bump(BumpCommand::BumpRelease {
4358 index: 0,
4359 value: None,
4360 });
4361 assert_eq!(version.to_string().as_str(), "5!3.0.0.0+local");
4362 }
4363
4364 #[test]
4367 fn bump_minor() {
4368 let mut version = "0".parse::<Version>().unwrap();
4370 version.bump(BumpCommand::BumpRelease {
4371 index: 1,
4372 value: None,
4373 });
4374 assert_eq!(version.to_string().as_str(), "0.1");
4375
4376 let mut version = "1.5".parse::<Version>().unwrap();
4378 version.bump(BumpCommand::BumpRelease {
4379 index: 1,
4380 value: None,
4381 });
4382 assert_eq!(version.to_string().as_str(), "1.6");
4383
4384 let mut version = "5.3.6".parse::<Version>().unwrap();
4386 version.bump(BumpCommand::BumpRelease {
4387 index: 1,
4388 value: None,
4389 });
4390 assert_eq!(version.to_string().as_str(), "5.4.0");
4391
4392 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4394 version.bump(BumpCommand::BumpRelease {
4395 index: 1,
4396 value: None,
4397 });
4398 assert_eq!(version.to_string().as_str(), "1.3.0.0");
4399
4400 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4402 .parse::<Version>()
4403 .unwrap();
4404 version.bump(BumpCommand::BumpRelease {
4405 index: 1,
4406 value: None,
4407 });
4408 assert_eq!(version.to_string().as_str(), "5!1.8.0.0+local");
4409 version.bump(BumpCommand::BumpRelease {
4410 index: 1,
4411 value: None,
4412 });
4413 assert_eq!(version.to_string().as_str(), "5!1.9.0.0+local");
4414 }
4415
4416 #[test]
4419 fn bump_patch() {
4420 let mut version = "0".parse::<Version>().unwrap();
4422 version.bump(BumpCommand::BumpRelease {
4423 index: 2,
4424 value: None,
4425 });
4426 assert_eq!(version.to_string().as_str(), "0.0.1");
4427
4428 let mut version = "1.5".parse::<Version>().unwrap();
4430 version.bump(BumpCommand::BumpRelease {
4431 index: 2,
4432 value: None,
4433 });
4434 assert_eq!(version.to_string().as_str(), "1.5.1");
4435
4436 let mut version = "5.3.6".parse::<Version>().unwrap();
4438 version.bump(BumpCommand::BumpRelease {
4439 index: 2,
4440 value: None,
4441 });
4442 assert_eq!(version.to_string().as_str(), "5.3.7");
4443
4444 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4446 version.bump(BumpCommand::BumpRelease {
4447 index: 2,
4448 value: None,
4449 });
4450 assert_eq!(version.to_string().as_str(), "1.2.4.0");
4451
4452 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4454 .parse::<Version>()
4455 .unwrap();
4456 version.bump(BumpCommand::BumpRelease {
4457 index: 2,
4458 value: None,
4459 });
4460 assert_eq!(version.to_string().as_str(), "5!1.7.4.0+local");
4461 version.bump(BumpCommand::BumpRelease {
4462 index: 2,
4463 value: None,
4464 });
4465 assert_eq!(version.to_string().as_str(), "5!1.7.5.0+local");
4466 }
4467
4468 #[test]
4471 fn bump_alpha() {
4472 let mut version = "0".parse::<Version>().unwrap();
4474 version.bump(BumpCommand::BumpPrerelease {
4475 kind: PrereleaseKind::Alpha,
4476 value: None,
4477 });
4478 assert_eq!(version.to_string().as_str(), "0a1");
4479
4480 let mut version = "1.5".parse::<Version>().unwrap();
4482 version.bump(BumpCommand::BumpPrerelease {
4483 kind: PrereleaseKind::Alpha,
4484 value: None,
4485 });
4486 assert_eq!(version.to_string().as_str(), "1.5a1");
4487
4488 let mut version = "5.3.6".parse::<Version>().unwrap();
4490 version.bump(BumpCommand::BumpPrerelease {
4491 kind: PrereleaseKind::Alpha,
4492 value: None,
4493 });
4494 assert_eq!(version.to_string().as_str(), "5.3.6a1");
4495
4496 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4498 version.bump(BumpCommand::BumpPrerelease {
4499 kind: PrereleaseKind::Alpha,
4500 value: None,
4501 });
4502 assert_eq!(version.to_string().as_str(), "1.2.3.4a1");
4503
4504 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4506 .parse::<Version>()
4507 .unwrap();
4508 version.bump(BumpCommand::BumpPrerelease {
4509 kind: PrereleaseKind::Alpha,
4510 value: None,
4511 });
4512 assert_eq!(version.to_string().as_str(), "5!1.7.3.5a1+local");
4513 version.bump(BumpCommand::BumpPrerelease {
4514 kind: PrereleaseKind::Alpha,
4515 value: None,
4516 });
4517 assert_eq!(version.to_string().as_str(), "5!1.7.3.5a2+local");
4518 }
4519
4520 #[test]
4523 fn bump_beta() {
4524 let mut version = "0".parse::<Version>().unwrap();
4526 version.bump(BumpCommand::BumpPrerelease {
4527 kind: PrereleaseKind::Beta,
4528 value: None,
4529 });
4530 assert_eq!(version.to_string().as_str(), "0b1");
4531
4532 let mut version = "1.5".parse::<Version>().unwrap();
4534 version.bump(BumpCommand::BumpPrerelease {
4535 kind: PrereleaseKind::Beta,
4536 value: None,
4537 });
4538 assert_eq!(version.to_string().as_str(), "1.5b1");
4539
4540 let mut version = "5.3.6".parse::<Version>().unwrap();
4542 version.bump(BumpCommand::BumpPrerelease {
4543 kind: PrereleaseKind::Beta,
4544 value: None,
4545 });
4546 assert_eq!(version.to_string().as_str(), "5.3.6b1");
4547
4548 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4550 version.bump(BumpCommand::BumpPrerelease {
4551 kind: PrereleaseKind::Beta,
4552 value: None,
4553 });
4554 assert_eq!(version.to_string().as_str(), "1.2.3.4b1");
4555
4556 let mut version = "5!1.7.3.5a2.post345.dev456+local"
4558 .parse::<Version>()
4559 .unwrap();
4560 version.bump(BumpCommand::BumpPrerelease {
4561 kind: PrereleaseKind::Beta,
4562 value: None,
4563 });
4564 assert_eq!(version.to_string().as_str(), "5!1.7.3.5b1+local");
4565 version.bump(BumpCommand::BumpPrerelease {
4566 kind: PrereleaseKind::Beta,
4567 value: None,
4568 });
4569 assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2+local");
4570 }
4571
4572 #[test]
4575 fn bump_rc() {
4576 let mut version = "0".parse::<Version>().unwrap();
4578 version.bump(BumpCommand::BumpPrerelease {
4579 kind: PrereleaseKind::Rc,
4580 value: None,
4581 });
4582 assert_eq!(version.to_string().as_str(), "0rc1");
4583
4584 let mut version = "1.5".parse::<Version>().unwrap();
4586 version.bump(BumpCommand::BumpPrerelease {
4587 kind: PrereleaseKind::Rc,
4588 value: None,
4589 });
4590 assert_eq!(version.to_string().as_str(), "1.5rc1");
4591
4592 let mut version = "5.3.6".parse::<Version>().unwrap();
4594 version.bump(BumpCommand::BumpPrerelease {
4595 kind: PrereleaseKind::Rc,
4596 value: None,
4597 });
4598 assert_eq!(version.to_string().as_str(), "5.3.6rc1");
4599
4600 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4602 version.bump(BumpCommand::BumpPrerelease {
4603 kind: PrereleaseKind::Rc,
4604 value: None,
4605 });
4606 assert_eq!(version.to_string().as_str(), "1.2.3.4rc1");
4607
4608 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4610 .parse::<Version>()
4611 .unwrap();
4612 version.bump(BumpCommand::BumpPrerelease {
4613 kind: PrereleaseKind::Rc,
4614 value: None,
4615 });
4616 assert_eq!(version.to_string().as_str(), "5!1.7.3.5rc1+local");
4617 version.bump(BumpCommand::BumpPrerelease {
4618 kind: PrereleaseKind::Rc,
4619 value: None,
4620 });
4621 assert_eq!(version.to_string().as_str(), "5!1.7.3.5rc2+local");
4622 }
4623
4624 #[test]
4627 fn bump_post() {
4628 let mut version = "0".parse::<Version>().unwrap();
4630 version.bump(BumpCommand::BumpPost { value: None });
4631 assert_eq!(version.to_string().as_str(), "0.post1");
4632
4633 let mut version = "1.5".parse::<Version>().unwrap();
4635 version.bump(BumpCommand::BumpPost { value: None });
4636 assert_eq!(version.to_string().as_str(), "1.5.post1");
4637
4638 let mut version = "5.3.6".parse::<Version>().unwrap();
4640 version.bump(BumpCommand::BumpPost { value: None });
4641 assert_eq!(version.to_string().as_str(), "5.3.6.post1");
4642
4643 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4645 version.bump(BumpCommand::BumpPost { value: None });
4646 assert_eq!(version.to_string().as_str(), "1.2.3.4.post1");
4647
4648 let mut version = "5!1.7.3.5b2.dev123+local".parse::<Version>().unwrap();
4650 version.bump(BumpCommand::BumpPost { value: None });
4651 assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2.post1+local");
4652 version.bump(BumpCommand::BumpPost { value: None });
4653 assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2.post2+local");
4654 }
4655
4656 #[test]
4659 fn bump_dev() {
4660 let mut version = "0".parse::<Version>().unwrap();
4662 version.bump(BumpCommand::BumpDev { value: None });
4663 assert_eq!(version.to_string().as_str(), "0.dev1");
4664
4665 let mut version = "1.5".parse::<Version>().unwrap();
4667 version.bump(BumpCommand::BumpDev { value: None });
4668 assert_eq!(version.to_string().as_str(), "1.5.dev1");
4669
4670 let mut version = "5.3.6".parse::<Version>().unwrap();
4672 version.bump(BumpCommand::BumpDev { value: None });
4673 assert_eq!(version.to_string().as_str(), "5.3.6.dev1");
4674
4675 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4677 version.bump(BumpCommand::BumpDev { value: None });
4678 assert_eq!(version.to_string().as_str(), "1.2.3.4.dev1");
4679
4680 let mut version = "5!1.7.3.5b2.post345+local".parse::<Version>().unwrap();
4682 version.bump(BumpCommand::BumpDev { value: None });
4683 assert_eq!(
4684 version.to_string().as_str(),
4685 "5!1.7.3.5b2.post345.dev1+local"
4686 );
4687 version.bump(BumpCommand::BumpDev { value: None });
4688 assert_eq!(
4689 version.to_string().as_str(),
4690 "5!1.7.3.5b2.post345.dev2+local"
4691 );
4692 }
4693
4694 #[test]
4697 fn make_stable() {
4698 let mut version = "0".parse::<Version>().unwrap();
4700 version.bump(BumpCommand::MakeStable);
4701 assert_eq!(version.to_string().as_str(), "0");
4702
4703 let mut version = "1.5".parse::<Version>().unwrap();
4705 version.bump(BumpCommand::MakeStable);
4706 assert_eq!(version.to_string().as_str(), "1.5");
4707
4708 let mut version = "5.3.6".parse::<Version>().unwrap();
4710 version.bump(BumpCommand::MakeStable);
4711 assert_eq!(version.to_string().as_str(), "5.3.6");
4712
4713 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4715 version.bump(BumpCommand::MakeStable);
4716 assert_eq!(version.to_string().as_str(), "1.2.3.4");
4717
4718 let mut version = "5!1.7.3.5b2.post345+local".parse::<Version>().unwrap();
4720 version.bump(BumpCommand::MakeStable);
4721 assert_eq!(version.to_string().as_str(), "5!1.7.3.5+local");
4722 version.bump(BumpCommand::MakeStable);
4723 assert_eq!(version.to_string().as_str(), "5!1.7.3.5+local");
4724 }
4725}