use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::Write;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComponentLayer {
Core,
Filesystem,
Device,
Observability,
Platform,
}
impl ComponentLayer {
pub const fn as_str(self) -> &'static str {
match self {
ComponentLayer::Core => "core",
ComponentLayer::Filesystem => "filesystem",
ComponentLayer::Device => "device",
ComponentLayer::Observability => "observability",
ComponentLayer::Platform => "platform",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComponentStability {
Stable,
Experimental,
Internal,
}
impl ComponentStability {
pub const fn as_str(self) -> &'static str {
match self {
ComponentStability::Stable => "stable",
ComponentStability::Experimental => "experimental",
ComponentStability::Internal => "internal",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ComponentManifest {
pub id: &'static str,
pub version: &'static str,
pub layer: ComponentLayer,
pub stability: ComponentStability,
pub description: &'static str,
pub capabilities: &'static [&'static str],
pub requires: &'static [&'static str],
pub provides: &'static [&'static str],
}
impl ComponentManifest {
pub const fn is_stable_public_interface(&self) -> bool {
matches!(self.stability, ComponentStability::Stable)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComponentRegistryError {
MissingDependency {
component: &'static str,
dependency: &'static str,
},
}
#[derive(Debug)]
pub struct ComponentRegistry {
components: &'static [ComponentManifest],
}
impl ComponentRegistry {
pub const fn new(components: &'static [ComponentManifest]) -> Self {
Self { components }
}
pub const fn components(&self) -> &'static [ComponentManifest] {
self.components
}
pub const fn len(&self) -> usize {
self.components.len()
}
pub const fn is_empty(&self) -> bool {
self.components.is_empty()
}
pub fn find(&self, id: &str) -> Option<&'static ComponentManifest> {
self.components.iter().find(|component| component.id == id)
}
pub fn validate_dependencies(&self) -> Result<(), ComponentRegistryError> {
for component in self.components.iter() {
for dependency in component.requires.iter() {
if self.find(dependency).is_none() {
return Err(ComponentRegistryError::MissingDependency {
component: component.id,
dependency,
});
}
}
}
Ok(())
}
pub fn render_sysfs_listing(&self) -> Vec<u8> {
let mut out = String::from("id version layer stability capabilities requires provides\n");
for component in self.components.iter() {
let _ = write!(
out,
"{} {} {} {} ",
component.id,
component.version,
component.layer.as_str(),
component.stability.as_str()
);
write_csv(&mut out, component.capabilities);
out.push(' ');
write_csv(&mut out, component.requires);
out.push(' ');
write_csv(&mut out, component.provides);
out.push('\n');
}
out.into_bytes()
}
}
fn write_csv(out: &mut String, values: &[&str]) {
if values.is_empty() {
out.push('-');
return;
}
for (idx, value) in values.iter().enumerate() {
if idx > 0 {
out.push(',');
}
out.push_str(value);
}
}
const VERSION: &str = env!("CARGO_PKG_VERSION");
const BUILTIN_COMPONENTS: &[ComponentManifest] = &[
ComponentManifest {
id: "ahrightos-core",
version: VERSION,
layer: ComponentLayer::Core,
stability: ComponentStability::Stable,
description: "Kernel bootstrap, heap initialization, and base runtime contracts.",
capabilities: &["kernel.boot", "heap.init", "runtime.base"],
requires: &[],
provides: &["abi.ahrightos-core.v0"],
},
ComponentManifest {
id: "ahrightos-vfs",
version: VERSION,
layer: ComponentLayer::Filesystem,
stability: ComponentStability::Stable,
description: "Unified path resolution and mount dispatch for filesystem components.",
capabilities: &[
"vfs.mount-table",
"vfs.path-resolution",
"vfs.file-dispatch",
],
requires: &["ahrightos-core"],
provides: &["api.vfs.v0"],
},
ComponentManifest {
id: "ahrightos-ramfs",
version: VERSION,
layer: ComponentLayer::Filesystem,
stability: ComponentStability::Stable,
description: "Volatile in-memory filesystem used for root paths and /run.",
capabilities: &["fs.ramfs", "fs.volatile-runtime"],
requires: &["ahrightos-vfs"],
provides: &["/run", "fs.ramfs.v0"],
},
ComponentManifest {
id: "ahrightos-blkfs",
version: VERSION,
layer: ComponentLayer::Filesystem,
stability: ComponentStability::Experimental,
description: "Block-backed filesystem for persistent teaching experiments.",
capabilities: &["fs.blkfs", "block-cache", "mount.blkfs"],
requires: &["ahrightos-vfs"],
provides: &["fs.blkfs.v0"],
},
ComponentManifest {
id: "ahrightos-procfs",
version: VERSION,
layer: ComponentLayer::Observability,
stability: ComponentStability::Experimental,
description: "Linux-inspired read-only process/system information pseudo filesystem.",
capabilities: &["proc.version", "proc.meminfo", "proc.mounts"],
requires: &["ahrightos-vfs"],
provides: &["/proc/version", "/proc/meminfo", "/proc/mounts"],
},
ComponentManifest {
id: "ahrightos-sysfs",
version: VERSION,
layer: ComponentLayer::Observability,
stability: ComponentStability::Experimental,
description: "Linux-inspired system attribute pseudo filesystem.",
capabilities: &["sys.kernel", "sys.component-inspection"],
requires: &["ahrightos-vfs"],
provides: &["/sys/kernel/name", "/sys/fs/ahrightos/components"],
},
ComponentManifest {
id: "ahrightos-devtmpfs",
version: VERSION,
layer: ComponentLayer::Device,
stability: ComponentStability::Experimental,
description: "Device-node entry point for built-in teaching character devices.",
capabilities: &["dev.null", "dev.zero"],
requires: &["ahrightos-vfs"],
provides: &["/dev/null", "/dev/zero"],
},
ComponentManifest {
id: "ahrightos-component-platform",
version: VERSION,
layer: ComponentLayer::Platform,
stability: ComponentStability::Experimental,
description: "Manifest and registry foundation for commercial extensions.",
capabilities: &[
"component.registry",
"component.manifest.v0",
"component.sysfs-export",
],
requires: &["ahrightos-sysfs"],
provides: &["/sys/fs/ahrightos/components", "component.manifest.v0"],
},
];
static BUILTIN_COMPONENT_REGISTRY: ComponentRegistry = ComponentRegistry::new(BUILTIN_COMPONENTS);
pub fn builtin_component_registry() -> &'static ComponentRegistry {
&BUILTIN_COMPONENT_REGISTRY
}
pub fn render_builtin_component_listing() -> Vec<u8> {
BUILTIN_COMPONENT_REGISTRY.render_sysfs_listing()
}