use serde::{Serialize, Deserialize};
use crate::vendors::Vendor;
#[derive(Clone, Debug, Serialize, Deserialize, Eq, Ord)]
pub struct Package {
pub name: String,
pub vendor: Vendor,
pub version: Option<String>,
pub repo: Option<String>,
}
impl Package {
fn ordering_string(&self) -> String {
format!("{}::{}", self.vendor, self.to_string())
}
fn archlinux_ordering_string(&self) -> String {
format!("{}::{}", self.archlinux_repo_prefix(), self.to_string())
}
fn archlinux_repo_prefix(&self) -> String {
if let Some(repo) = &self.repo {
match repo.as_str() {
"core" => "0",
"extra" => "1",
"multilib" => "2",
"extra-testing" => "3",
"multilib-testing" => "4",
"chaotic-aur" => "6",
"aur" => "8",
_ => "5",
}.to_string()
} else {
"7".to_string()
}
}
}
impl PartialEq for Package {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.vendor == self.vendor
}
}
impl PartialOrd for Package {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
let vendor1 =
match self.vendor {
Vendor::Pacman |
Vendor::Rua |
Vendor::Yay => self.archlinux_ordering_string(),
_ => self.ordering_string(),
};
let vendor2 =
match other.vendor {
Vendor::Pacman |
Vendor::Rua |
Vendor::Yay => self.archlinux_ordering_string(),
_ => self.ordering_string(),
};
vendor1.partial_cmp(&vendor2)
}
}
impl ToString for Package {
fn to_string(&self) -> String {
let mut res = self.name.clone();
if let Some(repo) = &self.repo {
res = format!("{}/{}", repo, self.name);
}
if let Some(version) = &self.version {
res.push_str(&self.vendor.version_sep());
res.push_str(version);
}
res
}
}
impl From<&str> for Package {
fn from(s: &str) -> Self {
let mut name: String;
let mut version = None;
let mut repo = None;
match s.rfind('/') {
Some(idx) => {
name = s[idx + 1..].to_string();
let _ = repo.insert(s[..idx].to_string());
},
None => name = s.to_string(),
}
match name.rfind('@') {
Some(idx) => {
let _ = version.insert(name[idx + 1..].to_string());
name = name[..idx].to_string();
},
None => (),
}
if version.is_none() {
match name.rfind('=') {
Some(idx) => {
let _ = version.insert(name[idx + 1..].to_string());
name = name[..idx].to_string();
},
None => (),
}
}
if version.is_none() {
match name.rfind("//") {
Some(idx) => {
let _ = version.insert(name[idx + 2..].to_string());
name = name[..idx].to_string();
},
None => (),
}
}
Package { name, version, repo, vendor: Vendor::default() }
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PackageFile {
pub installed: Vec<Package>,
}