use std::{collections::BTreeMap, fmt::Display};
use base64ct::{Base64, Encoding};
use bytes::Bytes;
use facet::Facet;
use ordered_float::OrderedFloat;
#[derive(thiserror::Error, Debug)]
pub enum Errors {
#[error(transparent)]
StdIo(#[from] std::io::Error),
#[error("{0}")]
Custom(String),
}
impl From<String> for Errors {
fn from(value: String) -> Self {
Self::Custom(value)
}
}
impl From<&str> for Errors {
fn from(value: &str) -> Self {
Self::from(value.to_string())
}
}
pub type Res<T> = Result<T, Errors>;
#[derive(Facet, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
#[repr(C)]
pub enum TagValue {
String(String),
Bytes(Bytes),
Int(i64),
Float(OrderedFloat<f64>),
List(Vec<TagValue>),
}
impl TryFrom<&str> for TagValue {
type Error = Errors;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let trim = value.trim();
let mut ci = trim.char_indices();
let (i, c) = if let Some(c) = ci.next() {
c
} else {
return Err(format!("").into());
};
assert!(i == 0, "Somehow got a char_index greater then 0 first!");
match c {
'[' => todo!(),
'-' | '+' => todo!(),
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => todo!(),
'"' => todo!(),
_ => todo!(),
};
for (i, c) in ci {}
todo!()
}
}
impl Display for TagValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TagValue::String(s) => {
if s.starts_with('"') && s.ends_with('"') {
write!(f, r#"{s}"#)
} else if s.starts_with('\"') {
write!(f, r#"{s}""#)
} else {
write!(f, r#""{s}""#)
}
}
TagValue::Bytes(bytes) => write!(f, "{}", Base64::encode_string(bytes)),
TagValue::Int(i) => write!(f, "{i}"),
TagValue::Float(ordered_float) => write!(f, "{ordered_float}"),
TagValue::List(tag_values) => {
let mut out = Vec::with_capacity(tag_values.len());
for tv in tag_values {
out.push(tv.to_string());
}
let t = out.join(" ");
write!(f, "[ {t} ]")
}
}
}
}
#[derive(Facet, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct TagName(String);
impl TagName {
pub fn parts(&self) -> std::str::Split<'_, &str> {
self.0.split("/")
}
pub fn push_part(&mut self, part: &str) {
if !part.starts_with("/") {
self.0.push('/');
};
self.0.push_str(part);
}
}
impl Display for TagName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Facet, PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct Tags(BTreeMap<TagName, TagValue>);