mercur 0.1.4

mercur - junolang package manager
use chrono::DateTime;

use crate::registry::compile::parse::PkgVersion;

/// Parsed semantic version.
///
/// This is an intermediate representation used during compilation.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct SemVersion {
    pub major: u16,
    pub minor: u8,
    pub patch: u8,
    pub tag: Option<String>,
}

impl Ord for SemVersion {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.major
            .cmp(&other.major)
            .then(self.minor.cmp(&other.minor))
            .then(self.patch.cmp(&other.patch))
            .then(self.tag.cmp(&other.tag))
    }
}

impl PartialOrd for SemVersion {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl SemVersion {
    pub fn parse(version: &str) -> Self {
        let mut split = version.splitn(2, '-');

        let numbers = split.next().unwrap_or("0.0.0");

        let tag = split.next().map(ToOwned::to_owned);

        let mut nums = numbers.split('.');

        Self {
            major: nums.next().unwrap_or("0").parse().unwrap_or(0),
            minor: nums.next().unwrap_or("0").parse().unwrap_or(0),
            patch: nums.next().unwrap_or("0").parse().unwrap_or(0),
            tag,
        }
    }
}

/// RFC3339 → unix timestamp
pub fn parse_date(date: &str) -> u64 {
    DateTime::parse_from_rfc3339(date)
        .map(|d| d.timestamp() as u64)
        .unwrap_or(0)
}

/// Sorts versions by SemVer ascending.
pub fn sort_versions(versions: &mut Vec<PkgVersion>) {
    versions.sort_by(|a, b| {
        let a = SemVersion::parse(&a.version);
        let b = SemVersion::parse(&b.version);

        a.cmp(&b)
    });
}