1#![deny(
10 bad_style,
11 const_err,
12 dead_code,
13 improper_ctypes,
14 missing_copy_implementations,
15 missing_debug_implementations,
16 missing_docs,
17 no_mangle_generic_items,
18 non_shorthand_field_patterns,
19 overflowing_literals,
20 path_statements,
21 patterns_in_fns_without_body,
22 private_in_public,
23 rust_2018_idioms,
24 trivial_casts,
25 trivial_numeric_casts,
26 unconditional_recursion,
27 unsafe_code,
28 unused_allocation,
29 unused_comparisons,
30 unused_extern_crates,
31 unused_import_braces,
32 unused_parens,
33 unused_qualifications,
34 unused_results,
35 unused,
36 while_true
37)]
38
39use std::{
40 cmp::Ordering,
41 fmt::{self, Display, Write},
42 hash,
43 ops::Deref,
44};
45
46mod metadata;
47pub use metadata::{Additional, Build, PreRelease};
48
49#[derive(Debug, Clone)]
53pub struct Version<'input> {
54 pub major: u64,
56 pub minor: u64,
58 pub patch: u64,
60 pub additional: Additional,
62 pub pre: PreRelease<'input>,
64 pub build: Build<'input>,
66}
67
68impl<'input> Version<'input> {
69 pub const fn empty() -> Self {
79 Version {
80 major: 0,
81 minor: 0,
82 patch: 0,
83 additional: Additional::empty(),
84 pre: PreRelease::empty(),
85 build: Build::empty(),
86 }
87 }
88
89 pub const fn new(major: u64, minor: u64, patch: u64) -> Self {
99 Version {
100 major,
101 minor,
102 patch,
103 additional: Additional::empty(),
104 pre: PreRelease::empty(),
105 build: Build::empty(),
106 }
107 }
108
109 #[cfg(feature = "parser")]
124 pub fn parse(input: &'input str) -> Result<Self, lenient_semver_parser::Error<'input>> {
125 lenient_semver_parser::parse::<Self>(input)
126 }
127
128 pub fn bump_major(&mut self) {
142 self.major += 1;
143 self.minor = 0;
144 self.patch = 0;
145 self.additional.set_to_zero();
146 self.clear_metadata();
147 }
148
149 pub fn bumped_major<'a>(&self) -> Version<'a> {
163 Version {
164 major: self.major + 1,
165 minor: 0,
166 patch: 0,
167 additional: self.additional.clone_with_zeroes(),
168 pre: PreRelease::empty(),
169 build: Build::empty(),
170 }
171 }
172
173 pub fn bump_minor(&mut self) {
187 self.minor += 1;
188 self.patch = 0;
189 self.additional.set_to_zero();
190 self.clear_metadata();
191 }
192
193 pub fn bumped_minor<'a>(&self) -> Version<'a> {
207 Version {
208 major: self.major,
209 minor: self.minor + 1,
210 patch: 0,
211 additional: self.additional.clone_with_zeroes(),
212 pre: PreRelease::empty(),
213 build: Build::empty(),
214 }
215 }
216
217 pub fn bump_patch(&mut self) {
231 self.patch += 1;
232 self.additional.set_to_zero();
233 self.clear_metadata();
234 }
235
236 pub fn bumped_patch<'a>(&self) -> Version<'a> {
250 Version {
251 major: self.major,
252 minor: self.minor,
253 patch: self.patch + 1,
254 additional: self.additional.clone_with_zeroes(),
255 pre: PreRelease::empty(),
256 build: Build::empty(),
257 }
258 }
259
260 pub fn bump_additional(&mut self, index: usize) {
283 self.additional.bump(index);
284 self.clear_metadata();
285 }
286
287 pub fn bumped_additional<'a>(&self, index: usize) -> Version<'a> {
303 let mut additional = self.additional.clone();
304 additional.bump(index);
305 Version {
306 major: self.major,
307 minor: self.minor,
308 patch: self.patch,
309 additional,
310 pre: PreRelease::empty(),
311 build: Build::empty(),
312 }
313 }
314
315 pub fn is_pre_release(&self) -> bool {
332 self.pre.is_defined()
333 }
334
335 pub fn disassociate_metadata<'a>(self) -> (Version<'a>, PreRelease<'input>, Build<'input>) {
373 let Version {
374 major,
375 minor,
376 patch,
377 additional,
378 pre,
379 build,
380 } = self;
381 let version = Version {
382 major,
383 minor,
384 patch,
385 additional,
386 pre: PreRelease::empty(),
387 build: Build::empty(),
388 };
389 (version, pre, build)
390 }
391
392 fn clear_metadata(&mut self) {
393 self.pre.clear();
394 self.build.clear();
395 }
396}
397
398impl Default for Version<'_> {
399 fn default() -> Self {
400 Self::empty()
401 }
402}
403
404impl<'input> From<u64> for Version<'input> {
405 fn from(x: u64) -> Self {
406 Version::new(x, 0, 0)
407 }
408}
409
410impl<'input> From<(u64, u64)> for Version<'input> {
411 fn from((x, y): (u64, u64)) -> Self {
412 Version::new(x, y, 0)
413 }
414}
415
416impl<'input> From<(u64, u64, u64)> for Version<'input> {
417 fn from((x, y, z): (u64, u64, u64)) -> Self {
418 Version::new(x, y, z)
419 }
420}
421
422impl<'input> From<[u64; 1]> for Version<'input> {
423 fn from(v: [u64; 1]) -> Self {
424 Version::new(v[0], 0, 0)
425 }
426}
427
428impl<'input> From<[u64; 2]> for Version<'input> {
429 fn from(v: [u64; 2]) -> Self {
430 Version::new(v[0], v[1], 0)
431 }
432}
433
434impl<'input> From<[u64; 3]> for Version<'input> {
435 fn from(v: [u64; 3]) -> Self {
436 Version::new(v[0], v[1], v[2])
437 }
438}
439
440#[cfg(feature = "parser")]
441impl<'input> std::convert::TryFrom<&'input str> for Version<'input> {
442 type Error = lenient_semver_parser::Error<'input>;
443
444 fn try_from(value: &'input str) -> Result<Self, Self::Error> {
445 Self::parse(value)
446 }
447}
448
449impl Display for Version<'_> {
450 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
451 let mut result = String::with_capacity(16);
452 write!(result, "{}.{}.{}", self.major, self.minor, self.patch)?;
453 for &additional in self.additional.iter() {
454 write!(result, ".{}", additional)?;
455 }
456
457 if let Some(pre) = self.pre.deref() {
458 result.push('-');
459 result.push_str(pre);
460 }
461 if let Some(build) = self.build.deref() {
462 result.push('+');
463 result.push_str(build);
464 }
465
466 f.pad(result.as_ref())
467 }
468}
469
470impl PartialEq for Version<'_> {
471 #[inline]
472 fn eq(&self, other: &Self) -> bool {
473 self.major == other.major
474 && self.minor == other.minor
475 && self.patch == other.patch
476 && self.additional == other.additional
477 && self.pre == other.pre
478 }
479}
480
481impl Eq for Version<'_> {}
482
483impl PartialOrd for Version<'_> {
484 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
485 Some(self.cmp(other))
486 }
487}
488
489impl Ord for Version<'_> {
490 fn cmp(&self, other: &Self) -> Ordering {
491 self.major
492 .cmp(&other.major)
493 .then_with(|| self.minor.cmp(&other.minor))
494 .then_with(|| self.patch.cmp(&other.patch))
495 .then_with(|| self.additional.cmp(&other.additional))
496 .then_with(|| self.pre.cmp(&other.pre))
497 }
498}
499
500impl hash::Hash for Version<'_> {
501 fn hash<H: hash::Hasher>(&self, into: &mut H) {
502 self.major.hash(into);
503 self.minor.hash(into);
504 self.patch.hash(into);
505 self.additional.hash(into);
506 self.pre.hash(into);
507 }
508}
509
510#[cfg(feature = "parser")]
511impl<'input> lenient_semver_parser::VersionBuilder<'input> for Version<'input> {
512 type Out = Self;
513
514 fn new() -> Self {
515 Version::default()
516 }
517
518 fn set_major(&mut self, major: u64) {
519 self.major = major;
520 }
521
522 fn set_minor(&mut self, minor: u64) {
523 self.minor = minor;
524 }
525
526 fn set_patch(&mut self, patch: u64) {
527 self.patch = patch;
528 }
529
530 fn add_additional(&mut self, num: u64) {
531 self.additional.push(num);
532 }
533
534 fn add_pre_release(&mut self, pre_release: &'input str) {
535 self.pre.set(pre_release)
536 }
537
538 fn add_build(&mut self, build: &'input str) {
539 self.build.set(build)
540 }
541
542 fn build(self) -> Self::Out {
543 self
544 }
545}
546
547#[cfg(all(feature = "serde", feature = "parser"))]
548use serde::de::{self, Deserialize, Deserializer, Visitor};
549#[cfg(feature = "serde")]
550use serde::ser::{Serialize, Serializer};
551#[cfg(feature = "serde")]
552impl Serialize for Version<'_> {
553 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
554 serializer.collect_str(self)
555 }
556}
557
558#[cfg(all(feature = "serde", feature = "parser"))]
559impl<'de: 'input, 'input> Deserialize<'de> for Version<'input> {
560 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
561 struct VersionVisitor<'input>(std::marker::PhantomData<&'input ()>);
562
563 impl<'de: 'input, 'input> Visitor<'de> for VersionVisitor<'input> {
564 type Value = Version<'input>;
565
566 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
567 formatter.write_str("a version string")
568 }
569
570 fn visit_borrowed_str<E>(self, v: &'input str) -> Result<Self::Value, E>
571 where
572 E: de::Error,
573 {
574 Version::parse(v).map_err(de::Error::custom)
575 }
576 }
577
578 deserializer.deserialize_str(VersionVisitor(std::marker::PhantomData))
579 }
580}
581
582#[cfg(feature = "semver")]
583impl<'input> From<Version<'input>> for semver_v100::Version {
584 fn from(v: Version<'input>) -> Self {
585 let build = if v.additional.is_empty() {
586 v.build.into()
587 } else {
588 let mut build = String::with_capacity(64);
589 for add in v.additional {
590 if !build.is_empty() {
591 build.push('.');
592 }
593 let _ = write!(build, "{}", add);
594 }
595 if let Some(b) = *v.build {
596 build.push('.');
597 build.push_str(b);
598 }
599 let build = lenient_semver_version_builder::sanitize_build(build);
600 semver_v100::BuildMetadata::new(&build).unwrap()
601 };
602
603 semver_v100::Version {
604 major: v.major,
605 minor: v.minor,
606 patch: v.patch,
607 pre: v.pre.into(),
608 build,
609 }
610 }
611}
612
613#[cfg(feature = "semver011")]
614impl From<Version<'_>> for semver_v011::Version {
615 fn from(v: Version<'_>) -> Self {
616 let mut add: Vec<semver_v011::Identifier> = v.additional.into();
617 let mut build: Vec<semver_v011::Identifier> = v.build.into();
618 add.append(&mut build);
619 semver_v011::Version {
620 major: v.major,
621 minor: v.minor,
622 patch: v.patch,
623 pre: v.pre.into(),
624 build: add,
625 }
626 }
627}
628
629#[cfg(feature = "semver010")]
630impl From<Version<'_>> for semver_v010::Version {
631 fn from(v: Version<'_>) -> Self {
632 let mut add: Vec<semver_v010::Identifier> = v.additional.into();
633 let mut build: Vec<semver_v010::Identifier> = v.build.into();
634 add.append(&mut build);
635 semver_v010::Version {
636 major: v.major,
637 minor: v.minor,
638 patch: v.patch,
639 pre: v.pre.into(),
640 build: add,
641 }
642 }
643}
644
645#[cfg(test)]
646mod tests {
647 use super::Version;
648 use test_case::test_case;
649
650 #[test]
651 fn test_bump_major() {
652 let mut version = Version::parse("1.2.3.4.5-pre+build").unwrap();
653 version.bump_major();
654 assert_eq!(version, Version::parse("2.0.0.0.0").unwrap());
655 }
656
657 #[test]
658 fn test_bumped_major() {
659 let version = Version::parse("1.2.3.4.5-pre+build").unwrap();
660 assert_eq!(version.bumped_major(), Version::parse("2.0.0.0.0").unwrap());
661 }
662
663 #[test]
664 fn test_bump_minor() {
665 let mut version = Version::parse("1.2.3.4.5-pre+build").unwrap();
666 version.bump_minor();
667 assert_eq!(version, Version::parse("1.3.0.0.0").unwrap());
668 }
669
670 #[test]
671 fn test_bumped_minor() {
672 let version = Version::parse("1.2.3.4.5-pre+build").unwrap();
673 assert_eq!(version.bumped_minor(), Version::parse("1.3.0.0.0").unwrap());
674 }
675
676 #[test]
677 fn test_bump_patch() {
678 let mut version = Version::parse("1.2.3.4.5-pre+build").unwrap();
679 version.bump_patch();
680 assert_eq!(version, Version::parse("1.2.4.0.0").unwrap());
681 }
682
683 #[test]
684 fn test_bumped_patch() {
685 let version = Version::parse("1.2.3.4.5-pre+build").unwrap();
686 assert_eq!(version.bumped_patch(), Version::parse("1.2.4.0.0").unwrap());
687 }
688
689 #[test_case(0, "1.2.3.5.0")]
690 #[test_case(1, "1.2.3.4.6")]
691 #[test_case(2, "1.2.3.4.5")]
692 fn test_bump_additional(index: usize, expected: &str) {
693 let mut version = Version::parse("1.2.3.4.5-pre+build").unwrap();
694 version.bump_additional(index);
695 assert_eq!(version, Version::parse(expected).unwrap());
696 }
697
698 #[test_case(0, "1.2.3.5.0")]
699 #[test_case(1, "1.2.3.4.6")]
700 #[test_case(2, "1.2.3.4.5")]
701 fn test_bumped_additional(index: usize, expected: &str) {
702 let version = Version::parse("1.2.3.4.5-pre+build").unwrap();
703 assert_eq!(
704 version.bumped_additional(index),
705 Version::parse(expected).unwrap()
706 );
707 }
708
709 #[test_case("1")]
710 #[test_case("1.2")]
711 #[test_case("1.2.3")]
712 #[test_case("1.2.3.4")]
713 #[test_case("1.2.3.4.5")]
714 #[test_case("1.2.3.4.5+build")]
715 fn test_is_not_pre_release(input: &str) {
716 assert!(!Version::parse(input).unwrap().is_pre_release());
717 }
718
719 #[test_case("1-2")]
720 #[test_case("1-a")]
721 #[test_case("1.2-3")]
722 #[test_case("1.2-a")]
723 #[test_case("1.2.3-4")]
724 #[test_case("1.2.3-a")]
725 #[test_case("1.2.3.4-5")]
726 #[test_case("1.2.3.4-a")]
727 #[test_case("1.2.3.4.5-pre")]
728 fn test_is_pre_release(input: &str) {
729 assert!(Version::parse(input).unwrap().is_pre_release());
730 }
731
732 #[test_case("1", "1.0.0")]
733 #[test_case("1.2", "1.2.0")]
734 #[test_case("1.2.3", "1.2.3")]
735 #[test_case("1.2.3.4", "1.2.3.4")]
736 #[test_case("1.2.3.4.5", "1.2.3.4.5")]
737 #[test_case("1.2.3-pre", "1.2.3-pre")]
738 #[test_case("1.2.3.pre2", "1.2.3-pre2")]
739 #[test_case("1.2.3+build", "1.2.3+build")]
740 #[test_case("1.2.3.4-pre-42+r-1337", "1.2.3.4-pre-42+r-1337")]
741 fn test_to_string(v: &str, expected: &str) {
742 assert_eq!(Version::parse(v).unwrap().to_string(), expected.to_string());
743 }
744
745 #[test]
746 fn test_from_u64() {
747 assert_eq!(Version::from(42), Version::new(42, 0, 0));
748 }
749
750 #[test]
751 fn test_from_u64_u64() {
752 assert_eq!(Version::from((42, 13)), Version::new(42, 13, 0));
753 }
754
755 #[test]
756 fn test_from_u64_u64_u64() {
757 assert_eq!(Version::from((42, 13, 37)), Version::new(42, 13, 37));
758 }
759
760 #[test]
761 fn test_from_u64_1() {
762 assert_eq!(Version::from([42]), Version::new(42, 0, 0));
763 }
764
765 #[test]
766 fn test_from_u64_2() {
767 assert_eq!(Version::from([42, 13]), Version::new(42, 13, 0));
768 }
769
770 #[test]
771 fn test_from_u64_3() {
772 assert_eq!(Version::from([42, 13, 37]), Version::new(42, 13, 37));
773 }
774
775 #[test]
776 fn test_display() {
777 let version = Version::parse("1.2.3.4.5-pre+build").unwrap();
778 assert_eq!(
779 format!("{:42}", version),
780 "1.2.3.4.5-pre+build "
781 );
782 assert_eq!(
783 format!("{:>42}", version),
784 " 1.2.3.4.5-pre+build"
785 );
786 assert_eq!(
787 format!("{:^42}", version),
788 " 1.2.3.4.5-pre+build "
789 );
790 assert_eq!(
791 format!("{:*<42}", version),
792 "1.2.3.4.5-pre+build***********************"
793 );
794 assert_eq!(
795 format!("{:*>42}", version),
796 "***********************1.2.3.4.5-pre+build"
797 );
798 assert_eq!(
799 format!("{:*^42}", version),
800 "***********1.2.3.4.5-pre+build************"
801 );
802 assert_eq!(format!("{:.7}", version), "1.2.3.4");
803 }
804
805 #[test]
806 fn test_parses_additional() {
807 let version = Version::parse("1.2.3.4.5-alpha1.drop02").unwrap();
808 assert_eq!(vec![4, 5], &*version.additional)
809 }
810
811 #[test_case("1")]
812 #[test_case("1.2")]
813 #[test_case("1.2.3")]
814 #[test_case("1.2.3.4")]
815 #[test_case("1.2.3.4.5")]
816 #[test_case("1.2.3-pre")]
817 #[test_case("1.2.3+build")]
818 #[test_case("1.2.3-pre+build")]
819 fn test_eq(input: &str) {
820 assert_eq!(Version::parse(input), Version::parse(input));
821 }
822
823 #[test_case("1", "1.0.0")]
824 #[test_case("1.2", "1.2.0")]
825 #[test_case("1.2.3+42", "1.2.3+1337")]
826 #[test_case("1.2.3-pre", "1.2.3-pre+build")]
827 fn test_eq2(v1: &str, v2: &str) {
828 assert_eq!(Version::parse(v1), Version::parse(v2));
829 }
830
831 #[test_case("1", "2")]
832 #[test_case("1.2", "1.3")]
833 #[test_case("1.2.3", "1.2.4")]
834 #[test_case("1.2.3-pre", "1.2.3")]
835 #[test_case("1.2.3.4", "1.2.3")]
836 #[test_case("1.2.3.4", "1.2.3.5")]
837 #[test_case("1.2.3.4", "1.2.3.4.5")]
838 #[test_case("1.2.3-pre", "1.2.3-pre2")]
839 fn test_ne(v1: &str, v2: &str) {
840 assert_ne!(Version::parse(v1), Version::parse(v2));
841 }
842
843 #[test_case("0.0.0", "0.0.1")]
844 #[test_case("0.0.0", "0.1.0")]
845 #[test_case("0.0.0", "1.0.0")]
846 #[test_case("1.0.0", "1.0.1")]
847 #[test_case("1.0.0", "1.1.0")]
848 #[test_case("1.0.0", "2.0.0")]
849 #[test_case("1.1.0", "1.1.1")]
850 #[test_case("1.1.0", "1.2.0")]
851 #[test_case("1.1.0", "2.0.0")]
852 #[test_case("1.2.3", "1.2.3.4")]
853 #[test_case("1.2.3.4", "1.2.3.5")]
854 #[test_case("1.2.3.4", "1.2.3.4.5")]
855 #[test_case("1.2.3-pre", "1.2.3")]
856 #[test_case("1.2.3.4-pre", "1.2.3.4")]
857 #[test_case("1.2.3.4.5-pre", "1.2.3.4.5")]
858 #[test_case("1.2.3", "1.2.3.4-pre")]
859 #[test_case("1.2.2", "1.2.3-pre")]
860 #[test_case("1.2.0", "1.2.3-pre")]
861 #[test_case("1.0.0", "1.2.3-pre")]
862 #[test_case("0.4.2", "1.2.3-pre")]
863 #[test_case("0.0.1", "1.2.3-pre")]
864 #[test_case("1.2.3-42", "1.2.3-84")]
865 #[test_case("1.2.3-42", "1.2.3-123")]
866 #[test_case("1.2.3-42", "1.2.3-42foo")]
867 #[test_case("1.2.3-42", "1.2.3-12foo")]
868 #[test_case("1.2.3-42", "1.2.3-1foo")]
869 #[test_case("1.2.3-42", "1.2.3-foo")]
870 fn test_lt(v1: &str, v2: &str) {
871 assert!(Version::parse(v1) < Version::parse(v2));
872 }
873
874 #[test_case("1.2.3", "1.2.3")]
875 #[test_case("1.2.3.4", "1.2.3.4")]
876 #[test_case("1.2.3.4.5", "1.2.3.4.5")]
877 #[test_case("1.2.3", "1.2.3.0.0")]
878 #[test_case("1.2.3.4", "1.2.3.4.0")]
879 #[test_case("1.2.3-pre", "1.2.3-pre")]
880 #[test_case("1.2.3+build", "1.2.3+build")]
881 #[test_case("1.2.3+build2", "1.2.3+build3")]
882 #[test_case("1.2.3+42", "1.2.3+84")]
883 fn test_not_lt(v1: &str, v2: &str) {
884 assert!(!(Version::parse(v1) < Version::parse(v2)));
885 }
886
887 #[test_case("0.0.0", "0.0.1")]
888 #[test_case("0.0.1", "0.0.1")]
889 #[test_case("0.0.0", "0.1.0")]
890 #[test_case("0.1.0", "0.1.0")]
891 #[test_case("0.0.0", "1.0.0")]
892 #[test_case("1.0.0", "1.0.0")]
893 #[test_case("1.2.3", "1.2.3.4")]
894 #[test_case("1.2.3.4", "1.2.3.4")]
895 #[test_case("1.2.3.4", "1.2.3.4.5")]
896 #[test_case("1.2.3.4.5", "1.2.3.4.5")]
897 #[test_case("1.2.3-pre", "1.2.3")]
898 #[test_case("1.2.3", "1.2.3")]
899 #[test_case("1.2.3+build", "1.2.3")]
900 fn test_lte(v1: &str, v2: &str) {
901 assert!(Version::parse(v1) <= Version::parse(v2));
902 }
903
904 #[test_case("0.0.1", "0.0.0")]
905 #[test_case("0.1.0", "0.0.0")]
906 #[test_case("1.0.0", "0.0.0")]
907 #[test_case("1.0.1", "1.0.0")]
908 #[test_case("1.1.0", "1.0.0")]
909 #[test_case("2.0.0", "1.0.0")]
910 #[test_case("1.1.1", "1.1.0")]
911 #[test_case("1.2.0", "1.1.0")]
912 #[test_case("2.0.0", "1.1.0")]
913 #[test_case("1.2.3.4", "1.2.3")]
914 #[test_case("1.2.3.5", "1.2.3.4")]
915 #[test_case("1.2.3.4.5", "1.2.3.4")]
916 #[test_case("1.2.3", "1.2.3-pre")]
917 #[test_case("1.2.3.4", "1.2.3.4-pre")]
918 #[test_case("1.2.3.4.5", "1.2.3.4.5-pre")]
919 #[test_case("1.2.3.4-pre", "1.2.3")]
920 #[test_case("1.2.3-pre", "1.2.2")]
921 #[test_case("1.2.3-pre", "1.2.0")]
922 #[test_case("1.2.3-pre", "1.0.0")]
923 #[test_case("1.2.3-pre", "0.4.2")]
924 #[test_case("1.2.3-pre", "0.0.1")]
925 fn test_gt(v1: &str, v2: &str) {
926 assert!(Version::parse(v1) > Version::parse(v2));
927 }
928
929 #[test_case("1.2.3", "1.2.3")]
930 #[test_case("1.2.3.4", "1.2.3.4")]
931 #[test_case("1.2.3.4.5", "1.2.3.4.5")]
932 #[test_case("1.2.3-pre", "1.2.3-pre")]
933 #[test_case("1.2.3+build", "1.2.3+build")]
934 #[test_case("1.2.3+build3", "1.2.3+build2")]
935 #[test_case("1.2.3+84", "1.2.3+42")]
936 fn test_not_gt(v1: &str, v2: &str) {
937 assert!(!(Version::parse(v1) > Version::parse(v2)));
938 }
939
940 #[test_case("0.0.1", "0.0.0")]
941 #[test_case("0.0.1", "0.0.1")]
942 #[test_case("0.1.0", "0.0.0")]
943 #[test_case("0.1.0", "0.1.0")]
944 #[test_case("1.0.0", "0.0.0")]
945 #[test_case("1.0.0", "1.0.0")]
946 #[test_case("1.2.3.4", "1.2.3")]
947 #[test_case("1.2.3.4", "1.2.3.4")]
948 #[test_case("1.2.3.4.5", "1.2.3.4")]
949 #[test_case("1.2.3.4.5", "1.2.3.4.5")]
950 #[test_case("1.2.3", "1.2.3-pre")]
951 #[test_case("1.2.3", "1.2.3")]
952 #[test_case("1.2.3", "1.2.3+build")]
953 fn test_gte(v1: &str, v2: &str) {
954 assert!(Version::parse(v1) >= Version::parse(v2));
955 }
956
957 #[test]
958 fn test_order_per_spec_11_4() {
959 let versions = [
960 "1.0.0-alpha",
961 "1.0.0-alpha.1",
962 "1.0.0-alpha.beta",
963 "1.0.0-beta",
964 "1.0.0-beta.2",
965 "1.0.0-beta.11",
966 "1.0.0-rc.1",
967 "1.0.0",
968 ]
969 .iter()
970 .map(|v| Version::parse(v))
971 .collect::<Result<Vec<_>, _>>()
972 .unwrap();
973
974 let left = versions.iter();
975 let right = versions.iter().skip(1);
976
977 for (left, right) in left.zip(right) {
978 assert!(left < right, "{} < {} was violated", left, right);
979 }
980 }
981
982 #[cfg(feature = "serde")]
983 #[cfg_attr(feature = "serde", test)]
984 fn test_ser() {
985 let v = Version::new(1, 2, 3);
986 assert_eq!(r#""1.2.3""#, serde_json::to_string(&v).unwrap());
987 }
988
989 #[cfg(feature = "serde")]
990 #[cfg_attr(feature = "serde", test)]
991 fn test_deser() {
992 let v = r#""1.2.3""#;
993 assert_eq!(Version::new(1, 2, 3), serde_json::from_str(v).unwrap());
994 }
995
996 #[cfg(feature = "semver")]
997 #[cfg_attr(feature = "semver", test)]
998 fn test_into_semver() {
999 let v = Version::new(1, 2, 3);
1000 assert_eq!(
1001 semver_v100::Version::new(1, 2, 3),
1002 semver_v100::Version::from(v)
1003 );
1004 }
1005
1006 #[cfg(feature = "semver")]
1007 #[test]
1008 fn test_into_semver_full() {
1009 use lenient_semver_version_builder::VersionBuilder;
1010 let mut v = <Version<'static> as VersionBuilder<'static>>::new();
1011 v.set_major(1);
1012 v.set_minor(2);
1013 v.set_patch(3);
1014 v.add_additional(42);
1015 v.add_additional(1337);
1016 v.add_pre_release("deprecated!alpha.01");
1017 v.add_build("build+42");
1018 let v = v.build();
1019
1020 let expected = semver_v100::Version {
1021 major: 1,
1022 minor: 2,
1023 patch: 3,
1024 pre: semver_v100::Prerelease::new("deprecated-alpha.1").unwrap(),
1025 build: semver_v100::BuildMetadata::new("42.1337.build-42").unwrap(),
1026 };
1027
1028 assert_eq!(expected, semver_v100::Version::from(v));
1029 }
1030
1031 #[cfg(feature = "semver011")]
1032 #[cfg_attr(feature = "semver011", test)]
1033 fn test_into_semver011() {
1034 let v = Version::new(1, 2, 3);
1035 assert_eq!(
1036 semver_v011::Version::new(1, 2, 3),
1037 semver_v011::Version::from(v)
1038 );
1039 }
1040
1041 #[cfg(feature = "semver010")]
1042 #[cfg_attr(feature = "semver010", test)]
1043 fn test_into_semver010() {
1044 let v = Version::new(1, 2, 3);
1045 assert_eq!(
1046 semver_v010::Version::new(1, 2, 3),
1047 semver_v010::Version::from(v)
1048 );
1049 }
1050}