lodestone-types 0.0.16

Shared semantic types for Lodestone components and public Rust APIs
Documentation
use std::error::Error;
use std::fmt::{self, Display, Formatter};

use serde::{Deserialize, Serialize};

/// The exact scheduling/accounting class selected for one authenticated
/// request. Resource quantities and scheduler weights remain Core policy and
/// are deliberately absent from this caller-visible classification.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum WorkloadClassV1 {
    InteractiveSearch,
    BatchAnalytics,
    StreamingIngest,
    BulkBackfill,
    InternalMaintenance,
}

impl WorkloadClassV1 {
    pub const ALL: [Self; 5] = [
        Self::InteractiveSearch,
        Self::BatchAnalytics,
        Self::StreamingIngest,
        Self::BulkBackfill,
        Self::InternalMaintenance,
    ];

    pub const PUBLIC: [Self; 4] = [
        Self::InteractiveSearch,
        Self::BatchAnalytics,
        Self::StreamingIngest,
        Self::BulkBackfill,
    ];

    #[must_use]
    pub const fn is_public(self) -> bool {
        !matches!(self, Self::InternalMaintenance)
    }

    const fn bit(self) -> u8 {
        match self {
            Self::InteractiveSearch => 1 << 0,
            Self::BatchAnalytics => 1 << 1,
            Self::StreamingIngest => 1 << 2,
            Self::BulkBackfill => 1 << 3,
            Self::InternalMaintenance => 1 << 4,
        }
    }
}

/// Copyable projection of the classes admitted by the exact role grants that
/// authorized one request action. This is reconstructible authentication
/// context, never a second durable policy authority.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct WorkloadClassCapabilitiesV1(u8);

impl WorkloadClassCapabilitiesV1 {
    #[must_use]
    pub const fn empty() -> Self {
        Self(0)
    }

    pub fn from_public_classes(
        classes: impl IntoIterator<Item = WorkloadClassV1>,
    ) -> Result<Self, WorkloadClassCapabilityError> {
        let mut value = Self::empty();
        for class in classes {
            if !class.is_public() {
                return Err(WorkloadClassCapabilityError::InternalClassAtPublicBoundary);
            }
            value.0 |= class.bit();
        }
        if value.is_empty() {
            return Err(WorkloadClassCapabilityError::Empty);
        }
        Ok(value)
    }

    #[must_use]
    pub const fn allows(self, class: WorkloadClassV1) -> bool {
        self.0 & class.bit() != 0
    }

    #[must_use]
    pub const fn is_empty(self) -> bool {
        self.0 == 0
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WorkloadClassCapabilityError {
    Empty,
    InternalClassAtPublicBoundary,
}

impl Display for WorkloadClassCapabilityError {
    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::Empty => formatter.write_str("workload-class capability set is empty"),
            Self::InternalClassAtPublicBoundary => {
                formatter.write_str("internal-maintenance class is not a public capability")
            }
        }
    }
}

impl Error for WorkloadClassCapabilityError {}

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

    #[test]
    fn public_capabilities_are_exact_and_internal_is_refused() -> Result<(), Box<dyn Error>> {
        let capabilities = WorkloadClassCapabilitiesV1::from_public_classes([
            WorkloadClassV1::InteractiveSearch,
            WorkloadClassV1::BulkBackfill,
        ])?;
        assert!(capabilities.allows(WorkloadClassV1::InteractiveSearch));
        assert!(capabilities.allows(WorkloadClassV1::BulkBackfill));
        assert!(!capabilities.allows(WorkloadClassV1::BatchAnalytics));
        assert!(!capabilities.allows(WorkloadClassV1::InternalMaintenance));
        assert_eq!(
            WorkloadClassCapabilitiesV1::from_public_classes([WorkloadClassV1::InternalMaintenance]),
            Err(WorkloadClassCapabilityError::InternalClassAtPublicBoundary)
        );
        Ok(())
    }
}