use crate::parsers::modular;
use crate::{BaseVersionParser, FullVersion, ParserError};
use std::fmt;
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BaseVersion {
pub major: u64,
pub minor: u64,
}
impl BaseVersion {
pub fn new(major: u64, minor: u64) -> Self {
Self { major, minor }
}
pub fn parse(input: &str) -> Result<Self, ParserError> {
modular::ModularParser.parse_base(input)
}
pub fn to_full_version_lossy(self) -> FullVersion {
FullVersion {
major: self.major,
minor: self.minor,
patch: 0,
}
}
pub fn map<U, F>(self, fun: F) -> U
where
F: FnOnce(Self) -> U,
{
fun(self)
}
}
impl From<(u64, u64)> for BaseVersion {
fn from(tuple: (u64, u64)) -> Self {
BaseVersion {
major: tuple.0,
minor: tuple.1,
}
}
}
impl fmt::Display for BaseVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!("{}.{}", self.major, self.minor))
}
}
#[cfg(test)]
mod tests {
use crate::{BaseVersion, FullVersion};
#[test]
fn from_tuple() {
let major = 0;
let minor = 1;
assert_eq!(
BaseVersion { major, minor },
BaseVersion::from((major, minor))
);
}
#[yare::parameterized(
zeros = { BaseVersion { major: 0, minor: 0 }, "0.0" },
non_zero = { BaseVersion { major: 1, minor: 2 }, "1.2" },
)]
fn display(base_version: BaseVersion, expected: &str) {
let displayed = format!("{}", base_version);
assert_eq!(&displayed, expected);
}
#[yare::parameterized(
instance_0 = { BaseVersion::new(1, 0) },
instance_1 = { BaseVersion::new(1, 1) },
instance_m = { BaseVersion::new(1, u64::MAX) },
)]
fn to_full_version_lossy(base: BaseVersion) {
let converted = base.to_full_version_lossy();
assert_eq!(
converted,
FullVersion {
major: base.major,
minor: base.minor,
patch: 0,
}
)
}
#[test]
fn map() {
let version = BaseVersion::new(1, 2);
let mapped = version.map(|v| format!("Wowsies {}", v.major));
assert_eq!(mapped.as_str(), "Wowsies 1");
}
}
#[cfg(test)]
mod ord_tests {
use crate::BaseVersion;
use std::cmp::Ordering;
#[yare::parameterized(
zero = { BaseVersion { major: 0, minor: 0 }, BaseVersion { major: 0, minor: 0 } },
ones = { BaseVersion { major: 1, minor: 1 }, BaseVersion { major: 1, minor: 1 } },
)]
fn equals(lhs: BaseVersion, rhs: BaseVersion) {
assert_eq!(lhs.cmp(&rhs), Ordering::Equal);
}
#[yare::parameterized(
minor_by_1 = { BaseVersion { major: 0, minor: 0 }, BaseVersion { major: 0, minor: 1 } },
major_by_1 = { BaseVersion { major: 1, minor: 0 }, BaseVersion { major: 2, minor: 0 } },
)]
fn less(lhs: BaseVersion, rhs: BaseVersion) {
assert_eq!(lhs.cmp(&rhs), Ordering::Less);
}
#[yare::parameterized(
minor_by_1 = { BaseVersion { major: 0, minor: 1 }, BaseVersion { major: 0, minor: 0 } },
major_by_1 = { BaseVersion { major: 1, minor: 0 }, BaseVersion { major: 0, minor: 0 } },
)]
fn greater(lhs: BaseVersion, rhs: BaseVersion) {
assert_eq!(lhs.cmp(&rhs), Ordering::Greater);
}
}
#[cfg(test)]
mod partial_ord_tests {
use crate::BaseVersion;
use std::cmp::Ordering;
#[yare::parameterized(
zero = { BaseVersion { major: 0, minor: 0 }, BaseVersion { major: 0, minor: 0 } },
ones = { BaseVersion { major: 1, minor: 1 }, BaseVersion { major: 1, minor: 1 } },
)]
fn equals(lhs: BaseVersion, rhs: BaseVersion) {
assert_eq!(lhs.partial_cmp(&rhs), Some(Ordering::Equal));
}
#[yare::parameterized(
minor_by_1 = { BaseVersion { major: 0, minor: 0 }, BaseVersion { major: 0, minor: 1 } },
major_by_1 = { BaseVersion { major: 1, minor: 0 }, BaseVersion { major: 2, minor: 0 } },
)]
fn less(lhs: BaseVersion, rhs: BaseVersion) {
assert_eq!(lhs.partial_cmp(&rhs), Some(Ordering::Less));
}
#[yare::parameterized(
minor_by_1 = { BaseVersion { major: 0, minor: 1 }, BaseVersion { major: 0, minor: 0 } },
major_by_1 = { BaseVersion { major: 1, minor: 0 }, BaseVersion { major: 0, minor: 0 } },
)]
fn greater(lhs: BaseVersion, rhs: BaseVersion) {
assert_eq!(lhs.partial_cmp(&rhs), Some(Ordering::Greater));
}
}
#[cfg(test)]
mod parse_base {
use crate::parsers::error::ExpectedError;
use crate::parsers::NumericError;
use crate::{BaseVersion, ParserError};
#[test]
fn ok() {
let version = BaseVersion::parse("1.2").unwrap();
assert_eq!(version, BaseVersion::new(1, 2));
}
#[test]
fn err_on_major_only() {
let result = BaseVersion::parse("1");
assert!(matches!(
result.unwrap_err(),
ParserError::Expected(ExpectedError::Separator { .. })
));
}
#[test]
fn err_on_not_finished() {
let result = BaseVersion::parse("1.2.3");
assert!(matches!(
result.unwrap_err(),
ParserError::Expected(ExpectedError::EndOfInput { .. })
));
}
#[test]
fn err_on_starts_with_0() {
let result = BaseVersion::parse("1.02");
assert!(matches!(
result.unwrap_err(),
ParserError::Numeric(NumericError::LeadingZero)
));
}
}