orthodoxy 0.2.0

A collection of my utility libraries
Documentation
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} ]")
            }
        }
    }
}

/// Nested with '/'
#[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>);