use core::borrow::Borrow;
use core::fmt::Display;
use core::ops::Deref;
use core::str::FromStr;
use alloc::collections::BTreeMap;
use delegate::delegate;
use miette::Diagnostic;
use snafu::ensure;
use snafu::Backtrace;
use snafu::Snafu;
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Key {
name: String,
}
impl Display for Key {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.name)
}
}
impl FromStr for Key {
type Err = KeyError;
#[inline]
fn from_str(name: &str) -> Result<Self, Self::Err> {
ensure!(is_valid_key(name), KeySnafu { name });
let name = name.to_owned();
Ok(Self { name })
}
}
impl TryFrom<String> for Key {
type Error = KeyError;
fn try_from(name: String) -> Result<Self, Self::Error> {
ensure!(is_valid_key(&name), KeySnafu { name });
Ok(Self { name })
}
}
#[derive(Debug, Diagnostic, Snafu)]
pub struct KeyError {
backtrace: Backtrace,
name: String,
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Link {
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 {
// SAFETY: self.name is a valid link name, by construction
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 = LinkError;
#[inline]
fn from_str(name: &str) -> Result<Self, Self::Err> {
<&Lnk>::try_from(name).map(Self::from)
}
}
impl TryFrom<String> for Link {
type Error = LinkError;
#[inline]
fn try_from(name: String) -> Result<Self, Self::Error> {
ensure!(is_valid_link_name(&name), LinkSnafu { name });
Ok(Self { name })
}
}
#[derive(Debug, Diagnostic, Snafu)]
pub struct LinkError {
name: String,
backtrace: Backtrace,
}
#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Lnk {
name: str,
}
impl Lnk {
#[allow(unsafe_code)]
#[inline]
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 = LinkError;
#[inline]
fn try_from(name: &'l str) -> Result<Self, Self::Error> {
ensure!(is_valid_link_name(name), LinkSnafu { name });
Ok(
#[allow(unsafe_code)]
unsafe {
// SAFETY: we have ensured that `name` is a valid link.
Lnk::from_unchecked(name)
},
)
}
}
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
pub struct Transaction {
pub key_value: BTreeMap<Key, Value>,
pub links: Vec<Link>,
}
impl Transaction {
#[inline]
pub fn add_link(&mut self, link: impl Into<Link>) -> &mut Self {
self.links.push(link.into());
self
}
#[inline]
pub fn add_key_value(&mut self, key: impl Into<Key>, value: impl Into<Value>) -> &mut Self {
self.key_value.insert(key.into(), value.into());
self
}
}
impl Display for Transaction {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
for link in &self.links {
link.fmt(f)?
}
Ok(())
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Value {
String(String),
}
impl Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::String(inner) => write!(f, "{inner:?}"),
}
}
}
impl<S> From<S> for Value
where
S: Into<String>,
{
fn from(value: S) -> Self {
Self::String(value.into())
}
}
fn is_valid_key(name: &str) -> bool {
lazy_regex::regex_is_match!(r"^(:?[a-z][a-zA-Z0-9\-_]+)$", name)
}
fn is_valid_link_name(name: &str) -> bool {
lazy_regex::regex_is_match!(r"^(:?\^[A-Za-z0-9\-_/.]+)$", name)
}