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 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 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(crate) 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(crate) 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(crate) 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(crate) 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(crate) 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(crate) fn into_version(self) -> Version {
1622 self.version
1623 }
1624
1625 #[inline]
1627 pub(crate) 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 fn empty() -> Self {
1750 Self::Segments(Vec::new())
1751 }
1752
1753 fn is_empty(&self) -> bool {
1755 match self {
1756 Self::Segments(segments) => segments.is_empty(),
1757 Self::Max => false,
1758 }
1759 }
1760
1761 fn as_slice(&self) -> LocalVersionSlice<'_> {
1763 match self {
1764 Self::Segments(segments) => LocalVersionSlice::Segments(segments),
1765 Self::Max => LocalVersionSlice::Max,
1766 }
1767 }
1768}
1769
1770impl std::fmt::Display for LocalVersionSlice<'_> {
1775 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1776 match self {
1777 Self::Segments(segments) => {
1778 for (i, segment) in segments.iter().enumerate() {
1779 if i > 0 {
1780 write!(f, ".")?;
1781 }
1782 write!(f, "{segment}")?;
1783 }
1784 Ok(())
1785 }
1786 Self::Max => write!(f, "[max]"),
1787 }
1788 }
1789}
1790
1791impl CacheKey for LocalVersionSlice<'_> {
1792 fn cache_key(&self, state: &mut CacheKeyHasher) {
1793 match self {
1794 Self::Segments(segments) => {
1795 0u8.cache_key(state);
1796 segments.len().cache_key(state);
1797 for segment in *segments {
1798 segment.cache_key(state);
1799 }
1800 }
1801 Self::Max => {
1802 1u8.cache_key(state);
1803 }
1804 }
1805 }
1806}
1807
1808impl PartialOrd for LocalVersionSlice<'_> {
1809 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1810 Some(self.cmp(other))
1811 }
1812}
1813
1814impl Ord for LocalVersionSlice<'_> {
1815 fn cmp(&self, other: &Self) -> Ordering {
1816 match (self, other) {
1817 (LocalVersionSlice::Segments(lv1), LocalVersionSlice::Segments(lv2)) => lv1.cmp(lv2),
1818 (LocalVersionSlice::Segments(_), LocalVersionSlice::Max) => Ordering::Less,
1819 (LocalVersionSlice::Max, LocalVersionSlice::Segments(_)) => Ordering::Greater,
1820 (LocalVersionSlice::Max, LocalVersionSlice::Max) => Ordering::Equal,
1821 }
1822 }
1823}
1824
1825impl LocalVersionSlice<'_> {
1826 const fn empty() -> Self {
1828 Self::Segments(&[])
1829 }
1830
1831 pub fn is_empty(&self) -> bool {
1833 matches!(self, &Self::Segments(&[]))
1834 }
1835}
1836
1837#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1853#[cfg_attr(
1854 feature = "rkyv",
1855 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
1856)]
1857#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, Eq, PartialEq, PartialOrd, Ord)))]
1858pub enum LocalSegment {
1859 String(String),
1861 Number(u64),
1863}
1864
1865impl std::fmt::Display for LocalSegment {
1866 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1867 match self {
1868 Self::String(string) => write!(f, "{string}"),
1869 Self::Number(number) => write!(f, "{number}"),
1870 }
1871 }
1872}
1873
1874impl CacheKey for LocalSegment {
1875 fn cache_key(&self, state: &mut CacheKeyHasher) {
1876 match self {
1877 Self::String(string) => {
1878 0u8.cache_key(state);
1879 string.cache_key(state);
1880 }
1881 Self::Number(number) => {
1882 1u8.cache_key(state);
1883 number.cache_key(state);
1884 }
1885 }
1886 }
1887}
1888
1889impl PartialOrd for LocalSegment {
1890 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1891 Some(self.cmp(other))
1892 }
1893}
1894
1895impl Ord for LocalSegment {
1896 fn cmp(&self, other: &Self) -> Ordering {
1897 match (self, other) {
1899 (Self::Number(n1), Self::Number(n2)) => n1.cmp(n2),
1900 (Self::String(s1), Self::String(s2)) => s1.cmp(s2),
1901 (Self::Number(_), Self::String(_)) => Ordering::Greater,
1902 (Self::String(_), Self::Number(_)) => Ordering::Less,
1903 }
1904 }
1905}
1906
1907#[derive(Debug)]
1917struct Parser<'a> {
1918 v: &'a [u8],
1920 i: usize,
1922 epoch: u64,
1924 release: ReleaseNumbers,
1926 pre: Option<Prerelease>,
1928 post: Option<u64>,
1930 dev: Option<u64>,
1932 local: Vec<LocalSegment>,
1934 wildcard: bool,
1938}
1939
1940impl<'a> Parser<'a> {
1941 #[expect(clippy::byte_char_slices)]
1944 const SEPARATOR: ByteSet = ByteSet::new(&[b'.', b'_', b'-']);
1945
1946 fn new(version: &'a [u8]) -> Self {
1948 Parser {
1949 v: version,
1950 i: 0,
1951 epoch: 0,
1952 release: ReleaseNumbers::new(),
1953 pre: None,
1954 post: None,
1955 dev: None,
1956 local: vec![],
1957 wildcard: false,
1958 }
1959 }
1960
1961 fn parse(self) -> Result<Version, VersionParseError> {
1965 match self.parse_pattern() {
1966 Ok(vpat) => {
1967 if vpat.is_wildcard() {
1968 Err(ErrorKind::Wildcard.into())
1969 } else {
1970 Ok(vpat.into_version())
1971 }
1972 }
1973 Err(err) => match *err.kind {
1980 PatternErrorKind::Version(err) => Err(err),
1981 PatternErrorKind::WildcardNotTrailing => Err(ErrorKind::Wildcard.into()),
1982 },
1983 }
1984 }
1985
1986 fn parse_pattern(mut self) -> Result<VersionPattern, VersionPatternParseError> {
1988 if let Some(vpat) = self.parse_fast() {
1989 return Ok(vpat);
1990 }
1991 self.bump_while(|byte| byte.is_ascii_whitespace());
1992 self.bump_if("v");
1993 self.parse_epoch_and_initial_release()?;
1994 self.parse_rest_of_release()?;
1995 if self.parse_wildcard()? {
1996 return Ok(self.into_pattern());
1997 }
1998 self.parse_pre()?;
1999 self.parse_post()?;
2000 self.parse_dev()?;
2001 self.parse_local()?;
2002 self.bump_while(|byte| byte.is_ascii_whitespace());
2003 if !self.is_done() {
2004 let version = String::from_utf8_lossy(&self.v[..self.i]).into_owned();
2005 let remaining = String::from_utf8_lossy(&self.v[self.i..]).into_owned();
2006 return Err(ErrorKind::UnexpectedEnd { version, remaining }.into());
2007 }
2008 Ok(self.into_pattern())
2009 }
2010
2011 fn parse_fast(&self) -> Option<VersionPattern> {
2021 let (mut prev_digit, mut cur, mut release, mut len) = (false, 0u8, [0u8; 4], 0u8);
2022 for &byte in self.v {
2023 if byte == b'.' {
2024 if !prev_digit {
2025 return None;
2026 }
2027 prev_digit = false;
2028 *release.get_mut(usize::from(len))? = cur;
2029 len += 1;
2030 cur = 0;
2031 } else {
2032 let digit = byte.checked_sub(b'0')?;
2033 if digit > 9 {
2034 return None;
2035 }
2036 prev_digit = true;
2037 cur = cur.checked_mul(10)?.checked_add(digit)?;
2038 }
2039 }
2040 if !prev_digit {
2041 return None;
2042 }
2043 *release.get_mut(usize::from(len))? = cur;
2044 len += 1;
2045 let small = VersionSmall {
2046 _force_niche: NonZero::<u8>::MIN,
2047 repr: (u64::from(release[0]) << 48)
2048 | (u64::from(release[1]) << 40)
2049 | (u64::from(release[2]) << 32)
2050 | (u64::from(release[3]) << 24)
2051 | (VersionSmall::SUFFIX_NONE << VersionSmall::SUFFIX_VERSION_BIT_LEN),
2052
2053 len,
2054 };
2055 let inner = VersionInner::Small { small };
2056 let version = Version { inner };
2057 Some(VersionPattern {
2058 version,
2059 wildcard: false,
2060 })
2061 }
2062
2063 fn parse_epoch_and_initial_release(&mut self) -> Result<(), VersionPatternParseError> {
2074 let first_number = self.parse_number()?.ok_or(ErrorKind::NoLeadingNumber)?;
2075 let first_release_number = if self.bump_if("!") {
2076 self.epoch = first_number;
2077 self.parse_number()?
2078 .ok_or(ErrorKind::NoLeadingReleaseNumber)?
2079 } else {
2080 first_number
2081 };
2082 self.release.push(first_release_number);
2083 Ok(())
2084 }
2085
2086 fn parse_rest_of_release(&mut self) -> Result<(), VersionPatternParseError> {
2097 while self.bump_if(".") {
2098 let Some(n) = self.parse_number()? else {
2099 self.unbump();
2100 break;
2101 };
2102 self.release.push(n);
2103 }
2104 Ok(())
2105 }
2106
2107 fn parse_wildcard(&mut self) -> Result<bool, VersionPatternParseError> {
2116 if !self.bump_if(".*") {
2117 return Ok(false);
2118 }
2119 if !self.is_done() {
2120 return Err(PatternErrorKind::WildcardNotTrailing.into());
2121 }
2122 self.wildcard = true;
2123 Ok(true)
2124 }
2125
2126 fn parse_pre(&mut self) -> Result<(), VersionPatternParseError> {
2132 const SPELLINGS: StringSet =
2141 StringSet::new(&["alpha", "beta", "preview", "pre", "rc", "a", "b", "c"]);
2142 const MAP: &[PrereleaseKind] = &[
2143 PrereleaseKind::Alpha,
2144 PrereleaseKind::Beta,
2145 PrereleaseKind::Rc,
2146 PrereleaseKind::Rc,
2147 PrereleaseKind::Rc,
2148 PrereleaseKind::Alpha,
2149 PrereleaseKind::Beta,
2150 PrereleaseKind::Rc,
2151 ];
2152
2153 let oldpos = self.i;
2154 self.bump_if_byte_set(&Parser::SEPARATOR);
2155 let Some(spelling) = self.bump_if_string_set(&SPELLINGS) else {
2156 self.reset(oldpos);
2161 return Ok(());
2162 };
2163 let kind = MAP[spelling];
2164 self.bump_if_byte_set(&Parser::SEPARATOR);
2165 let number = self.parse_number()?.unwrap_or(0);
2168 self.pre = Some(Prerelease { kind, number });
2169 Ok(())
2170 }
2171
2172 fn parse_post(&mut self) -> Result<(), VersionPatternParseError> {
2178 const SPELLINGS: StringSet = StringSet::new(&["post", "rev", "r"]);
2179
2180 let oldpos = self.i;
2181 if self.bump_if("-") {
2182 if let Some(n) = self.parse_number()? {
2183 self.post = Some(n);
2184 return Ok(());
2185 }
2186 self.reset(oldpos);
2187 }
2188 self.bump_if_byte_set(&Parser::SEPARATOR);
2189 if self.bump_if_string_set(&SPELLINGS).is_none() {
2190 self.reset(oldpos);
2194 return Ok(());
2195 }
2196 self.bump_if_byte_set(&Parser::SEPARATOR);
2197 self.post = Some(self.parse_number()?.unwrap_or(0));
2200 Ok(())
2201 }
2202
2203 fn parse_dev(&mut self) -> Result<(), VersionPatternParseError> {
2209 let oldpos = self.i;
2210 self.bump_if_byte_set(&Parser::SEPARATOR);
2211 if !self.bump_if("dev") {
2212 self.reset(oldpos);
2216 return Ok(());
2217 }
2218 self.bump_if_byte_set(&Parser::SEPARATOR);
2219 self.dev = Some(self.parse_number()?.unwrap_or(0));
2222 Ok(())
2223 }
2224
2225 fn parse_local(&mut self) -> Result<(), VersionPatternParseError> {
2233 if !self.bump_if("+") {
2234 return Ok(());
2235 }
2236 let mut precursor = '+';
2237 loop {
2238 let first = self.bump_while(|byte| byte.is_ascii_alphanumeric());
2239 if first.is_empty() {
2240 return Err(ErrorKind::LocalEmpty { precursor }.into());
2241 }
2242 self.local.push(if let Ok(number) = parse_u64(first) {
2243 LocalSegment::Number(number)
2244 } else {
2245 let string = String::from_utf8(first.to_ascii_lowercase())
2246 .expect("ASCII alphanumerics are always valid UTF-8");
2247 LocalSegment::String(string)
2248 });
2249 let Some(byte) = self.bump_if_byte_set(&Parser::SEPARATOR) else {
2250 break;
2251 };
2252 precursor = char::from(byte);
2253 }
2254 Ok(())
2255 }
2256
2257 fn parse_number(&mut self) -> Result<Option<u64>, VersionPatternParseError> {
2265 let digits = self.bump_while(|ch| ch.is_ascii_digit());
2266 if digits.is_empty() {
2267 return Ok(None);
2268 }
2269 let n = parse_u64(digits)?;
2270 if n == u64::MAX {
2276 return Err(ErrorKind::NumberTooBig {
2277 bytes: digits.to_vec(),
2278 }
2279 .into());
2280 }
2281 Ok(Some(n))
2282 }
2283
2284 fn into_pattern(self) -> VersionPattern {
2292 assert!(
2293 self.release.len() > 0,
2294 "version with no release numbers is invalid"
2295 );
2296 let version = Version::new(self.release.as_slice())
2297 .with_epoch(self.epoch)
2298 .with_pre(self.pre)
2299 .with_post(self.post)
2300 .with_dev(self.dev)
2301 .with_local(LocalVersion::Segments(self.local));
2302 VersionPattern {
2303 version,
2304 wildcard: self.wildcard,
2305 }
2306 }
2307
2308 fn bump_while(&mut self, mut predicate: impl FnMut(u8) -> bool) -> &'a [u8] {
2315 let start = self.i;
2316 while !self.is_done() && predicate(self.byte()) {
2317 self.i = self.i.saturating_add(1);
2318 }
2319 &self.v[start..self.i]
2320 }
2321
2322 fn bump_if(&mut self, string: &str) -> bool {
2327 if self.is_done() {
2328 return false;
2329 }
2330 if starts_with_ignore_ascii_case(string.as_bytes(), &self.v[self.i..]) {
2331 self.i = self
2332 .i
2333 .checked_add(string.len())
2334 .expect("valid offset because of prefix");
2335 true
2336 } else {
2337 false
2338 }
2339 }
2340
2341 fn bump_if_string_set(&mut self, set: &StringSet) -> Option<usize> {
2345 let index = set.starts_with(&self.v[self.i..])?;
2346 let found = &set.strings[index];
2347 self.i = self
2348 .i
2349 .checked_add(found.len())
2350 .expect("valid offset because of prefix");
2351 Some(index)
2352 }
2353
2354 fn bump_if_byte_set(&mut self, set: &ByteSet) -> Option<u8> {
2358 let found = set.starts_with(&self.v[self.i..])?;
2359 self.i = self
2360 .i
2361 .checked_add(1)
2362 .expect("valid offset because of prefix");
2363 Some(found)
2364 }
2365
2366 fn unbump(&mut self) {
2375 self.i = self.i.checked_sub(1).expect("not at beginning of input");
2376 }
2377
2378 fn reset(&mut self, offset: usize) {
2384 assert!(offset <= self.v.len());
2385 self.i = offset;
2386 }
2387
2388 fn byte(&self) -> u8 {
2394 self.v[self.i]
2395 }
2396
2397 fn is_done(&self) -> bool {
2399 self.i >= self.v.len()
2400 }
2401}
2402
2403#[derive(Debug)]
2407enum ReleaseNumbers {
2408 Inline { numbers: [u64; 4], len: usize },
2409 Vec(Vec<u64>),
2410}
2411
2412impl ReleaseNumbers {
2413 fn new() -> Self {
2415 Self::Inline {
2416 numbers: [0; 4],
2417 len: 0,
2418 }
2419 }
2420
2421 fn push(&mut self, n: u64) {
2424 match *self {
2425 Self::Inline {
2426 ref mut numbers,
2427 ref mut len,
2428 } => {
2429 assert!(*len <= 4);
2430 if *len == 4 {
2431 let mut numbers = numbers.to_vec();
2432 numbers.push(n);
2433 *self = Self::Vec(numbers.clone());
2434 } else {
2435 numbers[*len] = n;
2436 *len += 1;
2437 }
2438 }
2439 Self::Vec(ref mut numbers) => {
2440 numbers.push(n);
2441 }
2442 }
2443 }
2444
2445 fn len(&self) -> usize {
2447 self.as_slice().len()
2448 }
2449
2450 fn as_slice(&self) -> &[u64] {
2452 match self {
2453 Self::Inline { numbers, len } => &numbers[..*len],
2454 Self::Vec(vec) => vec,
2455 }
2456 }
2457}
2458
2459struct StringSet {
2464 first_byte: ByteSet,
2468 strings: &'static [&'static str],
2470}
2471
2472impl StringSet {
2473 const fn new(strings: &'static [&'static str]) -> Self {
2479 assert!(
2480 strings.len() <= 20,
2481 "only a small number of strings are supported"
2482 );
2483 let (mut firsts, mut firsts_len) = ([0u8; 20], 0);
2484 let mut i = 0;
2485 while i < strings.len() {
2486 assert!(
2487 !strings[i].is_empty(),
2488 "every string in set should be non-empty",
2489 );
2490 firsts[firsts_len] = strings[i].as_bytes()[0];
2491 firsts_len += 1;
2492 i += 1;
2493 }
2494 let first_byte = ByteSet::new(&firsts);
2495 Self {
2496 first_byte,
2497 strings,
2498 }
2499 }
2500
2501 fn starts_with(&self, haystack: &[u8]) -> Option<usize> {
2504 let first_byte = self.first_byte.starts_with(haystack)?;
2505 for (i, &string) in self.strings.iter().enumerate() {
2506 let bytes = string.as_bytes();
2507 if bytes[0].eq_ignore_ascii_case(&first_byte)
2508 && starts_with_ignore_ascii_case(bytes, haystack)
2509 {
2510 return Some(i);
2511 }
2512 }
2513 None
2514 }
2515}
2516
2517struct ByteSet {
2519 set: [bool; 256],
2520}
2521
2522impl ByteSet {
2523 const fn new(bytes: &[u8]) -> Self {
2525 let mut set = [false; 256];
2526 let mut i = 0;
2527 while i < bytes.len() {
2528 set[bytes[i].to_ascii_uppercase() as usize] = true;
2529 set[bytes[i].to_ascii_lowercase() as usize] = true;
2530 i += 1;
2531 }
2532 Self { set }
2533 }
2534
2535 fn starts_with(&self, haystack: &[u8]) -> Option<u8> {
2538 let byte = *haystack.first()?;
2539 if self.contains(byte) {
2540 Some(byte)
2541 } else {
2542 None
2543 }
2544 }
2545
2546 fn contains(&self, byte: u8) -> bool {
2548 self.set[usize::from(byte)]
2549 }
2550}
2551
2552impl std::fmt::Debug for ByteSet {
2553 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2554 let mut set = f.debug_set();
2555 for byte in 0..=255 {
2556 if self.contains(byte) {
2557 set.entry(&char::from(byte));
2558 }
2559 }
2560 set.finish()
2561 }
2562}
2563
2564#[derive(Clone, Debug, Eq, PartialEq)]
2566pub struct VersionParseError {
2567 kind: Box<ErrorKind>,
2568}
2569
2570impl std::error::Error for VersionParseError {}
2571
2572impl std::fmt::Display for VersionParseError {
2573 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2574 match *self.kind {
2575 ErrorKind::Wildcard => write!(f, "wildcards are not allowed in a version"),
2576 ErrorKind::InvalidDigit { got } if got.is_ascii() => {
2577 write!(f, "expected ASCII digit, but found {:?}", char::from(got))
2578 }
2579 ErrorKind::InvalidDigit { got } => {
2580 write!(
2581 f,
2582 "expected ASCII digit, but found non-ASCII byte \\x{got:02X}"
2583 )
2584 }
2585 ErrorKind::NumberTooBig { ref bytes } => {
2586 let string = match std::str::from_utf8(bytes) {
2587 Ok(v) => v,
2588 Err(err) => {
2589 std::str::from_utf8(&bytes[..err.valid_up_to()]).expect("valid UTF-8")
2590 }
2591 };
2592 write!(
2593 f,
2594 "expected number less than or equal to {}, \
2595 but number found in {string:?} exceeds it",
2596 u64::MAX - 1,
2597 )
2598 }
2599 ErrorKind::NoLeadingNumber => {
2600 write!(
2601 f,
2602 "expected version to start with a number, \
2603 but no leading ASCII digits were found"
2604 )
2605 }
2606 ErrorKind::NoLeadingReleaseNumber => {
2607 write!(
2608 f,
2609 "expected version to have a non-empty release component after an epoch, \
2610 but no ASCII digits after the epoch were found"
2611 )
2612 }
2613 ErrorKind::LocalEmpty { precursor } => {
2614 write!(
2615 f,
2616 "found a `{precursor}` indicating the start of a local \
2617 component in a version, but did not find any alphanumeric \
2618 ASCII segment following the `{precursor}`",
2619 )
2620 }
2621 ErrorKind::UnexpectedEnd {
2622 ref version,
2623 ref remaining,
2624 } => {
2625 write!(
2626 f,
2627 "after parsing `{version}`, found `{remaining}`, \
2628 which is not part of a valid version",
2629 )
2630 }
2631 }
2632 }
2633}
2634
2635#[derive(Clone, Debug, Eq, PartialEq)]
2637pub(crate) enum ErrorKind {
2638 Wildcard,
2641 InvalidDigit {
2643 got: u8,
2645 },
2646 NumberTooBig {
2648 bytes: Vec<u8>,
2651 },
2652 NoLeadingNumber,
2654 NoLeadingReleaseNumber,
2656 LocalEmpty {
2660 precursor: char,
2663 },
2664 UnexpectedEnd {
2667 version: String,
2669 remaining: String,
2671 },
2672}
2673
2674impl From<ErrorKind> for VersionParseError {
2675 fn from(kind: ErrorKind) -> Self {
2676 Self {
2677 kind: Box::new(kind),
2678 }
2679 }
2680}
2681
2682#[derive(Clone, Debug, Eq, PartialEq)]
2684pub struct VersionPatternParseError {
2685 kind: Box<PatternErrorKind>,
2686}
2687
2688impl std::error::Error for VersionPatternParseError {}
2689
2690impl std::fmt::Display for VersionPatternParseError {
2691 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2692 match *self.kind {
2693 PatternErrorKind::Version(ref err) => err.fmt(f),
2694 PatternErrorKind::WildcardNotTrailing => {
2695 write!(f, "wildcards in versions must be at the end")
2696 }
2697 }
2698 }
2699}
2700
2701#[derive(Clone, Debug, Eq, PartialEq)]
2703pub(crate) enum PatternErrorKind {
2704 Version(VersionParseError),
2705 WildcardNotTrailing,
2706}
2707
2708impl From<PatternErrorKind> for VersionPatternParseError {
2709 fn from(kind: PatternErrorKind) -> Self {
2710 Self {
2711 kind: Box::new(kind),
2712 }
2713 }
2714}
2715
2716impl From<ErrorKind> for VersionPatternParseError {
2717 fn from(kind: ErrorKind) -> Self {
2718 Self::from(VersionParseError::from(kind))
2719 }
2720}
2721
2722impl From<VersionParseError> for VersionPatternParseError {
2723 fn from(err: VersionParseError) -> Self {
2724 Self {
2725 kind: Box::new(PatternErrorKind::Version(err)),
2726 }
2727 }
2728}
2729
2730pub(crate) fn compare_release(this: &[u64], other: &[u64]) -> Ordering {
2733 if this.len() == other.len() {
2734 return this.cmp(other);
2735 }
2736 for (this, other) in this.iter().chain(std::iter::repeat(&0)).zip(
2739 other
2740 .iter()
2741 .chain(std::iter::repeat(&0))
2742 .take(this.len().max(other.len())),
2743 ) {
2744 match this.cmp(other) {
2745 Ordering::Less => {
2746 return Ordering::Less;
2747 }
2748 Ordering::Equal => {}
2749 Ordering::Greater => {
2750 return Ordering::Greater;
2751 }
2752 }
2753 }
2754 Ordering::Equal
2755}
2756
2757fn sortable_tuple(version: &Version) -> (u64, u64, Option<u64>, u64, LocalVersionSlice<'_>) {
2773 let post = if version.max().is_some() {
2775 Some(u64::MAX)
2776 } else {
2777 version.post()
2778 };
2779 match (version.pre(), post, version.dev(), version.min()) {
2780 (_pre, post, _dev, Some(n)) => (0, 0, post, n, version.local()),
2782 (None, None, Some(n), None) => (1, 0, None, n, version.local()),
2784 (
2786 Some(Prerelease {
2787 kind: PrereleaseKind::Alpha,
2788 number: n,
2789 }),
2790 post,
2791 dev,
2792 None,
2793 ) => (2, n, post, dev.unwrap_or(u64::MAX), version.local()),
2794 (
2796 Some(Prerelease {
2797 kind: PrereleaseKind::Beta,
2798 number: n,
2799 }),
2800 post,
2801 dev,
2802 None,
2803 ) => (3, n, post, dev.unwrap_or(u64::MAX), version.local()),
2804 (
2806 Some(Prerelease {
2807 kind: PrereleaseKind::Rc,
2808 number: n,
2809 }),
2810 post,
2811 dev,
2812 None,
2813 ) => (4, n, post, dev.unwrap_or(u64::MAX), version.local()),
2814 (None, None, None, None) => (5, 0, None, 0, version.local()),
2816 (None, Some(post), dev, None) => {
2818 (6, 0, Some(post), dev.unwrap_or(u64::MAX), version.local())
2819 }
2820 }
2821}
2822
2823fn starts_with_ignore_ascii_case(needle: &[u8], haystack: &[u8]) -> bool {
2826 needle.len() <= haystack.len()
2827 && std::iter::zip(needle, haystack).all(|(b1, b2)| b1.eq_ignore_ascii_case(b2))
2828}
2829
2830fn parse_u64(bytes: &[u8]) -> Result<u64, VersionParseError> {
2845 let mut n: u64 = 0;
2846 for &byte in bytes {
2847 let digit = match byte.checked_sub(b'0') {
2848 None => return Err(ErrorKind::InvalidDigit { got: byte }.into()),
2849 Some(digit) if digit > 9 => return Err(ErrorKind::InvalidDigit { got: byte }.into()),
2850 Some(digit) => {
2851 debug_assert!((0..=9).contains(&digit));
2852 u64::from(digit)
2853 }
2854 };
2855 n = n
2856 .checked_mul(10)
2857 .and_then(|n| n.checked_add(digit))
2858 .ok_or_else(|| ErrorKind::NumberTooBig {
2859 bytes: bytes.to_vec(),
2860 })?;
2861 }
2862 Ok(n)
2863}
2864
2865pub static MIN_VERSION: LazyLock<Version> =
2867 LazyLock::new(|| Version::from_str("0a0.dev0").unwrap());
2868
2869#[cfg(test)]
2870mod tests {
2871 use std::str::FromStr;
2872
2873 use crate::VersionSpecifier;
2874
2875 use super::*;
2876
2877 #[test]
2879 fn test_packaging_versions() {
2880 let versions = [
2881 ("1.0.dev456", Version::new([1, 0]).with_dev(Some(456))),
2883 (
2884 "1.0a1",
2885 Version::new([1, 0]).with_pre(Some(Prerelease {
2886 kind: PrereleaseKind::Alpha,
2887 number: 1,
2888 })),
2889 ),
2890 (
2891 "1.0a2.dev456",
2892 Version::new([1, 0])
2893 .with_pre(Some(Prerelease {
2894 kind: PrereleaseKind::Alpha,
2895 number: 2,
2896 }))
2897 .with_dev(Some(456)),
2898 ),
2899 (
2900 "1.0a12.dev456",
2901 Version::new([1, 0])
2902 .with_pre(Some(Prerelease {
2903 kind: PrereleaseKind::Alpha,
2904 number: 12,
2905 }))
2906 .with_dev(Some(456)),
2907 ),
2908 (
2909 "1.0a12",
2910 Version::new([1, 0]).with_pre(Some(Prerelease {
2911 kind: PrereleaseKind::Alpha,
2912 number: 12,
2913 })),
2914 ),
2915 (
2916 "1.0b1.dev456",
2917 Version::new([1, 0])
2918 .with_pre(Some(Prerelease {
2919 kind: PrereleaseKind::Beta,
2920 number: 1,
2921 }))
2922 .with_dev(Some(456)),
2923 ),
2924 (
2925 "1.0b2",
2926 Version::new([1, 0]).with_pre(Some(Prerelease {
2927 kind: PrereleaseKind::Beta,
2928 number: 2,
2929 })),
2930 ),
2931 (
2932 "1.0b2.post345.dev456",
2933 Version::new([1, 0])
2934 .with_pre(Some(Prerelease {
2935 kind: PrereleaseKind::Beta,
2936 number: 2,
2937 }))
2938 .with_dev(Some(456))
2939 .with_post(Some(345)),
2940 ),
2941 (
2942 "1.0b2.post345",
2943 Version::new([1, 0])
2944 .with_pre(Some(Prerelease {
2945 kind: PrereleaseKind::Beta,
2946 number: 2,
2947 }))
2948 .with_post(Some(345)),
2949 ),
2950 (
2951 "1.0b2-346",
2952 Version::new([1, 0])
2953 .with_pre(Some(Prerelease {
2954 kind: PrereleaseKind::Beta,
2955 number: 2,
2956 }))
2957 .with_post(Some(346)),
2958 ),
2959 (
2960 "1.0c1.dev456",
2961 Version::new([1, 0])
2962 .with_pre(Some(Prerelease {
2963 kind: PrereleaseKind::Rc,
2964 number: 1,
2965 }))
2966 .with_dev(Some(456)),
2967 ),
2968 (
2969 "1.0c1",
2970 Version::new([1, 0]).with_pre(Some(Prerelease {
2971 kind: PrereleaseKind::Rc,
2972 number: 1,
2973 })),
2974 ),
2975 (
2976 "1.0rc2",
2977 Version::new([1, 0]).with_pre(Some(Prerelease {
2978 kind: PrereleaseKind::Rc,
2979 number: 2,
2980 })),
2981 ),
2982 (
2983 "1.0c3",
2984 Version::new([1, 0]).with_pre(Some(Prerelease {
2985 kind: PrereleaseKind::Rc,
2986 number: 3,
2987 })),
2988 ),
2989 ("1.0", Version::new([1, 0])),
2990 (
2991 "1.0.post456.dev34",
2992 Version::new([1, 0]).with_post(Some(456)).with_dev(Some(34)),
2993 ),
2994 ("1.0.post456", Version::new([1, 0]).with_post(Some(456))),
2995 ("1.1.dev1", Version::new([1, 1]).with_dev(Some(1))),
2996 (
2997 "1.2+123abc",
2998 Version::new([1, 2])
2999 .with_local_segments(vec![LocalSegment::String("123abc".to_string())]),
3000 ),
3001 (
3002 "1.2+123abc456",
3003 Version::new([1, 2])
3004 .with_local_segments(vec![LocalSegment::String("123abc456".to_string())]),
3005 ),
3006 (
3007 "1.2+abc",
3008 Version::new([1, 2])
3009 .with_local_segments(vec![LocalSegment::String("abc".to_string())]),
3010 ),
3011 (
3012 "1.2+abc123",
3013 Version::new([1, 2])
3014 .with_local_segments(vec![LocalSegment::String("abc123".to_string())]),
3015 ),
3016 (
3017 "1.2+abc123def",
3018 Version::new([1, 2])
3019 .with_local_segments(vec![LocalSegment::String("abc123def".to_string())]),
3020 ),
3021 (
3022 "1.2+1234.abc",
3023 Version::new([1, 2]).with_local_segments(vec![
3024 LocalSegment::Number(1234),
3025 LocalSegment::String("abc".to_string()),
3026 ]),
3027 ),
3028 (
3029 "1.2+123456",
3030 Version::new([1, 2]).with_local_segments(vec![LocalSegment::Number(123_456)]),
3031 ),
3032 (
3033 "1.2.r32+123456",
3034 Version::new([1, 2])
3035 .with_post(Some(32))
3036 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3037 ),
3038 (
3039 "1.2.rev33+123456",
3040 Version::new([1, 2])
3041 .with_post(Some(33))
3042 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3043 ),
3044 (
3046 "1!1.0.dev456",
3047 Version::new([1, 0]).with_epoch(1).with_dev(Some(456)),
3048 ),
3049 (
3050 "1!1.0a1",
3051 Version::new([1, 0])
3052 .with_epoch(1)
3053 .with_pre(Some(Prerelease {
3054 kind: PrereleaseKind::Alpha,
3055 number: 1,
3056 })),
3057 ),
3058 (
3059 "1!1.0a2.dev456",
3060 Version::new([1, 0])
3061 .with_epoch(1)
3062 .with_pre(Some(Prerelease {
3063 kind: PrereleaseKind::Alpha,
3064 number: 2,
3065 }))
3066 .with_dev(Some(456)),
3067 ),
3068 (
3069 "1!1.0a12.dev456",
3070 Version::new([1, 0])
3071 .with_epoch(1)
3072 .with_pre(Some(Prerelease {
3073 kind: PrereleaseKind::Alpha,
3074 number: 12,
3075 }))
3076 .with_dev(Some(456)),
3077 ),
3078 (
3079 "1!1.0a12",
3080 Version::new([1, 0])
3081 .with_epoch(1)
3082 .with_pre(Some(Prerelease {
3083 kind: PrereleaseKind::Alpha,
3084 number: 12,
3085 })),
3086 ),
3087 (
3088 "1!1.0b1.dev456",
3089 Version::new([1, 0])
3090 .with_epoch(1)
3091 .with_pre(Some(Prerelease {
3092 kind: PrereleaseKind::Beta,
3093 number: 1,
3094 }))
3095 .with_dev(Some(456)),
3096 ),
3097 (
3098 "1!1.0b2",
3099 Version::new([1, 0])
3100 .with_epoch(1)
3101 .with_pre(Some(Prerelease {
3102 kind: PrereleaseKind::Beta,
3103 number: 2,
3104 })),
3105 ),
3106 (
3107 "1!1.0b2.post345.dev456",
3108 Version::new([1, 0])
3109 .with_epoch(1)
3110 .with_pre(Some(Prerelease {
3111 kind: PrereleaseKind::Beta,
3112 number: 2,
3113 }))
3114 .with_post(Some(345))
3115 .with_dev(Some(456)),
3116 ),
3117 (
3118 "1!1.0b2.post345",
3119 Version::new([1, 0])
3120 .with_epoch(1)
3121 .with_pre(Some(Prerelease {
3122 kind: PrereleaseKind::Beta,
3123 number: 2,
3124 }))
3125 .with_post(Some(345)),
3126 ),
3127 (
3128 "1!1.0b2-346",
3129 Version::new([1, 0])
3130 .with_epoch(1)
3131 .with_pre(Some(Prerelease {
3132 kind: PrereleaseKind::Beta,
3133 number: 2,
3134 }))
3135 .with_post(Some(346)),
3136 ),
3137 (
3138 "1!1.0c1.dev456",
3139 Version::new([1, 0])
3140 .with_epoch(1)
3141 .with_pre(Some(Prerelease {
3142 kind: PrereleaseKind::Rc,
3143 number: 1,
3144 }))
3145 .with_dev(Some(456)),
3146 ),
3147 (
3148 "1!1.0c1",
3149 Version::new([1, 0])
3150 .with_epoch(1)
3151 .with_pre(Some(Prerelease {
3152 kind: PrereleaseKind::Rc,
3153 number: 1,
3154 })),
3155 ),
3156 (
3157 "1!1.0rc2",
3158 Version::new([1, 0])
3159 .with_epoch(1)
3160 .with_pre(Some(Prerelease {
3161 kind: PrereleaseKind::Rc,
3162 number: 2,
3163 })),
3164 ),
3165 (
3166 "1!1.0c3",
3167 Version::new([1, 0])
3168 .with_epoch(1)
3169 .with_pre(Some(Prerelease {
3170 kind: PrereleaseKind::Rc,
3171 number: 3,
3172 })),
3173 ),
3174 ("1!1.0", Version::new([1, 0]).with_epoch(1)),
3175 (
3176 "1!1.0.post456.dev34",
3177 Version::new([1, 0])
3178 .with_epoch(1)
3179 .with_post(Some(456))
3180 .with_dev(Some(34)),
3181 ),
3182 (
3183 "1!1.0.post456",
3184 Version::new([1, 0]).with_epoch(1).with_post(Some(456)),
3185 ),
3186 (
3187 "1!1.1.dev1",
3188 Version::new([1, 1]).with_epoch(1).with_dev(Some(1)),
3189 ),
3190 (
3191 "1!1.2+123abc",
3192 Version::new([1, 2])
3193 .with_epoch(1)
3194 .with_local_segments(vec![LocalSegment::String("123abc".to_string())]),
3195 ),
3196 (
3197 "1!1.2+123abc456",
3198 Version::new([1, 2])
3199 .with_epoch(1)
3200 .with_local_segments(vec![LocalSegment::String("123abc456".to_string())]),
3201 ),
3202 (
3203 "1!1.2+abc",
3204 Version::new([1, 2])
3205 .with_epoch(1)
3206 .with_local_segments(vec![LocalSegment::String("abc".to_string())]),
3207 ),
3208 (
3209 "1!1.2+abc123",
3210 Version::new([1, 2])
3211 .with_epoch(1)
3212 .with_local_segments(vec![LocalSegment::String("abc123".to_string())]),
3213 ),
3214 (
3215 "1!1.2+abc123def",
3216 Version::new([1, 2])
3217 .with_epoch(1)
3218 .with_local_segments(vec![LocalSegment::String("abc123def".to_string())]),
3219 ),
3220 (
3221 "1!1.2+1234.abc",
3222 Version::new([1, 2]).with_epoch(1).with_local_segments(vec![
3223 LocalSegment::Number(1234),
3224 LocalSegment::String("abc".to_string()),
3225 ]),
3226 ),
3227 (
3228 "1!1.2+123456",
3229 Version::new([1, 2])
3230 .with_epoch(1)
3231 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3232 ),
3233 (
3234 "1!1.2.r32+123456",
3235 Version::new([1, 2])
3236 .with_epoch(1)
3237 .with_post(Some(32))
3238 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3239 ),
3240 (
3241 "1!1.2.rev33+123456",
3242 Version::new([1, 2])
3243 .with_epoch(1)
3244 .with_post(Some(33))
3245 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3246 ),
3247 (
3248 "98765!1.2.rev33+123456",
3249 Version::new([1, 2])
3250 .with_epoch(98765)
3251 .with_post(Some(33))
3252 .with_local_segments(vec![LocalSegment::Number(123_456)]),
3253 ),
3254 ];
3255 for (string, structured) in versions {
3256 match Version::from_str(string) {
3257 Err(err) => {
3258 unreachable!(
3259 "expected {string:?} to parse as {structured:?}, but got {err:?}",
3260 structured = structured.as_bloated_debug(),
3261 )
3262 }
3263 Ok(v) => assert!(
3264 v == structured,
3265 "for {string:?}, expected {structured:?} but got {v:?}",
3266 structured = structured.as_bloated_debug(),
3267 v = v.as_bloated_debug(),
3268 ),
3269 }
3270 let spec = format!("=={string}");
3271 match VersionSpecifier::from_str(&spec) {
3272 Err(err) => {
3273 unreachable!(
3274 "expected version in {spec:?} to parse as {structured:?}, but got {err:?}",
3275 structured = structured.as_bloated_debug(),
3276 )
3277 }
3278 Ok(v) => assert!(
3279 v.version() == &structured,
3280 "for {string:?}, expected {structured:?} but got {v:?}",
3281 structured = structured.as_bloated_debug(),
3282 v = v.version.as_bloated_debug(),
3283 ),
3284 }
3285 }
3286 }
3287
3288 #[test]
3290 fn test_packaging_failures() {
3291 let versions = [
3292 "1.0+a+",
3294 "1.0++",
3295 "1.0+_foobar",
3296 "1.0+foo&asd",
3297 "1.0+1+1",
3298 "french toast",
3300 "==french toast",
3301 ];
3302 for version in versions {
3303 assert!(Version::from_str(version).is_err());
3304 assert!(VersionSpecifier::from_str(&format!("=={version}")).is_err());
3305 }
3306 }
3307
3308 #[test]
3309 fn test_equality_and_normalization() {
3310 let versions = [
3311 ("1.0dev", "1.0.dev0"),
3313 ("1.0.dev", "1.0.dev0"),
3314 ("1.0dev1", "1.0.dev1"),
3315 ("1.0dev", "1.0.dev0"),
3316 ("1.0-dev", "1.0.dev0"),
3317 ("1.0-dev1", "1.0.dev1"),
3318 ("1.0DEV", "1.0.dev0"),
3319 ("1.0.DEV", "1.0.dev0"),
3320 ("1.0DEV1", "1.0.dev1"),
3321 ("1.0DEV", "1.0.dev0"),
3322 ("1.0.DEV1", "1.0.dev1"),
3323 ("1.0-DEV", "1.0.dev0"),
3324 ("1.0-DEV1", "1.0.dev1"),
3325 ("1.0a", "1.0a0"),
3327 ("1.0.a", "1.0a0"),
3328 ("1.0.a1", "1.0a1"),
3329 ("1.0-a", "1.0a0"),
3330 ("1.0-a1", "1.0a1"),
3331 ("1.0alpha", "1.0a0"),
3332 ("1.0.alpha", "1.0a0"),
3333 ("1.0.alpha1", "1.0a1"),
3334 ("1.0-alpha", "1.0a0"),
3335 ("1.0-alpha1", "1.0a1"),
3336 ("1.0A", "1.0a0"),
3337 ("1.0.A", "1.0a0"),
3338 ("1.0.A1", "1.0a1"),
3339 ("1.0-A", "1.0a0"),
3340 ("1.0-A1", "1.0a1"),
3341 ("1.0ALPHA", "1.0a0"),
3342 ("1.0.ALPHA", "1.0a0"),
3343 ("1.0.ALPHA1", "1.0a1"),
3344 ("1.0-ALPHA", "1.0a0"),
3345 ("1.0-ALPHA1", "1.0a1"),
3346 ("1.0b", "1.0b0"),
3348 ("1.0.b", "1.0b0"),
3349 ("1.0.b1", "1.0b1"),
3350 ("1.0-b", "1.0b0"),
3351 ("1.0-b1", "1.0b1"),
3352 ("1.0beta", "1.0b0"),
3353 ("1.0.beta", "1.0b0"),
3354 ("1.0.beta1", "1.0b1"),
3355 ("1.0-beta", "1.0b0"),
3356 ("1.0-beta1", "1.0b1"),
3357 ("1.0B", "1.0b0"),
3358 ("1.0.B", "1.0b0"),
3359 ("1.0.B1", "1.0b1"),
3360 ("1.0-B", "1.0b0"),
3361 ("1.0-B1", "1.0b1"),
3362 ("1.0BETA", "1.0b0"),
3363 ("1.0.BETA", "1.0b0"),
3364 ("1.0.BETA1", "1.0b1"),
3365 ("1.0-BETA", "1.0b0"),
3366 ("1.0-BETA1", "1.0b1"),
3367 ("1.0c", "1.0rc0"),
3369 ("1.0.c", "1.0rc0"),
3370 ("1.0.c1", "1.0rc1"),
3371 ("1.0-c", "1.0rc0"),
3372 ("1.0-c1", "1.0rc1"),
3373 ("1.0rc", "1.0rc0"),
3374 ("1.0.rc", "1.0rc0"),
3375 ("1.0.rc1", "1.0rc1"),
3376 ("1.0-rc", "1.0rc0"),
3377 ("1.0-rc1", "1.0rc1"),
3378 ("1.0C", "1.0rc0"),
3379 ("1.0.C", "1.0rc0"),
3380 ("1.0.C1", "1.0rc1"),
3381 ("1.0-C", "1.0rc0"),
3382 ("1.0-C1", "1.0rc1"),
3383 ("1.0RC", "1.0rc0"),
3384 ("1.0.RC", "1.0rc0"),
3385 ("1.0.RC1", "1.0rc1"),
3386 ("1.0-RC", "1.0rc0"),
3387 ("1.0-RC1", "1.0rc1"),
3388 ("1.0post", "1.0.post0"),
3390 ("1.0.post", "1.0.post0"),
3391 ("1.0post1", "1.0.post1"),
3392 ("1.0post", "1.0.post0"),
3393 ("1.0-post", "1.0.post0"),
3394 ("1.0-post1", "1.0.post1"),
3395 ("1.0POST", "1.0.post0"),
3396 ("1.0.POST", "1.0.post0"),
3397 ("1.0POST1", "1.0.post1"),
3398 ("1.0POST", "1.0.post0"),
3399 ("1.0r", "1.0.post0"),
3400 ("1.0rev", "1.0.post0"),
3401 ("1.0.POST1", "1.0.post1"),
3402 ("1.0.r1", "1.0.post1"),
3403 ("1.0.rev1", "1.0.post1"),
3404 ("1.0-POST", "1.0.post0"),
3405 ("1.0-POST1", "1.0.post1"),
3406 ("1.0-5", "1.0.post5"),
3407 ("1.0-r5", "1.0.post5"),
3408 ("1.0-rev5", "1.0.post5"),
3409 ("1.0+AbC", "1.0+abc"),
3411 ("1.01", "1.1"),
3413 ("1.0a05", "1.0a5"),
3414 ("1.0b07", "1.0b7"),
3415 ("1.0c056", "1.0rc56"),
3416 ("1.0rc09", "1.0rc9"),
3417 ("1.0.post000", "1.0.post0"),
3418 ("1.1.dev09000", "1.1.dev9000"),
3419 ("00!1.2", "1.2"),
3420 ("0100!0.0", "100!0.0"),
3421 ("v1.0", "1.0"),
3423 (" v1.0\t\n", "1.0"),
3424 ];
3425 for (version_str, normalized_str) in versions {
3426 let version = Version::from_str(version_str).unwrap();
3427 let normalized = Version::from_str(normalized_str).unwrap();
3428 assert_eq!(version, normalized, "{version_str} {normalized_str}");
3430 assert_eq!(
3432 version.to_string(),
3433 normalized.to_string(),
3434 "{version_str} {normalized_str}"
3435 );
3436 }
3437 }
3438
3439 #[test]
3441 fn test_equality_and_normalization2() {
3442 let versions = [
3443 ("1.0.dev456", "1.0.dev456"),
3444 ("1.0a1", "1.0a1"),
3445 ("1.0a2.dev456", "1.0a2.dev456"),
3446 ("1.0a12.dev456", "1.0a12.dev456"),
3447 ("1.0a12", "1.0a12"),
3448 ("1.0b1.dev456", "1.0b1.dev456"),
3449 ("1.0b2", "1.0b2"),
3450 ("1.0b2.post345.dev456", "1.0b2.post345.dev456"),
3451 ("1.0b2.post345", "1.0b2.post345"),
3452 ("1.0rc1.dev456", "1.0rc1.dev456"),
3453 ("1.0rc1", "1.0rc1"),
3454 ("1.0", "1.0"),
3455 ("1.0.post456.dev34", "1.0.post456.dev34"),
3456 ("1.0.post456", "1.0.post456"),
3457 ("1.0.1", "1.0.1"),
3458 ("0!1.0.2", "1.0.2"),
3459 ("1.0.3+7", "1.0.3+7"),
3460 ("0!1.0.4+8.0", "1.0.4+8.0"),
3461 ("1.0.5+9.5", "1.0.5+9.5"),
3462 ("1.2+1234.abc", "1.2+1234.abc"),
3463 ("1.2+123456", "1.2+123456"),
3464 ("1.2+123abc", "1.2+123abc"),
3465 ("1.2+123abc456", "1.2+123abc456"),
3466 ("1.2+abc", "1.2+abc"),
3467 ("1.2+abc123", "1.2+abc123"),
3468 ("1.2+abc123def", "1.2+abc123def"),
3469 ("1.1.dev1", "1.1.dev1"),
3470 ("7!1.0.dev456", "7!1.0.dev456"),
3471 ("7!1.0a1", "7!1.0a1"),
3472 ("7!1.0a2.dev456", "7!1.0a2.dev456"),
3473 ("7!1.0a12.dev456", "7!1.0a12.dev456"),
3474 ("7!1.0a12", "7!1.0a12"),
3475 ("7!1.0b1.dev456", "7!1.0b1.dev456"),
3476 ("7!1.0b2", "7!1.0b2"),
3477 ("7!1.0b2.post345.dev456", "7!1.0b2.post345.dev456"),
3478 ("7!1.0b2.post345", "7!1.0b2.post345"),
3479 ("7!1.0rc1.dev456", "7!1.0rc1.dev456"),
3480 ("7!1.0rc1", "7!1.0rc1"),
3481 ("7!1.0", "7!1.0"),
3482 ("7!1.0.post456.dev34", "7!1.0.post456.dev34"),
3483 ("7!1.0.post456", "7!1.0.post456"),
3484 ("7!1.0.1", "7!1.0.1"),
3485 ("7!1.0.2", "7!1.0.2"),
3486 ("7!1.0.3+7", "7!1.0.3+7"),
3487 ("7!1.0.4+8.0", "7!1.0.4+8.0"),
3488 ("7!1.0.5+9.5", "7!1.0.5+9.5"),
3489 ("7!1.1.dev1", "7!1.1.dev1"),
3490 ];
3491 for (version_str, normalized_str) in versions {
3492 let version = Version::from_str(version_str).unwrap();
3493 let normalized = Version::from_str(normalized_str).unwrap();
3494 assert_eq!(version, normalized, "{version_str} {normalized_str}");
3495 assert_eq!(
3497 version.to_string(),
3498 normalized_str,
3499 "{version_str} {normalized_str}"
3500 );
3501 assert_eq!(
3503 version.to_string(),
3504 normalized.to_string(),
3505 "{version_str} {normalized_str}"
3506 );
3507 }
3508 }
3509
3510 #[test]
3511 fn test_star_fixed_version() {
3512 let result = Version::from_str("0.9.1.*");
3513 assert_eq!(result.unwrap_err(), ErrorKind::Wildcard.into());
3514 }
3515
3516 #[test]
3517 fn test_invalid_word() {
3518 let result = Version::from_str("blergh");
3519 assert_eq!(result.unwrap_err(), ErrorKind::NoLeadingNumber.into());
3520 }
3521
3522 #[test]
3523 fn test_from_version_star() {
3524 let p = |s: &str| -> Result<VersionPattern, _> { s.parse() };
3525 assert!(!p("1.2.3").unwrap().is_wildcard());
3526 assert!(p("1.2.3.*").unwrap().is_wildcard());
3527 assert_eq!(
3528 p("1.2.*.4.*").unwrap_err(),
3529 PatternErrorKind::WildcardNotTrailing.into(),
3530 );
3531 assert_eq!(
3532 p("1.0-dev1.*").unwrap_err(),
3533 ErrorKind::UnexpectedEnd {
3534 version: "1.0-dev1".to_string(),
3535 remaining: ".*".to_string()
3536 }
3537 .into(),
3538 );
3539 assert_eq!(
3540 p("1.0a1.*").unwrap_err(),
3541 ErrorKind::UnexpectedEnd {
3542 version: "1.0a1".to_string(),
3543 remaining: ".*".to_string()
3544 }
3545 .into(),
3546 );
3547 assert_eq!(
3548 p("1.0.post1.*").unwrap_err(),
3549 ErrorKind::UnexpectedEnd {
3550 version: "1.0.post1".to_string(),
3551 remaining: ".*".to_string()
3552 }
3553 .into(),
3554 );
3555 assert_eq!(
3556 p("1.0+lolwat.*").unwrap_err(),
3557 ErrorKind::LocalEmpty { precursor: '.' }.into(),
3558 );
3559 }
3560
3561 #[test]
3567 fn parse_version_valid() {
3568 let p = |s: &str| match Parser::new(s.as_bytes()).parse() {
3569 Ok(v) => v,
3570 Err(err) => unreachable!("expected valid version, but got error: {err:?}"),
3571 };
3572
3573 assert_eq!(p("5"), Version::new([5]));
3575 assert_eq!(p("5.6"), Version::new([5, 6]));
3576 assert_eq!(p("5.6.7"), Version::new([5, 6, 7]));
3577 assert_eq!(p("512.623.734"), Version::new([512, 623, 734]));
3578 assert_eq!(p("1.2.3.4"), Version::new([1, 2, 3, 4]));
3579 assert_eq!(p("1.2.3.4.5"), Version::new([1, 2, 3, 4, 5]));
3580
3581 assert_eq!(p("4!5"), Version::new([5]).with_epoch(4));
3583 assert_eq!(p("4!5.6"), Version::new([5, 6]).with_epoch(4));
3584
3585 assert_eq!(
3587 p("5a1"),
3588 Version::new([5]).with_pre(Some(Prerelease {
3589 kind: PrereleaseKind::Alpha,
3590 number: 1
3591 }))
3592 );
3593 assert_eq!(
3594 p("5alpha1"),
3595 Version::new([5]).with_pre(Some(Prerelease {
3596 kind: PrereleaseKind::Alpha,
3597 number: 1
3598 }))
3599 );
3600 assert_eq!(
3601 p("5b1"),
3602 Version::new([5]).with_pre(Some(Prerelease {
3603 kind: PrereleaseKind::Beta,
3604 number: 1
3605 }))
3606 );
3607 assert_eq!(
3608 p("5beta1"),
3609 Version::new([5]).with_pre(Some(Prerelease {
3610 kind: PrereleaseKind::Beta,
3611 number: 1
3612 }))
3613 );
3614 assert_eq!(
3615 p("5rc1"),
3616 Version::new([5]).with_pre(Some(Prerelease {
3617 kind: PrereleaseKind::Rc,
3618 number: 1
3619 }))
3620 );
3621 assert_eq!(
3622 p("5c1"),
3623 Version::new([5]).with_pre(Some(Prerelease {
3624 kind: PrereleaseKind::Rc,
3625 number: 1
3626 }))
3627 );
3628 assert_eq!(
3629 p("5preview1"),
3630 Version::new([5]).with_pre(Some(Prerelease {
3631 kind: PrereleaseKind::Rc,
3632 number: 1
3633 }))
3634 );
3635 assert_eq!(
3636 p("5pre1"),
3637 Version::new([5]).with_pre(Some(Prerelease {
3638 kind: PrereleaseKind::Rc,
3639 number: 1
3640 }))
3641 );
3642 assert_eq!(
3643 p("5.6.7pre1"),
3644 Version::new([5, 6, 7]).with_pre(Some(Prerelease {
3645 kind: PrereleaseKind::Rc,
3646 number: 1
3647 }))
3648 );
3649 assert_eq!(
3650 p("5alpha789"),
3651 Version::new([5]).with_pre(Some(Prerelease {
3652 kind: PrereleaseKind::Alpha,
3653 number: 789
3654 }))
3655 );
3656 assert_eq!(
3657 p("5.alpha789"),
3658 Version::new([5]).with_pre(Some(Prerelease {
3659 kind: PrereleaseKind::Alpha,
3660 number: 789
3661 }))
3662 );
3663 assert_eq!(
3664 p("5-alpha789"),
3665 Version::new([5]).with_pre(Some(Prerelease {
3666 kind: PrereleaseKind::Alpha,
3667 number: 789
3668 }))
3669 );
3670 assert_eq!(
3671 p("5_alpha789"),
3672 Version::new([5]).with_pre(Some(Prerelease {
3673 kind: PrereleaseKind::Alpha,
3674 number: 789
3675 }))
3676 );
3677 assert_eq!(
3678 p("5alpha.789"),
3679 Version::new([5]).with_pre(Some(Prerelease {
3680 kind: PrereleaseKind::Alpha,
3681 number: 789
3682 }))
3683 );
3684 assert_eq!(
3685 p("5alpha-789"),
3686 Version::new([5]).with_pre(Some(Prerelease {
3687 kind: PrereleaseKind::Alpha,
3688 number: 789
3689 }))
3690 );
3691 assert_eq!(
3692 p("5alpha_789"),
3693 Version::new([5]).with_pre(Some(Prerelease {
3694 kind: PrereleaseKind::Alpha,
3695 number: 789
3696 }))
3697 );
3698 assert_eq!(
3699 p("5ALPHA789"),
3700 Version::new([5]).with_pre(Some(Prerelease {
3701 kind: PrereleaseKind::Alpha,
3702 number: 789
3703 }))
3704 );
3705 assert_eq!(
3706 p("5aLpHa789"),
3707 Version::new([5]).with_pre(Some(Prerelease {
3708 kind: PrereleaseKind::Alpha,
3709 number: 789
3710 }))
3711 );
3712 assert_eq!(
3713 p("5alpha"),
3714 Version::new([5]).with_pre(Some(Prerelease {
3715 kind: PrereleaseKind::Alpha,
3716 number: 0
3717 }))
3718 );
3719
3720 assert_eq!(p("5post2"), Version::new([5]).with_post(Some(2)));
3722 assert_eq!(p("5rev2"), Version::new([5]).with_post(Some(2)));
3723 assert_eq!(p("5r2"), Version::new([5]).with_post(Some(2)));
3724 assert_eq!(p("5.post2"), Version::new([5]).with_post(Some(2)));
3725 assert_eq!(p("5-post2"), Version::new([5]).with_post(Some(2)));
3726 assert_eq!(p("5_post2"), Version::new([5]).with_post(Some(2)));
3727 assert_eq!(p("5.post.2"), Version::new([5]).with_post(Some(2)));
3728 assert_eq!(p("5.post-2"), Version::new([5]).with_post(Some(2)));
3729 assert_eq!(p("5.post_2"), Version::new([5]).with_post(Some(2)));
3730 assert_eq!(
3731 p("5.6.7.post_2"),
3732 Version::new([5, 6, 7]).with_post(Some(2))
3733 );
3734 assert_eq!(p("5-2"), Version::new([5]).with_post(Some(2)));
3735 assert_eq!(p("5.6.7-2"), Version::new([5, 6, 7]).with_post(Some(2)));
3736 assert_eq!(p("5POST2"), Version::new([5]).with_post(Some(2)));
3737 assert_eq!(p("5PoSt2"), Version::new([5]).with_post(Some(2)));
3738 assert_eq!(p("5post"), Version::new([5]).with_post(Some(0)));
3739
3740 assert_eq!(p("5dev2"), Version::new([5]).with_dev(Some(2)));
3742 assert_eq!(p("5.dev2"), Version::new([5]).with_dev(Some(2)));
3743 assert_eq!(p("5-dev2"), Version::new([5]).with_dev(Some(2)));
3744 assert_eq!(p("5_dev2"), Version::new([5]).with_dev(Some(2)));
3745 assert_eq!(p("5.dev.2"), Version::new([5]).with_dev(Some(2)));
3746 assert_eq!(p("5.dev-2"), Version::new([5]).with_dev(Some(2)));
3747 assert_eq!(p("5.dev_2"), Version::new([5]).with_dev(Some(2)));
3748 assert_eq!(p("5.6.7.dev_2"), Version::new([5, 6, 7]).with_dev(Some(2)));
3749 assert_eq!(p("5DEV2"), Version::new([5]).with_dev(Some(2)));
3750 assert_eq!(p("5dEv2"), Version::new([5]).with_dev(Some(2)));
3751 assert_eq!(p("5DeV2"), Version::new([5]).with_dev(Some(2)));
3752 assert_eq!(p("5dev"), Version::new([5]).with_dev(Some(0)));
3753
3754 assert_eq!(
3756 p("5+2"),
3757 Version::new([5]).with_local_segments(vec![LocalSegment::Number(2)])
3758 );
3759 assert_eq!(
3760 p("5+a"),
3761 Version::new([5]).with_local_segments(vec![LocalSegment::String("a".to_string())])
3762 );
3763 assert_eq!(
3764 p("5+abc.123"),
3765 Version::new([5]).with_local_segments(vec![
3766 LocalSegment::String("abc".to_string()),
3767 LocalSegment::Number(123),
3768 ])
3769 );
3770 assert_eq!(
3771 p("5+123.abc"),
3772 Version::new([5]).with_local_segments(vec![
3773 LocalSegment::Number(123),
3774 LocalSegment::String("abc".to_string()),
3775 ])
3776 );
3777 assert_eq!(
3778 p("5+18446744073709551615.abc"),
3779 Version::new([5]).with_local_segments(vec![
3780 LocalSegment::Number(18_446_744_073_709_551_615),
3781 LocalSegment::String("abc".to_string()),
3782 ])
3783 );
3784 assert_eq!(
3785 p("5+18446744073709551616.abc"),
3786 Version::new([5]).with_local_segments(vec![
3787 LocalSegment::String("18446744073709551616".to_string()),
3788 LocalSegment::String("abc".to_string()),
3789 ])
3790 );
3791 assert_eq!(
3792 p("5+ABC.123"),
3793 Version::new([5]).with_local_segments(vec![
3794 LocalSegment::String("abc".to_string()),
3795 LocalSegment::Number(123),
3796 ])
3797 );
3798 assert_eq!(
3799 p("5+ABC-123.4_5_xyz-MNO"),
3800 Version::new([5]).with_local_segments(vec![
3801 LocalSegment::String("abc".to_string()),
3802 LocalSegment::Number(123),
3803 LocalSegment::Number(4),
3804 LocalSegment::Number(5),
3805 LocalSegment::String("xyz".to_string()),
3806 LocalSegment::String("mno".to_string()),
3807 ])
3808 );
3809 assert_eq!(
3810 p("5.6.7+abc-00123"),
3811 Version::new([5, 6, 7]).with_local_segments(vec![
3812 LocalSegment::String("abc".to_string()),
3813 LocalSegment::Number(123),
3814 ])
3815 );
3816 assert_eq!(
3817 p("5.6.7+abc-foo00123"),
3818 Version::new([5, 6, 7]).with_local_segments(vec![
3819 LocalSegment::String("abc".to_string()),
3820 LocalSegment::String("foo00123".to_string()),
3821 ])
3822 );
3823 assert_eq!(
3824 p("5.6.7+abc-00123a"),
3825 Version::new([5, 6, 7]).with_local_segments(vec![
3826 LocalSegment::String("abc".to_string()),
3827 LocalSegment::String("00123a".to_string()),
3828 ])
3829 );
3830
3831 assert_eq!(
3833 p("5a2post3"),
3834 Version::new([5])
3835 .with_pre(Some(Prerelease {
3836 kind: PrereleaseKind::Alpha,
3837 number: 2
3838 }))
3839 .with_post(Some(3))
3840 );
3841 assert_eq!(
3842 p("5.a-2_post-3"),
3843 Version::new([5])
3844 .with_pre(Some(Prerelease {
3845 kind: PrereleaseKind::Alpha,
3846 number: 2
3847 }))
3848 .with_post(Some(3))
3849 );
3850 assert_eq!(
3851 p("5a2-3"),
3852 Version::new([5])
3853 .with_pre(Some(Prerelease {
3854 kind: PrereleaseKind::Alpha,
3855 number: 2
3856 }))
3857 .with_post(Some(3))
3858 );
3859
3860 assert_eq!(p("v5"), Version::new([5]));
3862 assert_eq!(p("V5"), Version::new([5]));
3863 assert_eq!(p("v5.6.7"), Version::new([5, 6, 7]));
3864
3865 assert_eq!(p(" v5 "), Version::new([5]));
3867 assert_eq!(p(" 5 "), Version::new([5]));
3868 assert_eq!(
3869 p(" 5.6.7+abc.123.xyz "),
3870 Version::new([5, 6, 7]).with_local_segments(vec![
3871 LocalSegment::String("abc".to_string()),
3872 LocalSegment::Number(123),
3873 LocalSegment::String("xyz".to_string())
3874 ])
3875 );
3876 assert_eq!(p(" \n5\n \t"), Version::new([5]));
3877
3878 assert!(Parser::new("1.min0".as_bytes()).parse().is_err());
3880 }
3881
3882 #[test]
3890 fn parse_version_invalid() {
3891 let p = |s: &str| match Parser::new(s.as_bytes()).parse() {
3892 Err(err) => err,
3893 Ok(v) => unreachable!(
3894 "expected version parser error, but got: {v:?}",
3895 v = v.as_bloated_debug()
3896 ),
3897 };
3898
3899 assert_eq!(p(""), ErrorKind::NoLeadingNumber.into());
3900 assert_eq!(p("a"), ErrorKind::NoLeadingNumber.into());
3901 assert_eq!(p("v 5"), ErrorKind::NoLeadingNumber.into());
3902 assert_eq!(p("V 5"), ErrorKind::NoLeadingNumber.into());
3903 assert_eq!(p("x 5"), ErrorKind::NoLeadingNumber.into());
3904 assert_eq!(
3905 p("18446744073709551616"),
3906 ErrorKind::NumberTooBig {
3907 bytes: b"18446744073709551616".to_vec()
3908 }
3909 .into()
3910 );
3911 assert_eq!(p("5!"), ErrorKind::NoLeadingReleaseNumber.into());
3912 assert_eq!(
3913 p("5.6./"),
3914 ErrorKind::UnexpectedEnd {
3915 version: "5.6".to_string(),
3916 remaining: "./".to_string()
3917 }
3918 .into()
3919 );
3920 assert_eq!(
3921 p("5.6.-alpha2"),
3922 ErrorKind::UnexpectedEnd {
3923 version: "5.6".to_string(),
3924 remaining: ".-alpha2".to_string()
3925 }
3926 .into()
3927 );
3928 assert_eq!(
3929 p("1.2.3a18446744073709551616"),
3930 ErrorKind::NumberTooBig {
3931 bytes: b"18446744073709551616".to_vec()
3932 }
3933 .into()
3934 );
3935 assert_eq!(p("5+"), ErrorKind::LocalEmpty { precursor: '+' }.into());
3936 assert_eq!(p("5+ "), ErrorKind::LocalEmpty { precursor: '+' }.into());
3937 assert_eq!(p("5+abc."), ErrorKind::LocalEmpty { precursor: '.' }.into());
3938 assert_eq!(p("5+abc-"), ErrorKind::LocalEmpty { precursor: '-' }.into());
3939 assert_eq!(p("5+abc_"), ErrorKind::LocalEmpty { precursor: '_' }.into());
3940 assert_eq!(
3941 p("5+abc. "),
3942 ErrorKind::LocalEmpty { precursor: '.' }.into()
3943 );
3944 assert_eq!(
3945 p("5.6-"),
3946 ErrorKind::UnexpectedEnd {
3947 version: "5.6".to_string(),
3948 remaining: "-".to_string()
3949 }
3950 .into()
3951 );
3952 }
3953
3954 #[test]
3955 fn parse_version_pattern_valid() {
3956 let p = |s: &str| match Parser::new(s.as_bytes()).parse_pattern() {
3957 Ok(v) => v,
3958 Err(err) => unreachable!("expected valid version, but got error: {err:?}"),
3959 };
3960
3961 assert_eq!(p("5.*"), VersionPattern::wildcard(Version::new([5])));
3962 assert_eq!(p("5.6.*"), VersionPattern::wildcard(Version::new([5, 6])));
3963 assert_eq!(
3964 p("2!5.6.*"),
3965 VersionPattern::wildcard(Version::new([5, 6]).with_epoch(2))
3966 );
3967 }
3968
3969 #[test]
3970 fn parse_version_pattern_invalid() {
3971 let p = |s: &str| match Parser::new(s.as_bytes()).parse_pattern() {
3972 Err(err) => err,
3973 Ok(vpat) => unreachable!("expected version pattern parser error, but got: {vpat:?}"),
3974 };
3975
3976 assert_eq!(p("*"), ErrorKind::NoLeadingNumber.into());
3977 assert_eq!(p("2!*"), ErrorKind::NoLeadingReleaseNumber.into());
3978 }
3979
3980 #[test]
3985 fn ordering() {
3986 let versions = &[
3987 "1.dev0",
3988 "1.0.dev456",
3989 "1.0a1",
3990 "1.0a2.dev456",
3991 "1.0a12.dev456",
3992 "1.0a12",
3993 "1.0b1.dev456",
3994 "1.0b2",
3995 "1.0b2.post345.dev456",
3996 "1.0b2.post345",
3997 "1.0rc1.dev456",
3998 "1.0rc1",
3999 "1.0",
4000 "1.0+abc.5",
4001 "1.0+abc.7",
4002 "1.0+5",
4003 "1.0.post456.dev34",
4004 "1.0.post456",
4005 "1.0.15",
4006 "1.1.dev1",
4007 ];
4008 for (i, v1) in versions.iter().enumerate() {
4009 for v2 in &versions[i + 1..] {
4010 let less = v1.parse::<Version>().unwrap();
4011 let greater = v2.parse::<Version>().unwrap();
4012 assert_eq!(
4013 less.cmp(&greater),
4014 Ordering::Less,
4015 "less: {:?}\ngreater: {:?}",
4016 less.as_bloated_debug(),
4017 greater.as_bloated_debug()
4018 );
4019 }
4020 }
4021 }
4022
4023 #[test]
4024 fn local_sentinel_version() {
4025 let sentinel = Version::new([1, 0]).with_local(LocalVersion::Max);
4026
4027 let versions = &["1.0.post0", "1.1"];
4029
4030 for greater in versions {
4031 let greater = greater.parse::<Version>().unwrap();
4032 assert_eq!(
4033 sentinel.cmp(&greater),
4034 Ordering::Less,
4035 "less: {:?}\ngreater: {:?}",
4036 greater.as_bloated_debug(),
4037 sentinel.as_bloated_debug(),
4038 );
4039 }
4040
4041 let versions = &["1.0", "1.0.a0", "1.0+local"];
4043
4044 for less in versions {
4045 let less = less.parse::<Version>().unwrap();
4046 assert_eq!(
4047 sentinel.cmp(&less),
4048 Ordering::Greater,
4049 "less: {:?}\ngreater: {:?}",
4050 sentinel.as_bloated_debug(),
4051 less.as_bloated_debug()
4052 );
4053 }
4054 }
4055
4056 #[test]
4057 fn min_version() {
4058 let less = Version::new([1, 0]).with_min(Some(0));
4060
4061 let versions = &[
4062 "1.dev0",
4063 "1.0.dev456",
4064 "1.0a1",
4065 "1.0a2.dev456",
4066 "1.0a12.dev456",
4067 "1.0a12",
4068 "1.0b1.dev456",
4069 "1.0b2",
4070 "1.0b2.post345.dev456",
4071 "1.0b2.post345",
4072 "1.0rc1.dev456",
4073 "1.0rc1",
4074 "1.0",
4075 "1.0+abc.5",
4076 "1.0+abc.7",
4077 "1.0+5",
4078 "1.0.post456.dev34",
4079 "1.0.post456",
4080 "1.0.15",
4081 "1.1.dev1",
4082 ];
4083
4084 for greater in versions {
4085 let greater = greater.parse::<Version>().unwrap();
4086 assert_eq!(
4087 less.cmp(&greater),
4088 Ordering::Less,
4089 "less: {:?}\ngreater: {:?}",
4090 less.as_bloated_debug(),
4091 greater.as_bloated_debug()
4092 );
4093 }
4094 }
4095
4096 #[test]
4097 fn max_version() {
4098 let greater = Version::new([1, 0]).with_max(Some(0));
4100
4101 let versions = &[
4102 "1.dev0",
4103 "1.0.dev456",
4104 "1.0a1",
4105 "1.0a2.dev456",
4106 "1.0a12.dev456",
4107 "1.0a12",
4108 "1.0b1.dev456",
4109 "1.0b2",
4110 "1.0b2.post345.dev456",
4111 "1.0b2.post345",
4112 "1.0rc1.dev456",
4113 "1.0rc1",
4114 "1.0",
4115 "1.0+abc.5",
4116 "1.0+abc.7",
4117 "1.0+5",
4118 "1.0.post456.dev34",
4119 "1.0.post456",
4120 "1.0",
4121 ];
4122
4123 for less in versions {
4124 let less = less.parse::<Version>().unwrap();
4125 assert_eq!(
4126 less.cmp(&greater),
4127 Ordering::Less,
4128 "less: {:?}\ngreater: {:?}",
4129 less.as_bloated_debug(),
4130 greater.as_bloated_debug()
4131 );
4132 }
4133
4134 let greater = Version::new([1, 0])
4136 .with_pre(Some(Prerelease {
4137 kind: PrereleaseKind::Alpha,
4138 number: 1,
4139 }))
4140 .with_max(Some(0));
4141
4142 let versions = &["1.0a1", "1.0a1+local", "1.0a1.post1"];
4143
4144 for less in versions {
4145 let less = less.parse::<Version>().unwrap();
4146 assert_eq!(
4147 less.cmp(&greater),
4148 Ordering::Less,
4149 "less: {:?}\ngreater: {:?}",
4150 less.as_bloated_debug(),
4151 greater.as_bloated_debug()
4152 );
4153 }
4154
4155 let less = Version::new([1, 0])
4157 .with_pre(Some(Prerelease {
4158 kind: PrereleaseKind::Alpha,
4159 number: 1,
4160 }))
4161 .with_max(Some(0));
4162
4163 let versions = &["1.0b1", "1.0b1+local", "1.0b1.post1", "1.0"];
4164
4165 for greater in versions {
4166 let greater = greater.parse::<Version>().unwrap();
4167 assert_eq!(
4168 less.cmp(&greater),
4169 Ordering::Less,
4170 "less: {:?}\ngreater: {:?}",
4171 less.as_bloated_debug(),
4172 greater.as_bloated_debug()
4173 );
4174 }
4175 }
4176
4177 #[test]
4179 fn parse_number_u64() {
4180 let p = |s: &str| parse_u64(s.as_bytes());
4181 assert_eq!(p("0"), Ok(0));
4182 assert_eq!(p("00"), Ok(0));
4183 assert_eq!(p("1"), Ok(1));
4184 assert_eq!(p("01"), Ok(1));
4185 assert_eq!(p("9"), Ok(9));
4186 assert_eq!(p("10"), Ok(10));
4187 assert_eq!(p("18446744073709551615"), Ok(18_446_744_073_709_551_615));
4188 assert_eq!(p("018446744073709551615"), Ok(18_446_744_073_709_551_615));
4189 assert_eq!(
4190 p("000000018446744073709551615"),
4191 Ok(18_446_744_073_709_551_615)
4192 );
4193
4194 assert_eq!(p("10a"), Err(ErrorKind::InvalidDigit { got: b'a' }.into()));
4195 assert_eq!(p("10["), Err(ErrorKind::InvalidDigit { got: b'[' }.into()));
4196 assert_eq!(p("10/"), Err(ErrorKind::InvalidDigit { got: b'/' }.into()));
4197 assert_eq!(
4199 p("18446744073709551616"),
4200 Err(ErrorKind::NumberTooBig {
4201 bytes: b"18446744073709551616".to_vec()
4202 }
4203 .into())
4204 );
4205 assert_eq!(
4206 p("18446744073799551615abc"),
4207 Err(ErrorKind::NumberTooBig {
4208 bytes: b"18446744073799551615abc".to_vec()
4209 }
4210 .into())
4211 );
4212 assert_eq!(
4213 parse_u64(b"18446744073799551615\xFF"),
4214 Err(ErrorKind::NumberTooBig {
4215 bytes: b"18446744073799551615\xFF".to_vec()
4216 }
4217 .into())
4218 );
4219 }
4220
4221 impl Version {
4222 pub(crate) fn as_bloated_debug(&self) -> impl std::fmt::Debug + '_ {
4232 std::fmt::from_fn(|f| {
4233 f.debug_struct("Version")
4234 .field("epoch", &self.epoch())
4235 .field("release", &&*self.release())
4236 .field("pre", &self.pre())
4237 .field("post", &self.post())
4238 .field("dev", &self.dev())
4239 .field("local", &self.local())
4240 .field("min", &self.min())
4241 .field("max", &self.max())
4242 .finish()
4243 })
4244 }
4245 }
4246
4247 #[test]
4251 fn preserve_trailing_zeros() {
4252 let v1: Version = "1.2.0".parse().unwrap();
4253 assert_eq!(&*v1.release(), &[1, 2, 0]);
4254 assert_eq!(v1.to_string(), "1.2.0");
4255
4256 let v2: Version = "1.2".parse().unwrap();
4257 assert_eq!(&*v2.release(), &[1, 2]);
4258 assert_eq!(v2.to_string(), "1.2");
4259 }
4260
4261 #[test]
4262 fn only_release_trimmed_discards_non_release_segments() {
4263 for version in ["1.2a1", "1.2.post1", "1!1.2", "1.2+local", "1.2.dev1"] {
4264 let version = version.parse::<Version>().unwrap();
4265 assert_eq!(version.only_release_trimmed(), Version::new([1, 2]));
4266 }
4267
4268 assert_eq!(
4269 Version::new([1, 2])
4270 .with_min(Some(0))
4271 .only_release_trimmed(),
4272 Version::new([1, 2])
4273 );
4274 assert_eq!(
4275 Version::new([1, 2])
4276 .with_max(Some(0))
4277 .only_release_trimmed(),
4278 Version::new([1, 2])
4279 );
4280 assert_eq!(
4281 Version::new([1, 2, 0]).only_release_trimmed(),
4282 Version::new([1, 2])
4283 );
4284 assert_eq!(
4285 Version::new([1, 2]).only_release_trimmed(),
4286 Version::new([1, 2])
4287 );
4288 }
4289
4290 #[test]
4291 fn type_size() {
4292 assert_eq!(size_of::<VersionSmall>(), size_of::<usize>() * 2);
4293 assert_eq!(size_of::<Version>(), size_of::<usize>() * 2);
4294 }
4295
4296 #[test]
4299 fn bump_major() {
4300 let mut version = "0".parse::<Version>().unwrap();
4302 version.bump(BumpCommand::BumpRelease {
4303 index: 0,
4304 value: None,
4305 });
4306 assert_eq!(version.to_string().as_str(), "1");
4307
4308 let mut version = "1.5".parse::<Version>().unwrap();
4310 version.bump(BumpCommand::BumpRelease {
4311 index: 0,
4312 value: None,
4313 });
4314 assert_eq!(version.to_string().as_str(), "2.0");
4315
4316 let mut version = "0.1.2".parse::<Version>().unwrap();
4318 version.bump(BumpCommand::BumpRelease {
4319 index: 0,
4320 value: None,
4321 });
4322 assert_eq!(version.to_string().as_str(), "1.0.0");
4323
4324 let mut version = "1.2.3".parse::<Version>().unwrap();
4326 version.bump(BumpCommand::BumpRelease {
4327 index: 0,
4328 value: None,
4329 });
4330 assert_eq!(version.to_string().as_str(), "2.0.0");
4331
4332 let mut version = "1.2.3.4".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.0");
4339
4340 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4342 .parse::<Version>()
4343 .unwrap();
4344 version.bump(BumpCommand::BumpRelease {
4345 index: 0,
4346 value: None,
4347 });
4348 assert_eq!(version.to_string().as_str(), "5!2.0.0.0+local");
4349 version.bump(BumpCommand::BumpRelease {
4350 index: 0,
4351 value: None,
4352 });
4353 assert_eq!(version.to_string().as_str(), "5!3.0.0.0+local");
4354 }
4355
4356 #[test]
4359 fn bump_minor() {
4360 let mut version = "0".parse::<Version>().unwrap();
4362 version.bump(BumpCommand::BumpRelease {
4363 index: 1,
4364 value: None,
4365 });
4366 assert_eq!(version.to_string().as_str(), "0.1");
4367
4368 let mut version = "1.5".parse::<Version>().unwrap();
4370 version.bump(BumpCommand::BumpRelease {
4371 index: 1,
4372 value: None,
4373 });
4374 assert_eq!(version.to_string().as_str(), "1.6");
4375
4376 let mut version = "5.3.6".parse::<Version>().unwrap();
4378 version.bump(BumpCommand::BumpRelease {
4379 index: 1,
4380 value: None,
4381 });
4382 assert_eq!(version.to_string().as_str(), "5.4.0");
4383
4384 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4386 version.bump(BumpCommand::BumpRelease {
4387 index: 1,
4388 value: None,
4389 });
4390 assert_eq!(version.to_string().as_str(), "1.3.0.0");
4391
4392 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4394 .parse::<Version>()
4395 .unwrap();
4396 version.bump(BumpCommand::BumpRelease {
4397 index: 1,
4398 value: None,
4399 });
4400 assert_eq!(version.to_string().as_str(), "5!1.8.0.0+local");
4401 version.bump(BumpCommand::BumpRelease {
4402 index: 1,
4403 value: None,
4404 });
4405 assert_eq!(version.to_string().as_str(), "5!1.9.0.0+local");
4406 }
4407
4408 #[test]
4411 fn bump_patch() {
4412 let mut version = "0".parse::<Version>().unwrap();
4414 version.bump(BumpCommand::BumpRelease {
4415 index: 2,
4416 value: None,
4417 });
4418 assert_eq!(version.to_string().as_str(), "0.0.1");
4419
4420 let mut version = "1.5".parse::<Version>().unwrap();
4422 version.bump(BumpCommand::BumpRelease {
4423 index: 2,
4424 value: None,
4425 });
4426 assert_eq!(version.to_string().as_str(), "1.5.1");
4427
4428 let mut version = "5.3.6".parse::<Version>().unwrap();
4430 version.bump(BumpCommand::BumpRelease {
4431 index: 2,
4432 value: None,
4433 });
4434 assert_eq!(version.to_string().as_str(), "5.3.7");
4435
4436 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4438 version.bump(BumpCommand::BumpRelease {
4439 index: 2,
4440 value: None,
4441 });
4442 assert_eq!(version.to_string().as_str(), "1.2.4.0");
4443
4444 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4446 .parse::<Version>()
4447 .unwrap();
4448 version.bump(BumpCommand::BumpRelease {
4449 index: 2,
4450 value: None,
4451 });
4452 assert_eq!(version.to_string().as_str(), "5!1.7.4.0+local");
4453 version.bump(BumpCommand::BumpRelease {
4454 index: 2,
4455 value: None,
4456 });
4457 assert_eq!(version.to_string().as_str(), "5!1.7.5.0+local");
4458 }
4459
4460 #[test]
4463 fn bump_alpha() {
4464 let mut version = "0".parse::<Version>().unwrap();
4466 version.bump(BumpCommand::BumpPrerelease {
4467 kind: PrereleaseKind::Alpha,
4468 value: None,
4469 });
4470 assert_eq!(version.to_string().as_str(), "0a1");
4471
4472 let mut version = "1.5".parse::<Version>().unwrap();
4474 version.bump(BumpCommand::BumpPrerelease {
4475 kind: PrereleaseKind::Alpha,
4476 value: None,
4477 });
4478 assert_eq!(version.to_string().as_str(), "1.5a1");
4479
4480 let mut version = "5.3.6".parse::<Version>().unwrap();
4482 version.bump(BumpCommand::BumpPrerelease {
4483 kind: PrereleaseKind::Alpha,
4484 value: None,
4485 });
4486 assert_eq!(version.to_string().as_str(), "5.3.6a1");
4487
4488 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4490 version.bump(BumpCommand::BumpPrerelease {
4491 kind: PrereleaseKind::Alpha,
4492 value: None,
4493 });
4494 assert_eq!(version.to_string().as_str(), "1.2.3.4a1");
4495
4496 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4498 .parse::<Version>()
4499 .unwrap();
4500 version.bump(BumpCommand::BumpPrerelease {
4501 kind: PrereleaseKind::Alpha,
4502 value: None,
4503 });
4504 assert_eq!(version.to_string().as_str(), "5!1.7.3.5a1+local");
4505 version.bump(BumpCommand::BumpPrerelease {
4506 kind: PrereleaseKind::Alpha,
4507 value: None,
4508 });
4509 assert_eq!(version.to_string().as_str(), "5!1.7.3.5a2+local");
4510 }
4511
4512 #[test]
4515 fn bump_beta() {
4516 let mut version = "0".parse::<Version>().unwrap();
4518 version.bump(BumpCommand::BumpPrerelease {
4519 kind: PrereleaseKind::Beta,
4520 value: None,
4521 });
4522 assert_eq!(version.to_string().as_str(), "0b1");
4523
4524 let mut version = "1.5".parse::<Version>().unwrap();
4526 version.bump(BumpCommand::BumpPrerelease {
4527 kind: PrereleaseKind::Beta,
4528 value: None,
4529 });
4530 assert_eq!(version.to_string().as_str(), "1.5b1");
4531
4532 let mut version = "5.3.6".parse::<Version>().unwrap();
4534 version.bump(BumpCommand::BumpPrerelease {
4535 kind: PrereleaseKind::Beta,
4536 value: None,
4537 });
4538 assert_eq!(version.to_string().as_str(), "5.3.6b1");
4539
4540 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4542 version.bump(BumpCommand::BumpPrerelease {
4543 kind: PrereleaseKind::Beta,
4544 value: None,
4545 });
4546 assert_eq!(version.to_string().as_str(), "1.2.3.4b1");
4547
4548 let mut version = "5!1.7.3.5a2.post345.dev456+local"
4550 .parse::<Version>()
4551 .unwrap();
4552 version.bump(BumpCommand::BumpPrerelease {
4553 kind: PrereleaseKind::Beta,
4554 value: None,
4555 });
4556 assert_eq!(version.to_string().as_str(), "5!1.7.3.5b1+local");
4557 version.bump(BumpCommand::BumpPrerelease {
4558 kind: PrereleaseKind::Beta,
4559 value: None,
4560 });
4561 assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2+local");
4562 }
4563
4564 #[test]
4567 fn bump_rc() {
4568 let mut version = "0".parse::<Version>().unwrap();
4570 version.bump(BumpCommand::BumpPrerelease {
4571 kind: PrereleaseKind::Rc,
4572 value: None,
4573 });
4574 assert_eq!(version.to_string().as_str(), "0rc1");
4575
4576 let mut version = "1.5".parse::<Version>().unwrap();
4578 version.bump(BumpCommand::BumpPrerelease {
4579 kind: PrereleaseKind::Rc,
4580 value: None,
4581 });
4582 assert_eq!(version.to_string().as_str(), "1.5rc1");
4583
4584 let mut version = "5.3.6".parse::<Version>().unwrap();
4586 version.bump(BumpCommand::BumpPrerelease {
4587 kind: PrereleaseKind::Rc,
4588 value: None,
4589 });
4590 assert_eq!(version.to_string().as_str(), "5.3.6rc1");
4591
4592 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4594 version.bump(BumpCommand::BumpPrerelease {
4595 kind: PrereleaseKind::Rc,
4596 value: None,
4597 });
4598 assert_eq!(version.to_string().as_str(), "1.2.3.4rc1");
4599
4600 let mut version = "5!1.7.3.5b2.post345.dev456+local"
4602 .parse::<Version>()
4603 .unwrap();
4604 version.bump(BumpCommand::BumpPrerelease {
4605 kind: PrereleaseKind::Rc,
4606 value: None,
4607 });
4608 assert_eq!(version.to_string().as_str(), "5!1.7.3.5rc1+local");
4609 version.bump(BumpCommand::BumpPrerelease {
4610 kind: PrereleaseKind::Rc,
4611 value: None,
4612 });
4613 assert_eq!(version.to_string().as_str(), "5!1.7.3.5rc2+local");
4614 }
4615
4616 #[test]
4619 fn bump_post() {
4620 let mut version = "0".parse::<Version>().unwrap();
4622 version.bump(BumpCommand::BumpPost { value: None });
4623 assert_eq!(version.to_string().as_str(), "0.post1");
4624
4625 let mut version = "1.5".parse::<Version>().unwrap();
4627 version.bump(BumpCommand::BumpPost { value: None });
4628 assert_eq!(version.to_string().as_str(), "1.5.post1");
4629
4630 let mut version = "5.3.6".parse::<Version>().unwrap();
4632 version.bump(BumpCommand::BumpPost { value: None });
4633 assert_eq!(version.to_string().as_str(), "5.3.6.post1");
4634
4635 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4637 version.bump(BumpCommand::BumpPost { value: None });
4638 assert_eq!(version.to_string().as_str(), "1.2.3.4.post1");
4639
4640 let mut version = "5!1.7.3.5b2.dev123+local".parse::<Version>().unwrap();
4642 version.bump(BumpCommand::BumpPost { value: None });
4643 assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2.post1+local");
4644 version.bump(BumpCommand::BumpPost { value: None });
4645 assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2.post2+local");
4646 }
4647
4648 #[test]
4651 fn bump_dev() {
4652 let mut version = "0".parse::<Version>().unwrap();
4654 version.bump(BumpCommand::BumpDev { value: None });
4655 assert_eq!(version.to_string().as_str(), "0.dev1");
4656
4657 let mut version = "1.5".parse::<Version>().unwrap();
4659 version.bump(BumpCommand::BumpDev { value: None });
4660 assert_eq!(version.to_string().as_str(), "1.5.dev1");
4661
4662 let mut version = "5.3.6".parse::<Version>().unwrap();
4664 version.bump(BumpCommand::BumpDev { value: None });
4665 assert_eq!(version.to_string().as_str(), "5.3.6.dev1");
4666
4667 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4669 version.bump(BumpCommand::BumpDev { value: None });
4670 assert_eq!(version.to_string().as_str(), "1.2.3.4.dev1");
4671
4672 let mut version = "5!1.7.3.5b2.post345+local".parse::<Version>().unwrap();
4674 version.bump(BumpCommand::BumpDev { value: None });
4675 assert_eq!(
4676 version.to_string().as_str(),
4677 "5!1.7.3.5b2.post345.dev1+local"
4678 );
4679 version.bump(BumpCommand::BumpDev { value: None });
4680 assert_eq!(
4681 version.to_string().as_str(),
4682 "5!1.7.3.5b2.post345.dev2+local"
4683 );
4684 }
4685
4686 #[test]
4689 fn make_stable() {
4690 let mut version = "0".parse::<Version>().unwrap();
4692 version.bump(BumpCommand::MakeStable);
4693 assert_eq!(version.to_string().as_str(), "0");
4694
4695 let mut version = "1.5".parse::<Version>().unwrap();
4697 version.bump(BumpCommand::MakeStable);
4698 assert_eq!(version.to_string().as_str(), "1.5");
4699
4700 let mut version = "5.3.6".parse::<Version>().unwrap();
4702 version.bump(BumpCommand::MakeStable);
4703 assert_eq!(version.to_string().as_str(), "5.3.6");
4704
4705 let mut version = "1.2.3.4".parse::<Version>().unwrap();
4707 version.bump(BumpCommand::MakeStable);
4708 assert_eq!(version.to_string().as_str(), "1.2.3.4");
4709
4710 let mut version = "5!1.7.3.5b2.post345+local".parse::<Version>().unwrap();
4712 version.bump(BumpCommand::MakeStable);
4713 assert_eq!(version.to_string().as_str(), "5!1.7.3.5+local");
4714 version.bump(BumpCommand::MakeStable);
4715 assert_eq!(version.to_string().as_str(), "5!1.7.3.5+local");
4716 }
4717}