diff --git a/src/atom/mod.rs b/src/atom/mod.rs index 8da7468..3be42bb 100644 --- a/src/atom/mod.rs +++ b/src/atom/mod.rs @@ -66,6 +66,9 @@ pub struct Version { rev: Option, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Wildcard; + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum SlotOperator { Eq, @@ -127,7 +130,7 @@ pub struct Atom { blocker: Option, category: Category, name: Name, - version: Option<(VersionOperator, Version)>, + version: Option<(VersionOperator, Version, Option)>, slot: Option, #[get(kind = "deref")] usedeps: Vec, @@ -146,7 +149,7 @@ impl Cpv { impl Atom { #[must_use] pub fn version_operator(&self) -> Option { - self.version.clone().map(|(oper, _)| oper) + self.version.clone().map(|(oper, _, _)| oper) } #[must_use] @@ -160,7 +163,7 @@ impl Atom { #[must_use] pub fn into_cpv(self) -> Option { match self.version { - Some((_, version)) => Some(Cpv { + Some((_, version, _)) => Some(Cpv { category: self.category, name: self.name, version, @@ -639,8 +642,10 @@ impl fmt::Display for Atom { write!(f, "/")?; write!(f, "{}", self.name)?; - if let Some((_, version)) = self.version.as_ref() { + if let Some((_, version, None)) = self.version() { write!(f, "-{version}")?; + } else if let Some((_, version, Some(_))) = self.version() { + write!(f, "-{version}*")?; } if let Some(slot) = self.slot.as_ref() { diff --git a/src/atom/parsers.rs b/src/atom/parsers.rs index 6cd658e..7bcf5c6 100644 --- a/src/atom/parsers.rs +++ b/src/atom/parsers.rs @@ -7,7 +7,7 @@ use crate::{ atom::{ Atom, Blocker, Category, Cp, Cpv, Name, Slot, SlotName, SlotOperator, UseDep, UseDepCondition, UseDepNegate, UseDepSign, Version, VersionNumber, VersionNumbers, - VersionOperator, VersionSuffix, VersionSuffixKind, VersionSuffixes, + VersionOperator, VersionSuffix, VersionSuffixKind, VersionSuffixes, Wildcard, }, useflag::UseFlag, }; @@ -72,9 +72,6 @@ impl<'a> Parseable<'a, &'a str> for VersionNumbers { fn parser() -> Self::Parser { VersionNumber::parser() - .followed_by(tag("*").opt()) - .recognize() - .map(|output: &str| VersionNumber(output.to_string())) .separated_by(tag(".")) .at_least(1) .map(VersionNumbers) @@ -307,33 +304,30 @@ impl<'a> Parseable<'a, &'a str> for Atom { .and(Category::parser()) .and(Name::parser().preceded_by(tag("/"))) .and(Version::parser().preceded_by(tag("-"))) + .and(tag("*").map(|_| Wildcard).opt()) .and(Slot::parser().preceded_by(tag(":")).opt()) .and(usedeps()) + .verify_output(|(((((((_, version_operator), _), _), _), star), _), _)| { + matches!( + (version_operator, star), + (VersionOperator::Eq, Some(_) | None) | (_, None) + ) + }) .map( - |((((((blocker, version_operator), category), name), version), slot), usedeps)| { + |( + ((((((blocker, version_operator), category), name), version), star), slot), + usedeps, + )| { Atom { blocker, category, name, - version: Some((version_operator, version)), + version: Some((version_operator, version, star)), slot, usedeps: usedeps.unwrap_or(Vec::new()), } }, - ) - .verify_output(|atom| match &atom.version { - Some((VersionOperator::Eq, _)) => true, - Some((_, version)) - if !version - .numbers() - .get() - .iter() - .any(|number| number.get().contains('*')) => - { - true - } - _ => false, - }); + ); with_version.or(without_version) } @@ -513,6 +507,7 @@ mod test { let atoms = [ "media-libs/libsdl2[haptitick(+),sound(+)vd,eio(+)]", "=kde-frameworks/kcodecs-6.19*86", + "=dev-ml/stdio-0.17*t:=[ocamlopt?]", ]; for atom in atoms {