use types::{badge::Badge, bounded::CapSlot, generation::Generation, permission::PermissionSet}; pub mod authority; use crate::{error::KernelError, resource::Resource}; #[cfg(test)] #[path = "tests.rs"] mod tests; // Sized so that every representable `CapSlot` indexes a real slot. pub const MAX_CAPS_PER_PROCESS: usize = CapSlot::MAX as usize + 1; #[derive(Clone)] pub struct Capability { resource: Resource, permissions: PermissionSet, generation: Generation, badge: Badge, } impl Capability { pub fn new(resource: Resource, permissions: PermissionSet, generation: Generation) -> Self { Self { resource, permissions, generation, badge: Badge::NONE, } } /// The same capability with `badge` stamped on it. pub fn with_badge(mut self, badge: Badge) -> Self { self.badge = badge; self } pub fn badge(&self) -> Badge { self.badge } pub fn resource(&self) -> &Resource { &self.resource } pub fn permissions(&self) -> &PermissionSet { &self.permissions } pub fn generation(&self) -> &Generation { &self.generation } } pub struct CapabilityTable { slots: [Option; MAX_CAPS_PER_PROCESS], } impl CapabilityTable { pub fn new() -> Self { Self { slots: [const { None }; MAX_CAPS_PER_PROCESS], } } pub fn get(&self, slot: CapSlot) -> Result<&Capability, KernelError> { let idx = slot.value() as usize; self.slots[idx] .as_ref() .ok_or(KernelError::InvalidSlot(slot)) } pub fn insert(&mut self, cap: Capability) -> Result { let idx = self .slots .iter() .position(|s| s.is_none()) .ok_or(KernelError::NoFreeSlot)?; self.slots[idx] = Some(cap); CapSlot::new(idx as u8).ok_or(KernelError::NoFreeSlot) } pub fn remove(&mut self, slot: CapSlot) -> Result<(), KernelError> { let idx = slot.value() as usize; if self.slots[idx].is_none() { return Err(KernelError::InvalidSlot(slot)); } self.slots[idx] = None; Ok(()) } } impl Default for CapabilityTable { fn default() -> Self { Self::new() } }