summaryrefslogtreecommitdiff
path: root/src/atom/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/atom/mod.rs')
-rw-r--r--src/atom/mod.rs772
1 files changed, 0 insertions, 772 deletions
diff --git a/src/atom/mod.rs b/src/atom/mod.rs
deleted file mode 100644
index 24cb555..0000000
--- a/src/atom/mod.rs
+++ /dev/null
@@ -1,772 +0,0 @@
-use core::{
- fmt::{self},
- option::Option,
-};
-use std::cmp::Ordering;
-
-use crate::useflag::UseFlag;
-
-use get::Get;
-
-use itertools::Itertools;
-
-mod parsers;
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum Blocker {
- Weak,
- Strong,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum VersionOperator {
- Lt,
- Gt,
- Eq,
- LtEq,
- GtEq,
- Roughly,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Get)]
-pub struct Category(#[get(method = "get", kind = "deref")] String);
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Get)]
-pub struct Name(#[get(method = "get", kind = "deref")] String);
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Get)]
-pub struct VersionNumber(#[get(method = "get", kind = "deref")] String);
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Get)]
-struct VersionNumbers(#[get(method = "get", kind = "deref")] Vec<VersionNumber>);
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum VersionSuffixKind {
- Alpha,
- Beta,
- Pre,
- Rc,
- P,
-}
-
-#[derive(Clone, Debug, Hash, PartialEq, Eq, Get)]
-pub struct VersionSuffix {
- kind: VersionSuffixKind,
- number: Option<VersionNumber>,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Get)]
-pub struct VersionSuffixes(#[get(method = "get", kind = "deref")] Vec<VersionSuffix>);
-
-#[derive(Debug, Clone, Get, PartialEq, Eq, Hash)]
-pub struct BuildId(#[get(method = "get", kind = "deref")] String);
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Get)]
-pub struct Version {
- numbers: VersionNumbers,
- letter: Option<char>,
- suffixes: VersionSuffixes,
- rev: Option<VersionNumber>,
- build_id: Option<BuildId>,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub struct Wildcard;
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum SlotOperator {
- Eq,
- Star,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Get)]
-pub struct SlotName(#[get(method = "name", kind = "deref")] String);
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub enum Slot {
- Wildcard,
- Equal,
- NameEqual {
- primary: SlotName,
- sub: Option<SlotName>,
- },
- Name {
- primary: SlotName,
- sub: Option<SlotName>,
- },
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum UseDepNegate {
- Minus,
- Exclamation,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum UseDepSign {
- Enabled,
- Disabled,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum UseDepCondition {
- Eq,
- Question,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct Repo(String);
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Get)]
-pub struct UseDep {
- negate: Option<UseDepNegate>,
- flag: UseFlag,
- sign: Option<UseDepSign>,
- condition: Option<UseDepCondition>,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Get)]
-pub struct Cp {
- category: Category,
- name: Name,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Get)]
-pub struct Cpv {
- category: Category,
- name: Name,
- version: Version,
- slot: Option<Slot>,
-}
-
-#[derive(Clone, Debug, Get, PartialEq, Eq, Hash)]
-pub struct Atom {
- blocker: Option<Blocker>,
- category: Category,
- name: Name,
- version: Option<(VersionOperator, Version, Option<Wildcard>)>,
- slot: Option<Slot>,
- repo: Option<Repo>,
- #[get(kind = "deref")]
- usedeps: Vec<UseDep>,
-}
-
-impl Cpv {
- #[must_use]
- pub fn into_cp(self) -> Cp {
- Cp {
- name: self.name,
- category: self.category,
- }
- }
-}
-
-impl Atom {
- #[must_use]
- pub fn version_operator(&self) -> Option<VersionOperator> {
- self.version.clone().map(|(oper, _, _)| oper)
- }
-
- #[must_use]
- pub fn into_cp(self) -> Cp {
- Cp {
- category: self.category,
- name: self.name,
- }
- }
-
- #[must_use]
- pub fn into_cpv(self) -> Option<Cpv> {
- match self.version {
- Some((_, version, _)) => Some(Cpv {
- category: self.category,
- name: self.name,
- version,
- slot: self.slot,
- }),
- None => None,
- }
- }
-}
-
-impl VersionNumber {
- #[must_use]
- pub fn cmp_as_ints(&self, other: &Self) -> Ordering {
- let a = self.get().trim_start_matches('0');
- let b = other.get().trim_start_matches('0');
-
- a.len().cmp(&b.len()).then_with(|| a.cmp(b))
- }
-
- #[must_use]
- pub fn cmp_as_str(&self, other: &Self) -> Ordering {
- if self.get().starts_with('0') || other.get().starts_with('0') {
- let a = self.get().trim_end_matches('0');
- let b = other.get().trim_end_matches('0');
-
- a.cmp(b)
- } else {
- self.cmp_as_ints(other)
- }
- }
-}
-
-impl PartialOrd for BuildId {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- 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 PartialOrd for VersionSuffix {
- fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for VersionSuffix {
- fn cmp(&self, other: &Self) -> Ordering {
- match &self.kind.cmp(&other.kind) {
- Ordering::Less => Ordering::Less,
- Ordering::Greater => Ordering::Greater,
- Ordering::Equal => match (&self.number, &other.number) {
- (Some(a), Some(b)) => a.cmp_as_ints(b),
- (Some(a), None) if a.get().chars().all(|c| c == '0') => Ordering::Equal,
- (None, Some(b)) if b.get().chars().all(|c| c == '0') => Ordering::Equal,
- (Some(_), None) => Ordering::Greater,
- (None, Some(_)) => Ordering::Less,
- (None, None) => Ordering::Equal,
- },
- }
- }
-}
-
-impl PartialOrd for VersionSuffixes {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for VersionSuffixes {
- fn cmp(&self, other: &Self) -> Ordering {
- let mut a = self.get().iter();
- let mut b = other.get().iter();
-
- loop {
- match (a.next(), b.next()) {
- (Some(a), Some(b)) => match a.cmp(b) {
- Ordering::Less => break Ordering::Less,
- Ordering::Greater => break Ordering::Greater,
- Ordering::Equal => (),
- },
- (Some(a), None) if matches!(a.kind, VersionSuffixKind::P) => {
- break Ordering::Greater;
- }
- (Some(_), None) => break Ordering::Less,
- (None, Some(b)) if matches!(b.kind, VersionSuffixKind::P) => break Ordering::Less,
- (None, Some(_)) => break Ordering::Greater,
- (None, None) => break Ordering::Equal,
- }
- }
- }
-}
-
-impl PartialOrd for VersionNumbers {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for VersionNumbers {
- fn cmp(&self, other: &Self) -> Ordering {
- match self
- .get()
- .first()
- .unwrap()
- .cmp_as_ints(other.get().first().unwrap())
- {
- Ordering::Less => Ordering::Less,
- Ordering::Greater => Ordering::Greater,
- Ordering::Equal => {
- let mut a = self.get().iter().skip(1);
- let mut b = other.get().iter().skip(1);
-
- loop {
- match (a.next(), b.next()) {
- (Some(a), Some(b)) => match a.cmp_as_str(b) {
- Ordering::Less => break Ordering::Less,
- Ordering::Greater => break Ordering::Greater,
- Ordering::Equal => (),
- },
-
- (Some(_), None) => break Ordering::Greater,
- (None, Some(_)) => break Ordering::Less,
- (None, None) => break Ordering::Equal,
- }
- }
- }
- }
- }
-}
-
-impl PartialOrd for Version {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for Version {
- fn cmp(&self, other: &Self) -> Ordering {
- match self.numbers.cmp(&other.numbers) {
- Ordering::Less => return Ordering::Less,
- Ordering::Greater => return Ordering::Greater,
- Ordering::Equal => (),
- }
-
- match (self.letter, other.letter) {
- (Some(a), Some(b)) if a < b => return Ordering::Less,
- (Some(a), Some(b)) if a > b => return Ordering::Greater,
- (Some(a), Some(b)) if a == b => (),
- (Some(_), None) => return Ordering::Greater,
- (None, Some(_)) => return Ordering::Less,
- (None, None) => (),
- _ => unreachable!(),
- }
-
- match self.suffixes.cmp(&other.suffixes) {
- Ordering::Less => return Ordering::Less,
- Ordering::Greater => return Ordering::Greater,
- Ordering::Equal => (),
- }
-
- match (&self.rev, &other.rev) {
- (Some(a), Some(b)) => match a.cmp_as_ints(b) {
- Ordering::Less => return Ordering::Less,
- Ordering::Greater => return Ordering::Greater,
- Ordering::Equal => (),
- },
- (Some(a), None) if a.get().chars().all(|c| c == '0') => (),
- (Some(_), None) => return Ordering::Greater,
- (None, Some(b)) if b.get().chars().all(|c| c == '0') => (),
- (None, Some(_)) => return Ordering::Less,
- (None, None) => (),
- }
-
- match (&self.build_id, &other.build_id) {
- (Some(a), Some(b)) => a.cmp(b),
- (Some(_), None) => Ordering::Greater,
- (None, Some(_)) => Ordering::Less,
- (None, None) => Ordering::Equal,
- }
- }
-}
-
-impl PartialOrd for Cpv {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- if self.category == other.category && self.name == other.name {
- Some(self.version.cmp(&other.version))
- } else {
- None
- }
- }
-}
-
-impl fmt::Display for Blocker {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::Weak => write!(f, "!"),
- Self::Strong => write!(f, "!!"),
- }
- }
-}
-
-impl fmt::Display for VersionOperator {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::Lt => write!(f, "<"),
- Self::Gt => write!(f, ">"),
- Self::Eq => write!(f, "="),
- Self::LtEq => write!(f, "<="),
- Self::GtEq => write!(f, ">="),
- Self::Roughly => write!(f, "~"),
- }
- }
-}
-
-impl fmt::Display for Category {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.0)
- }
-}
-
-impl fmt::Display for Name {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.0)
- }
-}
-
-impl fmt::Display for VersionNumber {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.0)
- }
-}
-
-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 {
- Self::Alpha => write!(f, "alpha"),
- Self::Beta => write!(f, "beta"),
- Self::Pre => write!(f, "pre"),
- Self::Rc => write!(f, "rc"),
- Self::P => write!(f, "p"),
- }
- }
-}
-
-impl fmt::Display for VersionSuffix {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.kind)?;
-
- if let Some(number) = self.number.as_ref() {
- write!(f, "{number}")?;
- }
-
- Ok(())
- }
-}
-
-impl fmt::Display for Version {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let numbers = self
- .numbers
- .get()
- .iter()
- .map(VersionNumber::get)
- .intersperse(".")
- .collect::<String>();
-
- let suffixes = self
- .suffixes
- .get()
- .iter()
- .map(VersionSuffix::to_string)
- .intersperse("_".to_string())
- .collect::<String>();
-
- write!(f, "{numbers}")?;
-
- if let Some(letter) = self.letter {
- write!(f, "{letter}")?;
- }
-
- if !suffixes.is_empty() {
- write!(f, "_{suffixes}")?;
- }
-
- if let Some(rev) = self.rev.as_ref() {
- write!(f, "-r{rev}")?;
- }
-
- if let Some(build_id) = self.build_id.as_ref() {
- write!(f, "-{build_id}")?;
- }
-
- Ok(())
- }
-}
-
-impl fmt::Display for SlotOperator {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::Eq => write!(f, "="),
- Self::Star => write!(f, "*"),
- }
- }
-}
-
-impl fmt::Display for SlotName {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.0)
- }
-}
-
-impl fmt::Display for Slot {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::Wildcard => write!(f, "*"),
- Self::Equal => {
- write!(f, "=")
- }
- Self::NameEqual { primary, sub } => {
- write!(f, "{primary}")?;
-
- if let Some(sub) = sub {
- write!(f, "/{sub}")?;
- }
-
- write!(f, "=")
- }
- Self::Name { primary, sub } => {
- write!(f, "{primary}")?;
-
- if let Some(sub) = sub {
- write!(f, "/{sub}")?;
- }
-
- Ok(())
- }
- }
- }
-}
-
-impl fmt::Display for UseDepNegate {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::Minus => write!(f, "-"),
- Self::Exclamation => write!(f, "!"),
- }
- }
-}
-
-impl fmt::Display for UseDepSign {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::Enabled => write!(f, "(+)"),
- Self::Disabled => write!(f, "(-)"),
- }
- }
-}
-
-impl fmt::Display for UseDepCondition {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::Eq => write!(f, "="),
- Self::Question => write!(f, "?"),
- }
- }
-}
-
-impl fmt::Display for UseDep {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- if let Some(negate) = self.negate.as_ref() {
- write!(f, "{negate}")?;
- }
-
- write!(f, "{}", self.flag)?;
-
- if let Some(sign) = self.sign.as_ref() {
- write!(f, "{sign}")?;
- }
-
- if let Some(condition) = self.condition.as_ref() {
- write!(f, "{condition}")?;
- }
-
- Ok(())
- }
-}
-
-impl fmt::Display for Cp {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}/{}", &self.category, &self.name)
- }
-}
-
-impl fmt::Display for Cpv {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}/{}-{}", &self.category, &self.name, &self.version)?;
-
- if let Some(slot) = self.slot.as_ref() {
- write!(f, ":{slot}")?;
- }
-
- Ok(())
- }
-}
-
-impl fmt::Display for Atom {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- if let Some(blocker) = self.blocker.as_ref() {
- write!(f, "{blocker}")?;
- }
-
- if let Some(version_operator) = self.version_operator().as_ref() {
- write!(f, "{version_operator}")?;
- }
-
- write!(f, "{}", self.category)?;
- write!(f, "/")?;
- write!(f, "{}", self.name)?;
-
- 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() {
- write!(f, ":{slot}")?;
- }
-
- let usedeps = self
- .usedeps
- .iter()
- .map(UseDep::to_string)
- .intersperse(",".to_string())
- .collect::<String>();
-
- if !usedeps.is_empty() {
- write!(f, "[{usedeps}]")?;
- }
-
- Ok(())
- }
-}
-
-#[cfg(test)]
-mod test {
- use mon::{Parser, input::InputIter};
-
- use super::*;
-
- use crate::Parseable;
-
- macro_rules! assert_cmp_display {
- ($a:expr, $b:expr, $ordering:expr) => {
- if $a.cmp(&$b) != $ordering {
- panic!("{} ~ {} != {:?}", $a, $b, $ordering)
- }
- };
- }
-
- macro_rules! assert_partial_cmp_display {
- ($a:expr, $b:expr, $ordering:expr) => {
- if $a.partial_cmp(&$b) != $ordering {
- panic!("{} ~ {} != {:?}", $a, $b, $ordering)
- }
- };
- }
-
- #[test]
- fn test_version_display() {
- let s = "1.0.0_alpha1_beta1-r1";
- let version = Version::parser().parse_finished(InputIter::new(s)).unwrap();
-
- assert_eq!(version.to_string().as_str(), s);
- }
-
- #[test]
- fn test_display_atom() {
- let s = "!!>=foo/bar-1.0.0v_alpha1_beta1-r1:slot/sub=[a,b,c]";
- let atom = Atom::parser().parse_finished(InputIter::new(s)).unwrap();
-
- assert_eq!(atom.to_string().as_str(), s);
- }
-
- #[test]
- fn test_version_cmp() {
- let versions = [
- ("1.0.1", "1.0", Ordering::Greater),
- ("1.0.0", "1.0.0_alpha", Ordering::Greater),
- ("1.0.0_alpha", "1.0.0_alpha_p", Ordering::Less),
- ("1.0.0-r0", "1.0.0", Ordering::Equal),
- ("1.0.0-r0000", "1.0.0", Ordering::Equal),
- ("1.0.0-r1-1", "1.0.0-r1-2", Ordering::Less),
- ];
-
- for (a, b, ordering) in versions.iter().map(|(a, b, ordering)| {
- (
- Version::parser().parse_finished(InputIter::new(a)).unwrap(),
- Version::parser().parse_finished(InputIter::new(b)).unwrap(),
- ordering,
- )
- }) {
- assert_cmp_display!(a, b, *ordering);
- }
- }
-
- #[test]
- fn test_cpv_eq() {
- let cpvs = [
- ("foo/bar-1", "foo/bar-1", Some(Ordering::Equal)),
- ("foo/baz-1", "foo/bar-1", None),
- ];
-
- for (a, b, ordering) in cpvs.iter().copied().map(|(a, b, ordering)| {
- (
- Cpv::parser().parse_finished(InputIter::new(a)).unwrap(),
- Cpv::parser().parse_finished(InputIter::new(b)).unwrap(),
- ordering,
- )
- }) {
- assert_partial_cmp_display!(a, b, ordering);
- }
- }
-
- #[test]
- fn test_version_cmp_letter() {
- let a = Version::parser()
- .parse_finished(InputIter::new("1.0.0"))
- .unwrap();
- let b = Version::parser()
- .parse_finished(InputIter::new("1.0.0a"))
- .unwrap();
-
- assert_cmp_display!(a, b, Ordering::Less);
- }
-
- #[test]
- fn test_version_cmp_where_b_has_leading_zeros() {
- let a = Version::parser()
- .parse_finished(InputIter::new("1.2"))
- .unwrap();
- let b = Version::parser()
- .parse_finished(InputIter::new("1.054"))
- .unwrap();
-
- assert_cmp_display!(a, b, Ordering::Greater);
- }
-
- #[test]
- fn test_version_has_more_zeros() {
- let a = Version::parser()
- .parse_finished(InputIter::new("1.0.0"))
- .unwrap();
- let b = Version::parser()
- .parse_finished(InputIter::new("1.0"))
- .unwrap();
-
- assert_cmp_display!(a, b, Ordering::Greater);
- }
-
- #[test]
- fn test_fuzzer_cases() {
- let control = Version::parser()
- .parse_finished(InputIter::new("1.2.0a_alpha1_beta2-r1-8"))
- .unwrap();
-
- #[allow(clippy::single_element_loop)]
- for (version_str, expected) in [("1.2.0", Ordering::Greater)] {
- let version = Version::parser()
- .parse_finished(InputIter::new(version_str))
- .unwrap();
-
- assert_cmp_display!(control, version, expected);
- }
- }
-}