354 lines
7.8 KiB
Rust
354 lines
7.8 KiB
Rust
use core::{
|
|
fmt::{self, write},
|
|
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<VersionNumber>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Get)]
|
|
pub struct Version {
|
|
numbers: Vec<VersionNumber>,
|
|
letter: Option<char>,
|
|
suffixes: Vec<VersionSuffix>,
|
|
rev: Option<VersionNumber>,
|
|
}
|
|
|
|
#[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<SlotName>,
|
|
sub: Option<SlotName>,
|
|
operator: Option<SlotOperator>,
|
|
}
|
|
|
|
#[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<UseDepNegate>,
|
|
flag: UseFlag,
|
|
sign: Option<UseDepSign>,
|
|
condition: Option<UseDepCondition>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Get)]
|
|
pub struct Atom {
|
|
blocker: Option<Blocker>,
|
|
version_operator: Option<VersionOperator>,
|
|
category: Category,
|
|
name: Name,
|
|
version: Option<Version>,
|
|
slot: Option<Slot>,
|
|
usedeps: Vec<UseDep>,
|
|
}
|
|
|
|
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::<String>();
|
|
|
|
let suffixes = self
|
|
.suffixes
|
|
.iter()
|
|
.map(|s| s.to_string())
|
|
.intersperse("_".to_string())
|
|
.collect::<String>();
|
|
|
|
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::<String>();
|
|
|
|
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);
|
|
}
|
|
}
|