From fb69d82e6f1dce4677114e717a5954bb9ab5c0e4 Mon Sep 17 00:00:00 2001 From: John Turner Date: Fri, 21 Nov 2025 04:33:55 +0000 Subject: [PATCH] build-id must not start with zero --- src/atom/mod.rs | 31 ++++++++++++++++++++++++++++--- src/atom/parsers.rs | 24 +++++++++++++++++++----- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/atom/mod.rs b/src/atom/mod.rs index 8cffa06..82cef15 100644 --- a/src/atom/mod.rs +++ b/src/atom/mod.rs @@ -58,13 +58,16 @@ pub struct VersionSuffix { #[derive(Debug, Clone, Get)] pub struct VersionSuffixes(#[get(method = "get", kind = "deref")] Vec); +#[derive(Debug, Clone, Get, PartialEq, Eq)] +pub struct BuildId(#[get(method = "get", kind = "deref")] String); + #[derive(Clone, Debug, Get)] pub struct Version { numbers: VersionNumbers, letter: Option, suffixes: VersionSuffixes, rev: Option, - build_id: Option, + build_id: Option, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -207,6 +210,22 @@ impl VersionNumber { } } +impl PartialOrd for BuildId { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for BuildId { + fn cmp(&self, other: &Self) -> Ordering { + // build-id may not start with a zero so we dont need to strip them + self.get() + .len() + .cmp(&other.get().len()) + .then_with(|| self.get().cmp(other.get())) + } +} + impl PartialEq for VersionSuffix { fn eq(&self, other: &Self) -> bool { self.kind == other.kind @@ -373,7 +392,7 @@ impl PartialEq for Version { (None, None) => true, } && match (&self.build_id, &other.build_id) { - (Some(a), Some(b)) => matches!(a.cmp_as_ints(b), Ordering::Equal), + (Some(a), Some(b)) => a == b, (Some(_), None) | (None, Some(_)) => false, (None, None) => true, } @@ -426,7 +445,7 @@ impl Ord for Version { } match (&self.build_id, &other.build_id) { - (Some(a), Some(b)) => a.cmp_as_ints(b), + (Some(a), Some(b)) => a.cmp(b), (Some(_), None) => Ordering::Greater, (None, Some(_)) => Ordering::Less, (None, None) => Ordering::Equal, @@ -484,6 +503,12 @@ impl fmt::Display for VersionNumber { } } +impl fmt::Display for BuildId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.get()) + } +} + impl fmt::Display for VersionSuffixKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/src/atom/parsers.rs b/src/atom/parsers.rs index 301409c..df0890f 100644 --- a/src/atom/parsers.rs +++ b/src/atom/parsers.rs @@ -1,15 +1,15 @@ use core::option::Option::None; use mon::{ - Parser, ParserIter, ascii_alphanumeric, ascii_numeric1, eof, r#if, input::InputIter, one_of, - tag, + Parser, ParserIter, ascii_alphanumeric, ascii_numeric, ascii_numeric1, eof, r#if, + input::InputIter, one_of, tag, }; use crate::{ Parseable, atom::{ - Atom, Blocker, Category, Cp, Cpv, Name, Repo, Slot, SlotName, SlotOperator, UseDep, - UseDepCondition, UseDepNegate, UseDepSign, Version, VersionNumber, VersionNumbers, + Atom, Blocker, BuildId, Category, Cp, Cpv, Name, Repo, Slot, SlotName, SlotOperator, + UseDep, UseDepCondition, UseDepNegate, UseDepSign, Version, VersionNumber, VersionNumbers, VersionOperator, VersionSuffix, VersionSuffixKind, VersionSuffixes, Wildcard, }, useflag::UseFlag, @@ -47,6 +47,20 @@ impl<'a> Parseable<'a, &'a str> for VersionNumber { } } +impl<'a> Parseable<'a, &'a str> for BuildId { + type Parser = impl Parser<&'a str, Output = Self>; + + fn parser() -> Self::Parser { + let start = ascii_numeric().and_not(tag("0")); + let rest = ascii_numeric().repeated().many(); + + start + .and(rest) + .recognize() + .map(|output: &str| BuildId(output.to_string())) + } +} + impl<'a> Parseable<'a, &'a str> for VersionSuffixKind { type Parser = impl Parser<&'a str, Output = Self>; @@ -97,7 +111,7 @@ impl<'a> Parseable<'a, &'a str> for Version { fn parser() -> Self::Parser { let rev = VersionNumber::parser().preceded_by(tag("-r")); - let build_id = VersionNumber::parser().preceded_by(tag("-")); + let build_id = BuildId::parser().preceded_by(tag("-")); VersionNumbers::parser() .and(r#if(|c: &char| c.is_ascii_alphabetic() && c.is_ascii_lowercase()).opt())