114 lines
3.6 KiB
Rust
114 lines
3.6 KiB
Rust
//! [TSM.ID].[11031972] -- Platform X Ecosystem
|
|
//! xcu-camera-raw -- Raw camera access with zero-copy frame buffer
|
|
#![deny(warnings)]
|
|
#![allow(dead_code)]
|
|
|
|
use serde::{Serialize, Deserialize};
|
|
use std::collections::HashMap;
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
#[derive(Debug)]
|
|
pub enum XcuError {
|
|
InitFailed(String),
|
|
InvalidConfig(String),
|
|
OperationFailed(String),
|
|
ResourceExhausted,
|
|
NotFound(String),
|
|
Timeout,
|
|
IoError(String),
|
|
}
|
|
|
|
impl std::fmt::Display for XcuError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::InitFailed(e) => write!(f, "Init failed: {e}"),
|
|
Self::InvalidConfig(e) => write!(f, "Invalid config: {e}"),
|
|
Self::OperationFailed(e) => write!(f, "Op failed: {e}"),
|
|
Self::ResourceExhausted => write!(f, "Resource exhausted"),
|
|
Self::NotFound(e) => write!(f, "Not found: {e}"),
|
|
Self::Timeout => write!(f, "Timeout"),
|
|
Self::IoError(e) => write!(f, "IO: {e}"),
|
|
}
|
|
}
|
|
}
|
|
impl std::error::Error for XcuError {}
|
|
pub type Result<T> = std::result::Result<T, XcuError>;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ModuleConfig {
|
|
pub name: String,
|
|
pub params: HashMap<String, String>,
|
|
pub enabled: bool,
|
|
}
|
|
|
|
impl ModuleConfig {
|
|
pub fn new(name: &str) -> Self {
|
|
Self { name: name.to_string(), params: HashMap::new(), enabled: true }
|
|
}
|
|
pub fn set(&mut self, k: &str, v: &str) -> &mut Self {
|
|
self.params.insert(k.to_string(), v.to_string()); self
|
|
}
|
|
pub fn get(&self, k: &str) -> Result<&str> {
|
|
self.params.get(k).map(|s| s.as_str()).ok_or_else(|| XcuError::NotFound(k.into()))
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub enum ModuleState { Idle, Running, Paused, Stopping, Stopped, Error(String) }
|
|
|
|
pub struct Module {
|
|
config: ModuleConfig,
|
|
state: Arc<Mutex<ModuleState>>,
|
|
metrics: Arc<Mutex<HashMap<String, u64>>>,
|
|
}
|
|
|
|
impl Module {
|
|
pub fn new(config: ModuleConfig) -> Result<Self> {
|
|
Ok(Self {
|
|
config, state: Arc::new(Mutex::new(ModuleState::Idle)),
|
|
metrics: Arc::new(Mutex::new(HashMap::new())),
|
|
})
|
|
}
|
|
|
|
pub fn start(&self) -> Result<()> {
|
|
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
|
|
match &*s {
|
|
ModuleState::Idle | ModuleState::Stopped => { *s = ModuleState::Running; Ok(()) }
|
|
other => Err(XcuError::InvalidConfig(format!("Cannot start from state: {other:?}"))),
|
|
}
|
|
}
|
|
|
|
pub fn stop(&self) -> Result<()> {
|
|
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
|
|
*s = ModuleState::Stopping;
|
|
*s = ModuleState::Stopped;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn state(&self) -> Result<ModuleState> {
|
|
Ok(self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?.clone())
|
|
}
|
|
|
|
pub fn record_metric(&self, key: &str, val: u64) -> Result<()> {
|
|
let mut m = self.metrics.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
|
|
m.insert(key.to_string(), val);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn config(&self) -> &ModuleConfig { &self.config }
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
#[test]
|
|
fn test_lifecycle() {
|
|
let m = Module::new(ModuleConfig::new("xcu-camera-raw")).unwrap();
|
|
assert_eq!(m.state().unwrap(), ModuleState::Idle);
|
|
m.start().unwrap();
|
|
assert_eq!(m.state().unwrap(), ModuleState::Running);
|
|
m.stop().unwrap();
|
|
assert_eq!(m.state().unwrap(), ModuleState::Stopped);
|
|
}
|
|
}
|