souvenir 0.3.1

Prefixed identifier library
Documentation
use std::{
    fmt::{Debug, Display, Formatter},
    str::FromStr,
};

use crate::{encoding::parse_base32, Error, Id, Type};

impl Type for () {
    const PREFIX: &'static str = "";
}

#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Generic {
    prefix: String,
    value: Id<()>,
}

impl Generic {
    /// Create a new `Id<T>` with the following underlying value.
    pub fn new(prefix: impl Into<String>, value: [u8; 16]) -> Self {
        Self {
            prefix: prefix.into(),
            value: Id::new(value),
        }
    }

    /// Get the data value of the identifier.
    pub fn as_bytes(&self) -> &[u8; 16] {
        &self.value.as_bytes()
    }

    /// Get the data value of the identifier.
    pub fn to_bytes(self) -> [u8; 16] {
        self.value.to_bytes()
    }

    /// Get the data value of the identifier as a `u64`.
    pub fn to_u128(&self) -> u128 {
        self.value.to_u128()
    }

    /// Get the data value of the identifier as an `i64`.
    pub fn to_i128(&self) -> i128 {
        self.value.to_i128()
    }

    /// Test to see if the provided string is a valid `Generic`.
    pub fn test(value: &str) -> bool {
        Self::parse(value).is_ok()
    }

    /// Attempt to parse the provided string into a `Generic`.
    pub fn parse(value: &str) -> Result<Self, Error> {
        let (prefix, value) = value.split_once('_').ok_or(Error::InvalidData)?;

        Ok(Self {
            prefix: prefix.to_owned(),
            value: Id::new(parse_base32(value)?),
        })
    }

    /// Get the prefix of this identifier.
    pub fn prefix(&self) -> &str {
        &self.prefix
    }

    /// Cast this Id into an Id of a different type.
    pub const fn cast<U: Type + ?Sized>(&self) -> Id<U> {
        self.value.cast()
    }
}

impl Debug for Generic {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self)
    }
}

impl Display for Generic {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}{}", self.prefix, self.value)
    }
}

impl FromStr for Generic {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::parse(s)
    }
}

impl From<Generic> for u128 {
    fn from(value: Generic) -> Self {
        value.to_u128()
    }
}

impl From<Generic> for i128 {
    fn from(value: Generic) -> Self {
        value.to_i128()
    }
}

#[cfg(test)]
mod test {
    use super::Generic;

    #[test]
    fn generic_display() {
        let id = Generic::parse("test_7zzzzzzzzzzzzzzzzzzzzzzzzz").unwrap();
        assert_eq!(id.to_string(), "test_7zzzzzzzzzzzzzzzzzzzzzzzzz");
    }
}