//! [TSM.ID].[11031972] -- Platform X Ecosystem //! xcu-ebpf-loader -- Cross-platform eBPF program loader #![deny(warnings)] use serde::{Serialize, Deserialize}; use std::collections::HashMap; use std::sync::{Arc, Mutex}; #[derive(Debug)] pub enum LoaderError { FileNotFound(String), ParseFailed(String), ValidationFailed(String), LoadFailed(String), } impl std::fmt::Display for LoaderError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::FileNotFound(e) => write!(f, "File not found: {e}"), Self::ParseFailed(e) => write!(f, "Parse failed: {e}"), Self::ValidationFailed(e) => write!(f, "Validation: {e}"), Self::LoadFailed(e) => write!(f, "Load failed: {e}"), } } } impl std::error::Error for LoaderError {} pub type Result = std::result::Result; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProgramSpec { pub name: String, pub prog_type: String, pub bytecode_path: String, pub maps: Vec, } pub struct ProgramLoader { loaded: Arc>>, verified: Arc>>, } impl ProgramLoader { pub fn new() -> Self { Self { loaded: Arc::new(Mutex::new(HashMap::new())), verified: Arc::new(Mutex::new(Vec::new())) } } pub fn load_spec(&self, spec: ProgramSpec) -> Result<()> { let mut loaded = self.loaded.lock().map_err(|e| LoaderError::LoadFailed(e.to_string()))?; loaded.insert(spec.name.clone(), spec); Ok(()) } pub fn verify(&self, name: &str) -> Result { let loaded = self.loaded.lock().map_err(|e| LoaderError::LoadFailed(e.to_string()))?; if !loaded.contains_key(name) { return Err(LoaderError::FileNotFound(name.into())); } let mut verified = self.verified.lock().map_err(|e| LoaderError::LoadFailed(e.to_string()))?; verified.push(name.to_string()); Ok(true) } pub fn loaded_count(&self) -> usize { self.loaded.lock().map(|l| l.len()).unwrap_or(0) } } impl Default for ProgramLoader { fn default() -> Self { Self::new() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_loader() { let loader = ProgramLoader::new(); loader.load_spec(ProgramSpec { name: "test".into(), prog_type: "xdp".into(), bytecode_path: "/dev/null".into(), maps: vec![], }).unwrap(); assert_eq!(loader.loaded_count(), 1); assert!(loader.verify("test").unwrap()); } }