feat: add package identifiers
This commit is contained in:
parent
6e30a8bed7
commit
a0416cf6a9
5 changed files with 185 additions and 1 deletions
114
pkgr/src/package/identifier.rs
Normal file
114
pkgr/src/package/identifier.rs
Normal file
|
@ -0,0 +1,114 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PackageIdentifierError {
|
||||
InvalidPackageLocator(String),
|
||||
InvalidURI(String),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PackageIdentifierError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
PackageIdentifierError::InvalidPackageLocator(s) => write!(f, "Invalid package locator: {}", s),
|
||||
PackageIdentifierError::InvalidURI(s) => write!(f, "Invalid URI: {}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PackageIdentifier {
|
||||
PackageLocator(PackageLocator),
|
||||
URI(String),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PackageIdentifier {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
PackageIdentifier::PackageLocator(pl) => write!(f, "{}", pl),
|
||||
PackageIdentifier::URI(uri) => write!(f, "{}", uri),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PackageLocator {
|
||||
pub name: String,
|
||||
pub version: Option<u32>,
|
||||
pub tags: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PackageLocator {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let mut s = self.name.clone();
|
||||
if let Some(version) = self.version {
|
||||
s += &*format!("@{}", version);
|
||||
}
|
||||
if let Some(tags) = &self.tags {
|
||||
s += &*format!(":{}", tags.join(","));
|
||||
}
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for PackageIdentifier {
|
||||
type Err = PackageIdentifierError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let uri_re = regex::Regex::new(r"^[a-zA-Z0-9]+://").unwrap();
|
||||
if uri_re.is_match(s) {
|
||||
// there needs to be stuff after the protocol
|
||||
let split = s.split("://").collect::<Vec<&str>>();
|
||||
if split.len() != 2 || split[1].is_empty() {
|
||||
return Err(PackageIdentifierError::InvalidURI(s.to_string()));
|
||||
}
|
||||
Ok(PackageIdentifier::URI(s.to_string()))
|
||||
} else {
|
||||
let pl = match PackageLocator::from_str(s) {
|
||||
Ok(pl) => pl,
|
||||
Err(e) => return Err(PackageIdentifierError::InvalidPackageLocator(e.to_string())),
|
||||
};
|
||||
Ok(PackageIdentifier::PackageLocator(pl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for PackageLocator {
|
||||
type Err = PackageIdentifierError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
#[allow(unused_assignments)] // false positive
|
||||
let mut name = None;
|
||||
let mut version = None;
|
||||
let mut tags = None;
|
||||
|
||||
if s.is_empty() {
|
||||
return Err(PackageIdentifierError::InvalidPackageLocator(s.to_string()));
|
||||
}
|
||||
|
||||
let name_re = Regex::new("^([A-Za-z][A-Za-z0-9_.]+)").unwrap();
|
||||
let version_re = Regex::new("@([0-9]+)").unwrap();
|
||||
let tags_re = Regex::new(":([a-zA-Z0-9,._]+)").unwrap();
|
||||
|
||||
if let Some(caps) = name_re.captures(s) {
|
||||
name = Some(caps.get(1).unwrap().as_str().to_string());
|
||||
} else {
|
||||
return Err(PackageIdentifierError::InvalidPackageLocator(s.to_string()));
|
||||
}
|
||||
|
||||
if let Some(caps) = version_re.captures(s) {
|
||||
version = Some(caps.get(1).unwrap().as_str().parse::<u32>().unwrap());
|
||||
}
|
||||
|
||||
if let Some(caps) = tags_re.captures(s) {
|
||||
tags = Some(caps.get(1).unwrap().as_str().split(",").map(|s| s.to_string()).collect());
|
||||
}
|
||||
|
||||
Ok(PackageLocator {
|
||||
name: name.unwrap(),
|
||||
version,
|
||||
tags,
|
||||
})
|
||||
}
|
||||
}
|
1
pkgr/src/package/mod.rs
Normal file
1
pkgr/src/package/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod identifier;
|
Loading…
Add table
Add a link
Reference in a new issue