mod mediatype;
mod parser;
use crate::digest::Digest;
pub use mediatype::MediaType;
#[derive(thiserror::Error, Debug)]
pub enum ParseError {
#[error("Missing repository.")]
MissingRepository,
#[error("{0}")]
InvalidDigest(#[from] crate::digest::DigestError),
}
#[derive(Clone, Debug, PartialEq)]
pub struct Reference<'a> {
pub registry: &'a str,
pub repository: Repository<'a>,
pub tag: &'a str,
pub digest: Option<Digest>,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Repository<'a>(RepositoryInner<'a>);
impl<'a> Repository<'a> {
pub(crate) fn components(namespace: &'a str, name: &'a str) -> Self {
Repository(RepositoryInner::Components(namespace, name))
}
pub(crate) fn full(name: &'a str) -> Self {
Repository(RepositoryInner::Full(name))
}
pub fn name(&self) -> &str {
match self.0 {
RepositoryInner::Full(full) => full.split_once('/').map(|s| s.1).unwrap_or(full),
RepositoryInner::Components(_, name) => name,
}
}
pub fn namespace(&self) -> Option<&str> {
match self.0 {
RepositoryInner::Full(full) => full.split_once('/').map(|s| s.0),
RepositoryInner::Components(ns, _) => Some(ns),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
enum RepositoryInner<'a> {
Full(&'a str),
Components(&'a str, &'a str),
}
impl std::fmt::Display for Repository<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.0 {
RepositoryInner::Full(full) => f.write_str(full),
RepositoryInner::Components(a, b) => write!(f, "{a}/{b}"),
}
}
}
impl<'a> TryFrom<&'a str> for Reference<'a> {
type Error = ParseError;
fn try_from(reference: &'a str) -> Result<Self, Self::Error> {
parser::parse(reference)
}
}