use core::{ fmt::{self}, option::Option, }; use crate::useflag::UseFlag; use get::Get; use itertools::Itertools; pub mod parsers; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Blocker { Weak, Strong, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum VersionOperator { Lt, Gt, Eq, LtEq, GtEq, Roughly, } #[derive(Clone, Debug, PartialEq, Eq, Get)] pub struct Category(#[get(method = "get")] String); #[derive(Clone, Debug, PartialEq, Eq, Get)] pub struct Name(#[get(method = "get")] String); #[derive(Clone, Debug, Get)] pub struct VersionNumber(#[get(method = "get")] String); #[derive(Clone, Copy, Debug)] pub enum VersionSuffixKind { Alpha, Beta, Pre, Rc, P, } #[derive(Clone, Debug, Get)] pub struct VersionSuffix { kind: VersionSuffixKind, number: Option, } #[derive(Clone, Debug, Get)] pub struct Version { numbers: Vec, letter: Option, suffixes: Vec, rev: Option, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum SlotOperator { Eq, Star, } #[derive(Clone, Debug, PartialEq, Eq, Get)] pub struct SlotName(#[get(method = "name")] String); #[derive(Clone, Debug, PartialEq, Eq, Get)] pub struct Slot { slot: Option, sub: Option, operator: Option, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum UseDepNegate { Minus, Exclamation, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum UseDepSign { Enabled, Disabled, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum UseDepCondition { Eq, Question, } #[derive(Clone, Debug, PartialEq, Eq, Get)] pub struct UseDep { negate: Option, flag: UseFlag, sign: Option, condition: Option, } #[derive(Clone, Debug, Get)] pub struct Atom { blocker: Option, version_operator: Option, category: Category, name: Name, version: Option, slot: Option, usedeps: Vec, } 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 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 .iter() .map(|n| n.get().as_str()) .intersperse(".") .collect::(); let suffixes = self .suffixes .iter() .map(|s| s.to_string()) .intersperse("_".to_string()) .collect::(); write!(f, "{}", numbers)?; if let Some(letter) = self.letter { write!(f, "{letter}")?; } if suffixes.len() > 0 { write!(f, "_{}", suffixes)?; } if let Some(rev) = self.rev.as_ref() { write!(f, "-r{rev}")?; } 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 { if let Some(slot) = self.slot.as_ref() { write!(f, "{slot}")?; } if let Some(sub) = self.sub.as_ref() { write!(f, "/{sub}")?; } if let Some(operator) = self.operator.as_ref() { write!(f, "{operator}")?; } 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 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) = self.version.as_ref() { write!(f, "-{version}")?; } if let Some(slot) = self.slot.as_ref() { write!(f, ":{slot}")?; } let usedeps = self .usedeps .iter() .map(|u| u.to_string()) .intersperse(",".to_string()) .collect::(); if !usedeps.is_empty() { write!(f, "[{usedeps}]")?; } Ok(()) } } #[cfg(test)] mod test { use mon::{Parser, input::InputIter}; use crate::atom::parsers; #[test] fn test_version_display() { let s = "1.0.0_alpha1_beta1-r1"; let version = parsers::version() .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 = parsers::atom().parse_finished(InputIter::new(s)).unwrap(); assert_eq!(atom.to_string().as_str(), s); } }