uvb-core 0.2.1

Core error types and shared primitives for the UVB authentication platform
Documentation
use serde::{Deserialize, Serialize};
use std::fmt;

/// Type-safe factor identifier wrapper
///
/// This newtype provides compile-time guarantees that:
/// 1. Factor IDs cannot be accidentally mixed with other string types
/// 2. All factor-scoped operations explicitly require a FactorId
/// 3. Cross-factor operations are caught at compile time
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct FactorId(String);

impl FactorId {
    /// Create a new FactorId from a string
    pub fn new(id: impl Into<String>) -> Self {
        Self(id.into())
    }

    /// Get the factor ID as a string slice
    pub fn as_str(&self) -> &str {
        &self.0
    }

    /// Consume the FactorId and return the inner String
    pub fn into_inner(self) -> String {
        self.0
    }

    /// Validate that the factor ID is well-formed
    pub fn is_valid(&self) -> bool {
        !self.0.is_empty()
            && self.0.len() <= 64
            && self.0.chars().all(|c| c.is_alphanumeric() || c == '_')
    }
}

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

impl AsRef<str> for FactorId {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

impl From<String> for FactorId {
    fn from(s: String) -> Self {
        Self(s)
    }
}

impl From<&str> for FactorId {
    fn from(s: &str) -> Self {
        Self(s.to_string())
    }
}

impl From<FactorId> for String {
    fn from(factor_id: FactorId) -> Self {
        factor_id.0
    }
}

impl PartialEq<str> for FactorId {
    fn eq(&self, other: &str) -> bool {
        self.0 == other
    }
}

impl PartialEq<&str> for FactorId {
    fn eq(&self, other: &&str) -> bool {
        self.0 == *other
    }
}

impl PartialEq<String> for FactorId {
    fn eq(&self, other: &String) -> bool {
        &self.0 == other
    }
}