summaryrefslogtreecommitdiff
path: root/src/atom
diff options
context:
space:
mode:
authorJohn Turner <jturner.usa@gmail.com>2025-11-07 20:57:48 +0000
committerJohn Turner <jturner.usa@gmail.com>2025-11-08 22:13:14 +0000
commitb147d967d45092d6e289483e48ad4a91e3b89a14 (patch)
tree96fc18c245cd3e78e6371c367a474c9126d22486 /src/atom
parent5fd26e7c81899fabc066d8eefc7a8ec2b27e6351 (diff)
downloadgentoo-utils-b147d967d45092d6e289483e48ad4a91e3b89a14.tar.gz
put version and version operator in the same Option in the Atom struct
All atoms must either have a version with a version operator, or have no version and no version operator. Putting these in the same Option helps encode that into the type system.
Diffstat (limited to 'src/atom')
-rw-r--r--src/atom/mod.rs16
-rw-r--r--src/atom/parsers.rs51
2 files changed, 46 insertions, 21 deletions
diff --git a/src/atom/mod.rs b/src/atom/mod.rs
index ffb9c61..eb7537b 100644
--- a/src/atom/mod.rs
+++ b/src/atom/mod.rs
@@ -106,15 +106,23 @@ pub struct UseDep {
#[derive(Clone, Debug, Get)]
pub struct Atom {
blocker: Option<Blocker>,
- version_operator: Option<VersionOperator>,
category: Category,
name: Name,
- version: Option<Version>,
+ version: Option<(VersionOperator, Version)>,
slot: Option<Slot>,
#[get(kind = "deref")]
usedeps: Vec<UseDep>,
}
+impl Atom {
+ pub fn version_operator(&self) -> Option<VersionOperator> {
+ match self.version {
+ Some((operator, _)) => Some(operator),
+ None => None,
+ }
+ }
+}
+
impl fmt::Display for Blocker {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@@ -299,7 +307,7 @@ impl fmt::Display for Atom {
write!(f, "{blocker}")?;
}
- if let Some(version_operator) = self.version_operator.as_ref() {
+ if let Some(version_operator) = self.version_operator().as_ref() {
write!(f, "{version_operator}")?;
}
@@ -307,7 +315,7 @@ impl fmt::Display for Atom {
write!(f, "/")?;
write!(f, "{}", self.name)?;
- if let Some(version) = self.version.as_ref() {
+ if let Some((_, version)) = self.version.as_ref() {
write!(f, "-{version}")?;
}
diff --git a/src/atom/parsers.rs b/src/atom/parsers.rs
index f8a9f25..60f9223 100644
--- a/src/atom/parsers.rs
+++ b/src/atom/parsers.rs
@@ -253,36 +253,52 @@ impl<'a> Parseable<'a, &'a str> for Atom {
type Parser = impl Parser<&'a str, Output = Self>;
fn parser() -> Self::Parser {
- Blocker::parser()
+ let usedeps = || {
+ UseDep::parser()
+ .separated_by(tag(","))
+ .many()
+ .delimited_by(tag("["), tag("]"))
+ .opt()
+ };
+
+ let without_version = Blocker::parser()
.opt()
- .and(VersionOperator::parser().opt())
.and(Category::parser())
.and(Name::parser().preceded_by(tag("/")))
- .and(Version::parser().preceded_by(tag("-")).opt())
.and(Slot::parser().preceded_by(tag(":")).opt())
- .and(
- UseDep::parser()
- .separated_by(tag(","))
- .many()
- .delimited_by(tag("["), tag("]"))
- .opt(),
- )
+ .and(usedeps())
+ .map(|((((blocker, category), name), slot), usedeps)| Atom {
+ blocker,
+ category,
+ name,
+ version: None,
+ slot,
+ usedeps: usedeps.unwrap_or(Vec::new()),
+ });
+
+ let with_version = Blocker::parser()
+ .opt()
+ .and(VersionOperator::parser())
+ .and(Category::parser())
+ .and(Name::parser().preceded_by(tag("/")))
+ .and(Version::parser().preceded_by(tag("-")))
+ .and(Slot::parser().preceded_by(tag(":")).opt())
+ .and(usedeps())
.map(
|((((((blocker, version_operator), category), name), version), slot), usedeps)| {
Atom {
blocker,
- version_operator,
category,
name,
- version,
+ version: Some((version_operator, version)),
slot,
usedeps: usedeps.unwrap_or(Vec::new()),
}
},
)
- .verify_output(|atom| match (&atom.version_operator, &atom.version) {
- (Some(VersionOperator::Eq), Some(_)) => true,
- (Some(_), Some(version))
+ .verify_output(|atom| match &atom.version {
+ Some((VersionOperator::Eq, _)) => true,
+ Some((_, version))
if !version
.numbers()
.iter()
@@ -290,9 +306,10 @@ impl<'a> Parseable<'a, &'a str> for Atom {
{
true
}
- (None, None) => true,
_ => false,
- })
+ });
+
+ with_version.or(without_version)
}
}