use crate::pkg::{Op, Rstr};
use anyhow::{anyhow, Context};
use lazy_static::lazy_static;
use regex::Regex;
use std::{
cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
fmt::{Display, Formatter, Result},
str::FromStr,
};
pub struct Dep {
pub pkg_name: String,
pub rstr: Option<Rstr>,
}
impl Display for Dep {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match &self.rstr {
Some(rstr) => write!(f, "{} {}", self.pkg_name, rstr),
None => write!(f, "{}", self.pkg_name),
}
}
}
impl Ord for Dep {
fn cmp(&self, other: &Self) -> Ordering {
self.pkg_name.cmp(&other.pkg_name)
}
}
impl PartialOrd for Dep {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for Dep {
fn eq(&self, other: &Self) -> bool {
self.pkg_name == other.pkg_name
}
}
impl Eq for Dep {}
impl FromStr for Dep {
type Err = anyhow::Error;
fn from_str(s: &str) -> anyhow::Result<Self> {
lazy_static! {
static ref RE: Regex = Regex::new(r"^([^<>=]+)(=|<|>|<=|>=)?([^<>=]*)$").unwrap();
}
let err_msg = format!("'{s}' is not a valid dependency");
if !RE.is_match(s) {
return Err(anyhow!(err_msg));
}
let captures = RE.captures(s).unwrap();
if captures.get(2).is_none() {
Ok(Dep {
pkg_name: s.trim().to_string(),
rstr: None,
})
} else {
Ok(Dep {
pkg_name: captures.get(1).unwrap().as_str().trim().to_string(),
rstr: Some(Rstr {
op: Op::from_str(captures.get(2).unwrap().as_str().trim())
.with_context(|| err_msg)?,
version: captures.get(3).unwrap().as_str().trim().to_string(),
}),
})
}
}
}
pub struct OptDep {
pub pkg_name: String,
pub comment: Option<String>,
}
impl Display for OptDep {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match &self.comment {
Some(comment) => write!(f, "{} // {}", self.pkg_name, comment),
None => write!(f, "{}", self.pkg_name),
}
}
}
impl Ord for OptDep {
fn cmp(&self, other: &Self) -> Ordering {
self.pkg_name.cmp(&other.pkg_name)
}
}
impl PartialOrd for OptDep {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for OptDep {
fn eq(&self, other: &Self) -> bool {
self.pkg_name == other.pkg_name
}
}
impl Eq for OptDep {}
impl FromStr for OptDep {
type Err = anyhow::Error;
fn from_str(s: &str) -> anyhow::Result<Self> {
lazy_static! {
static ref RE: Regex = Regex::new(r"^([^:]+)(: *)?(.*)$").unwrap();
}
let err_msg = format!("'{s}' is not a valid optional dependency");
if !RE.is_match(s) {
return Err(anyhow!(err_msg));
}
let captures = RE.captures(s).unwrap();
if captures.get(2).is_none() {
Ok(OptDep {
pkg_name: s.trim().to_string(),
comment: None,
})
} else {
Ok(OptDep {
pkg_name: captures.get(1).unwrap().as_str().trim().to_string(),
comment: Some(captures.get(3).unwrap().as_str().trim().to_string()),
})
}
}
}