use alloc::collections::BTreeSet;
use delegate::delegate;
use miette::Diagnostic;
use snafu::Backtrace;
use snafu::ensure;
use snafu::Snafu;
use core::str::FromStr;
use core::fmt::Display;
use core::ops::Deref;
use core::borrow::Borrow;
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Link {
pub(crate) name: String,
}
impl Borrow<Lnk> for Link {
fn borrow(&self) -> &Lnk {
self
}
}
impl Deref for Link {
type Target = Lnk;
fn deref(&self) -> &Self::Target {
#[allow(unsafe_code)]
unsafe {
Self::Target::from_unchecked(&self.name)
}
}
}
impl Display for Link {
delegate! {
to self.name {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
}
}
}
impl From<&Lnk> for Link {
#[inline]
fn from(link: &Lnk) -> Self {
link.to_owned()
}
}
impl FromStr for Link {
type Err = Error;
#[inline]
fn from_str(name: &str) -> Result<Self, Self::Err> {
<&Lnk>::try_from(name).map(Self::from)
}
}
impl TryFrom<String> for Link {
type Error = Error;
#[inline]
fn try_from(name: String) -> Result<Self, Self::Error> {
ensure!(is_valid_link_name(&name), Snafu { name });
Ok(Self { name })
}
}
#[derive(Debug, Diagnostic, Snafu)]
pub struct Error {
pub(crate) name: String,
pub(crate) backtrace: Backtrace,
}
#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Lnk {
pub(crate) name: str,
}
impl Lnk {
#[allow(unsafe_code)]
#[inline]
pub(crate) const unsafe fn from_unchecked(name: &str) -> &Self {
let name: *const _ = name;
let name = name as *const _;
unsafe { &*name }
}
}
impl ToOwned for Lnk {
type Owned = Link;
#[inline]
fn to_owned(&self) -> Self::Owned {
let name = self.name.to_owned();
Self::Owned { name }
}
}
impl<'l> TryFrom<&'l str> for &'l Lnk {
type Error = Error;
#[inline]
fn try_from(name: &'l str) -> Result<Self, Self::Error> {
ensure!(is_valid_link_name(name), Snafu { name });
Ok(
#[allow(unsafe_code)]
unsafe {
Lnk::from_unchecked(name)
},
)
}
}
pub type Set = BTreeSet<Link>;
fn is_valid_link_name(name: &str) -> bool {
lazy_regex::regex_is_match!(r"^(:?\^[A-Za-z0-9\-_/.]+)$", name)
}