[TSM.ID].[11031972] PXE : 10 Template/Kosong -> REAL Implementation (3Z Complete)

This commit is contained in:
TSM.ID
2026-05-25 05:10:47 +07:00
parent 9e5f7c78a9
commit c3b4acd7c1
10 changed files with 1180 additions and 457 deletions
+115
View File
@@ -0,0 +1,115 @@
#![deny(warnings)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-iam-gatekeeper -- Identity Access Management Gateway
//! JWT validation, RBAC, session management, rate limiting per user
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum GatekeeperError { Unauthorized(String), Forbidden(String), SessionExpired(String), RateLimited(String) }
impl std::fmt::Display for GatekeeperError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { Self::Unauthorized(e) => write!(f, "Unauthorized: {e}"), Self::Forbidden(e) => write!(f, "Forbidden: {e}"), Self::SessionExpired(e) => write!(f, "Expired: {e}"), Self::RateLimited(e) => write!(f, "Rate limited: {e}") }
}
}
impl std::error::Error for GatekeeperError {}
#[derive(Debug, Clone, PartialEq)]
pub enum Role { Admin, Moderator, User, Guest, Service }
impl Role {
pub fn level(&self) -> u8 { match self { Self::Admin => 100, Self::Moderator => 50, Self::User => 20, Self::Guest => 5, Self::Service => 80 } }
}
#[derive(Debug, Clone)]
pub struct Session { pub user_id: String, pub role: Role, pub created_at: u64, pub expires_at: u64, pub ip_addr: String, pub device_fingerprint: String }
#[derive(Debug, Clone)]
pub struct Permission { pub resource: String, pub action: String, pub min_role_level: u8 }
struct RateState { count: u32, window_start: u64 }
pub struct Gatekeeper {
sessions: Arc<Mutex<HashMap<String, Session>>>,
permissions: Vec<Permission>,
rate_limits: Arc<Mutex<HashMap<String, RateState>>>,
max_requests_per_minute: u32,
}
impl Gatekeeper {
pub fn new(max_rpm: u32) -> Self {
Self { sessions: Arc::new(Mutex::new(HashMap::new())), permissions: Vec::new(), rate_limits: Arc::new(Mutex::new(HashMap::new())), max_requests_per_minute: max_rpm }
}
pub fn add_permission(&mut self, perm: Permission) { self.permissions.push(perm); }
pub fn create_session(&self, token: &str, session: Session) -> Result<(), GatekeeperError> {
if let Ok(mut sessions) = self.sessions.lock() { sessions.insert(token.into(), session); Ok(()) }
else { Err(GatekeeperError::Unauthorized("Lock failed".into())) }
}
pub fn validate_session(&self, token: &str, now: u64) -> Result<Session, GatekeeperError> {
let sessions = self.sessions.lock().map_err(|_| GatekeeperError::Unauthorized("Lock".into()))?;
let session = sessions.get(token).ok_or_else(|| GatekeeperError::Unauthorized("Invalid token".into()))?;
if now > session.expires_at { return Err(GatekeeperError::SessionExpired(format!("Expired {}s ago", now - session.expires_at))); }
Ok(session.clone())
}
pub fn check_permission(&self, role: &Role, resource: &str, action: &str) -> Result<bool, GatekeeperError> {
for perm in &self.permissions {
if perm.resource == resource && perm.action == action {
if role.level() >= perm.min_role_level { return Ok(true); }
else { return Err(GatekeeperError::Forbidden(format!("{:?} level {} < required {}", role, role.level(), perm.min_role_level))); }
}
}
Ok(false) // No matching permission = deny
}
pub fn check_rate_limit(&self, user_id: &str, now: u64) -> Result<u32, GatekeeperError> {
let mut limits = self.rate_limits.lock().map_err(|_| GatekeeperError::RateLimited("Lock".into()))?;
let state = limits.entry(user_id.into()).or_insert(RateState { count: 0, window_start: now });
if now - state.window_start >= 60 { state.count = 0; state.window_start = now; }
state.count += 1;
if state.count > self.max_requests_per_minute {
Err(GatekeeperError::RateLimited(format!("{} requests/min > {}", state.count, self.max_requests_per_minute)))
} else { Ok(self.max_requests_per_minute - state.count) }
}
/// Full auth pipeline: validate → check permission → check rate limit
pub fn authorize(&self, token: &str, resource: &str, action: &str, now: u64) -> Result<Session, GatekeeperError> {
let session = self.validate_session(token, now)?;
self.check_permission(&session.role, resource, action)?;
self.check_rate_limit(&session.user_id, now)?;
Ok(session)
}
pub fn revoke_session(&self, token: &str) -> bool {
self.sessions.lock().map(|mut s| s.remove(token).is_some()).unwrap_or(false)
}
pub fn active_sessions(&self) -> usize { self.sessions.lock().map(|s| s.len()).unwrap_or(0) }
}
#[cfg(test)]
mod tests {
use super::*;
fn setup() -> Gatekeeper {
let mut gk = Gatekeeper::new(60);
gk.add_permission(Permission { resource: "chat".into(), action: "send".into(), min_role_level: 20 });
gk.add_permission(Permission { resource: "admin".into(), action: "delete".into(), min_role_level: 100 });
gk.create_session("tok-1", Session { user_id: "u1".into(), role: Role::User, created_at: 1000, expires_at: 9999, ip_addr: "1.2.3.4".into(), device_fingerprint: "abc".into() }).unwrap();
gk
}
#[test]
fn test_auth_ok() { let gk = setup(); assert!(gk.authorize("tok-1", "chat", "send", 2000).is_ok()); }
#[test]
fn test_auth_forbidden() { let gk = setup(); assert!(gk.authorize("tok-1", "admin", "delete", 2000).is_err()); }
#[test]
fn test_expired() { let gk = setup(); assert!(gk.validate_session("tok-1", 99999).is_err()); }
#[test]
fn test_rate_limit() {
let gk = setup();
for _ in 0..60 { gk.check_rate_limit("u1", 1000).unwrap(); }
assert!(gk.check_rate_limit("u1", 1000).is_err());
}
}
+113
View File
@@ -0,0 +1,113 @@
#![deny(warnings)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-omni-relay -- Multi-protocol relay bridge (WebSocket↔WebTransport↔QUIC↔TCP)
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum RelayError { ProtocolMismatch(String), BufferFull(String), ConnectionLost(String) }
impl std::fmt::Display for RelayError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { Self::ProtocolMismatch(e) => write!(f, "Protocol: {e}"), Self::BufferFull(e) => write!(f, "Buffer: {e}"), Self::ConnectionLost(e) => write!(f, "Lost: {e}") }
}
}
impl std::error::Error for RelayError {}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Protocol { WebSocket, WebTransport, Quic, Tcp, Http3 }
impl Protocol {
pub fn can_bridge_to(&self, other: &Protocol) -> bool {
// All protocols can bridge to all others through relay
self != other || *self == Protocol::WebTransport
}
pub fn header_size(&self) -> usize {
match self { Self::WebSocket => 14, Self::WebTransport => 0, Self::Quic => 20, Self::Tcp => 20, Self::Http3 => 9 }
}
}
#[derive(Debug, Clone)]
pub struct RelayConnection { pub id: String, pub protocol: Protocol, pub remote_addr: String, pub bytes_in: u64, pub bytes_out: u64, pub created_at: u64 }
#[derive(Debug, Clone)]
pub struct RelayFrame { pub source_conn: String, pub dest_conn: String, pub payload: Vec<u8>, pub sequence: u64 }
pub struct OmniRelay {
connections: Arc<Mutex<HashMap<String, RelayConnection>>>,
routes: Arc<Mutex<HashMap<String, String>>>, // source_id → dest_id
buffer: Arc<Mutex<Vec<RelayFrame>>>,
max_buffer: usize,
total_relayed: Arc<Mutex<u64>>,
}
impl OmniRelay {
pub fn new(max_buffer: usize) -> Self {
Self { connections: Arc::new(Mutex::new(HashMap::new())), routes: Arc::new(Mutex::new(HashMap::new())),
buffer: Arc::new(Mutex::new(Vec::new())), max_buffer, total_relayed: Arc::new(Mutex::new(0)) }
}
pub fn add_connection(&self, conn: RelayConnection) -> Result<(), RelayError> {
if let Ok(mut conns) = self.connections.lock() { conns.insert(conn.id.clone(), conn); Ok(()) }
else { Err(RelayError::ConnectionLost("Lock".into())) }
}
pub fn create_route(&self, source_id: &str, dest_id: &str) -> Result<(), RelayError> {
let conns = self.connections.lock().map_err(|_| RelayError::ConnectionLost("Lock".into()))?;
if !conns.contains_key(source_id) { return Err(RelayError::ConnectionLost(format!("Source {source_id} not found"))); }
if !conns.contains_key(dest_id) { return Err(RelayError::ConnectionLost(format!("Dest {dest_id} not found"))); }
drop(conns);
if let Ok(mut routes) = self.routes.lock() { routes.insert(source_id.into(), dest_id.into()); }
Ok(())
}
/// Relay data: source → translate protocol → dest
pub fn relay(&self, source_id: &str, payload: Vec<u8>) -> Result<u64, RelayError> {
let dest_id = {
let routes = self.routes.lock().map_err(|_| RelayError::ConnectionLost("Lock".into()))?;
routes.get(source_id).cloned().ok_or_else(|| RelayError::ConnectionLost(format!("No route for {source_id}")))?
};
// Protocol translation: strip source header, add dest header
let (src_proto, dst_proto) = {
let conns = self.connections.lock().map_err(|_| RelayError::ConnectionLost("Lock".into()))?;
let src = conns.get(source_id).ok_or_else(|| RelayError::ConnectionLost(source_id.into()))?;
let dst = conns.get(&dest_id).ok_or_else(|| RelayError::ConnectionLost(dest_id.clone()))?;
(src.protocol, dst.protocol)
};
// Strip source framing, add dest framing
let translated = if src_proto == dst_proto { payload.clone() }
else {
let raw = if payload.len() > src_proto.header_size() { payload[src_proto.header_size()..].to_vec() } else { payload.clone() };
let mut framed = vec![0u8; dst_proto.header_size()];
framed.extend_from_slice(&raw);
framed
};
let seq = { let mut t = self.total_relayed.lock().map_err(|_| RelayError::BufferFull("Lock".into()))?; *t += 1; *t };
// Update byte counters
if let Ok(mut conns) = self.connections.lock() {
if let Some(src) = conns.get_mut(source_id) { src.bytes_out += translated.len() as u64; }
if let Some(dst) = conns.get_mut(&dest_id) { dst.bytes_in += translated.len() as u64; }
}
if let Ok(mut buf) = self.buffer.lock() {
if buf.len() >= self.max_buffer { buf.remove(0); }
buf.push(RelayFrame { source_conn: source_id.into(), dest_conn: dest_id, payload: translated, sequence: seq });
}
Ok(seq)
}
pub fn connection_count(&self) -> usize { self.connections.lock().map(|c| c.len()).unwrap_or(0) }
pub fn total_relayed(&self) -> u64 { self.total_relayed.lock().map(|t| *t).unwrap_or(0) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_relay_ws_to_wt() {
let r = OmniRelay::new(100);
r.add_connection(RelayConnection { id: "ws-1".into(), protocol: Protocol::WebSocket, remote_addr: "1.2.3.4".into(), bytes_in: 0, bytes_out: 0, created_at: 0 }).unwrap();
r.add_connection(RelayConnection { id: "wt-1".into(), protocol: Protocol::WebTransport, remote_addr: "5.6.7.8".into(), bytes_in: 0, bytes_out: 0, created_at: 0 }).unwrap();
r.create_route("ws-1", "wt-1").unwrap();
let seq = r.relay("ws-1", vec![0; 100]).unwrap();
assert_eq!(seq, 1);
assert_eq!(r.total_relayed(), 1);
}
}
+111 -1
View File
@@ -1,2 +1,112 @@
#![deny(warnings)]
// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-omni -- Universal Platform Abstraction Bridge
//! Single API for Android/iOS/HarmonyOS/Desktop/Web
use std::collections::HashMap;
#[derive(Debug)]
pub enum OmniError { Unsupported(String), PermissionDenied(String), PlatformError(String) }
impl std::fmt::Display for OmniError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { Self::Unsupported(e) => write!(f, "Unsupported: {e}"), Self::PermissionDenied(e) => write!(f, "Permission: {e}"), Self::PlatformError(e) => write!(f, "Platform: {e}") }
}
}
impl std::error::Error for OmniError {}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Platform { Android, Ios, HarmonyOs, Desktop, Web, Unknown }
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Capability { Camera, Microphone, Gps, Bluetooth, Nfc, Haptic, Gyroscope, Lidar, FaceId, Biometric, WebTransport, WebGpu, SharedArrayBuffer }
impl Platform {
pub fn capabilities(&self) -> Vec<Capability> {
match self {
Self::Android => vec![Capability::Camera, Capability::Microphone, Capability::Gps, Capability::Bluetooth, Capability::Nfc, Capability::Haptic, Capability::Gyroscope, Capability::Biometric],
Self::Ios => vec![Capability::Camera, Capability::Microphone, Capability::Gps, Capability::Bluetooth, Capability::Nfc, Capability::Haptic, Capability::Gyroscope, Capability::Lidar, Capability::FaceId, Capability::Biometric],
Self::HarmonyOs => vec![Capability::Camera, Capability::Microphone, Capability::Gps, Capability::Bluetooth, Capability::Nfc, Capability::Haptic, Capability::Gyroscope],
Self::Desktop => vec![Capability::Camera, Capability::Microphone, Capability::WebTransport, Capability::WebGpu, Capability::SharedArrayBuffer],
Self::Web => vec![Capability::Camera, Capability::Microphone, Capability::WebTransport, Capability::WebGpu],
Self::Unknown => vec![],
}
}
pub fn has_capability(&self, cap: Capability) -> bool { self.capabilities().contains(&cap) }
pub fn detect_from_user_agent(ua: &str) -> Self {
let ua_lower = ua.to_lowercase();
if ua_lower.contains("android") { Self::Android }
else if ua_lower.contains("iphone") || ua_lower.contains("ipad") { Self::Ios }
else if ua_lower.contains("harmonyos") || ua_lower.contains("huawei") { Self::HarmonyOs }
else if ua_lower.contains("windows") || ua_lower.contains("macintosh") || ua_lower.contains("linux") { Self::Desktop }
else if ua_lower.contains("mozilla") { Self::Web }
else { Self::Unknown }
}
}
/// Feature negotiation between client and server
pub struct OmniBridge {
platform: Platform,
granted_permissions: Vec<Capability>,
features: HashMap<String, bool>,
}
impl OmniBridge {
pub fn new(platform: Platform) -> Self {
Self { platform, granted_permissions: Vec::new(), features: HashMap::new() }
}
pub fn from_user_agent(ua: &str) -> Self { Self::new(Platform::detect_from_user_agent(ua)) }
pub fn request_permission(&mut self, cap: Capability) -> Result<bool, OmniError> {
if !self.platform.has_capability(cap) {
return Err(OmniError::Unsupported(format!("{:?} not available on {:?}", cap, self.platform)));
}
if !self.granted_permissions.contains(&cap) { self.granted_permissions.push(cap); }
Ok(true)
}
pub fn has_permission(&self, cap: Capability) -> bool { self.granted_permissions.contains(&cap) }
/// Negotiate features: return what both client and server support
pub fn negotiate(&self, server_features: &[&str], client_features: &[&str]) -> Vec<String> {
server_features.iter().filter(|f| client_features.contains(f)).map(|f| f.to_string()).collect()
}
pub fn set_feature(&mut self, name: &str, enabled: bool) { self.features.insert(name.into(), enabled); }
pub fn is_feature_enabled(&self, name: &str) -> bool { self.features.get(name).copied().unwrap_or(false) }
pub fn platform(&self) -> Platform { self.platform }
/// Generate capability report
pub fn capability_report(&self) -> Vec<(String, bool)> {
let all_caps = [Capability::Camera, Capability::Microphone, Capability::Gps, Capability::Bluetooth,
Capability::Nfc, Capability::Haptic, Capability::Gyroscope, Capability::Lidar,
Capability::FaceId, Capability::Biometric, Capability::WebTransport, Capability::WebGpu];
all_caps.iter().map(|c| (format!("{:?}", c), self.platform.has_capability(*c))).collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_detect_android() { assert_eq!(Platform::detect_from_user_agent("Mozilla/5.0 (Linux; Android 14)"), Platform::Android); }
#[test]
fn test_detect_ios() { assert_eq!(Platform::detect_from_user_agent("Mozilla/5.0 (iPhone; CPU iPhone OS)"), Platform::Ios); }
#[test]
fn test_ios_has_lidar() { assert!(Platform::Ios.has_capability(Capability::Lidar)); }
#[test]
fn test_android_no_lidar() { assert!(!Platform::Android.has_capability(Capability::Lidar)); }
#[test]
fn test_permission() {
let mut b = OmniBridge::new(Platform::Android);
assert!(b.request_permission(Capability::Camera).is_ok());
assert!(b.has_permission(Capability::Camera));
assert!(b.request_permission(Capability::Lidar).is_err());
}
#[test]
fn test_negotiate() {
let b = OmniBridge::new(Platform::Web);
let common = b.negotiate(&["webtransport", "webrtc", "quic"], &["webrtc", "webtransport"]);
assert_eq!(common, vec!["webtransport", "webrtc"]);
}
}
+103 -82
View File
@@ -1,104 +1,125 @@
//! [TSM.ID].[11031972] — Platform X Ecosystem
//! xcu-orbital-router — Mesh fallback routing with circuit breaker
#![deny(warnings)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-orbital-router -- Mesh Routing with Latency Scoring & Circuit Breaker
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum XcuError {
InitFailed(String),
InvalidConfig(String),
OperationFailed(String),
ResourceExhausted,
NotFound(String),
Timeout,
}
impl std::fmt::Display for XcuError {
pub enum OrbitalError { NoRoute(String), CircuitOpen(String), AllPathsFailed(String) }
impl std::fmt::Display for OrbitalError {
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, "Operation failed: {e}"),
Self::ResourceExhausted => write!(f, "Resource exhausted"),
Self::NotFound(e) => write!(f, "Not found: {e}"),
Self::Timeout => write!(f, "Operation timed out"),
match self { Self::NoRoute(e) => write!(f, "No route: {e}"), Self::CircuitOpen(e) => write!(f, "Circuit: {e}"), Self::AllPathsFailed(e) => write!(f, "All failed: {e}") }
}
}
impl std::error::Error for OrbitalError {}
#[derive(Debug, Clone)]
pub struct MeshNode { pub id: String, pub region: String, pub latency_ms: u32, pub capacity: u32, pub current_load: u32 }
#[derive(Debug, Clone)]
pub struct MeshEdge { pub from: String, pub to: String, pub latency_ms: u32, pub bandwidth_mbps: u32 }
#[derive(Debug, Clone)]
pub struct CircuitBreaker { pub failures: u32, pub threshold: u32, pub is_open: bool, pub last_failure: u64 }
impl CircuitBreaker {
pub fn new(threshold: u32) -> Self { Self { failures: 0, threshold, is_open: false, last_failure: 0 } }
pub fn record_failure(&mut self, now: u64) { self.failures += 1; self.last_failure = now; if self.failures >= self.threshold { self.is_open = true; } }
pub fn record_success(&mut self) { self.failures = 0; self.is_open = false; }
pub fn try_half_open(&mut self, now: u64, cooldown_secs: u64) -> bool {
if self.is_open && now - self.last_failure > cooldown_secs { self.is_open = false; self.failures = self.threshold - 1; return true; }
!self.is_open
}
}
pub struct OrbitalRouter {
nodes: HashMap<String, MeshNode>,
edges: Vec<MeshEdge>,
breakers: HashMap<String, CircuitBreaker>,
breaker_threshold: u32,
}
impl OrbitalRouter {
pub fn new(breaker_threshold: u32) -> Self {
Self { nodes: HashMap::new(), edges: Vec::new(), breakers: HashMap::new(), breaker_threshold }
}
pub fn add_node(&mut self, node: MeshNode) { self.nodes.insert(node.id.clone(), node); }
pub fn add_edge(&mut self, edge: MeshEdge) { self.edges.push(edge); }
/// Find best route using scoring (latency + load + circuit state)
pub fn find_route(&mut self, from: &str, to: &str, now: u64) -> Result<Vec<String>, OrbitalError> {
// Direct edge?
let direct: Vec<&MeshEdge> = self.edges.iter().filter(|e| e.from == from && e.to == to).collect();
for edge in &direct {
let key = format!("{}->{}", edge.from, edge.to);
let breaker = self.breakers.entry(key).or_insert_with(|| CircuitBreaker::new(self.breaker_threshold));
if breaker.try_half_open(now, 30) {
return Ok(vec![from.into(), to.into()]);
}
}
}
}
impl std::error::Error for XcuError {}
pub type Result<T> = std::result::Result<T, XcuError>;
// Multi-hop: find via intermediate nodes
let intermediates: Vec<String> = self.edges.iter()
.filter(|e| e.from == from)
.flat_map(|e1| {
self.edges.iter()
.filter(|e2| e2.from == e1.to && e2.to == to)
.map(move |e2| (e1.clone(), e2.clone()))
})
.map(|(e1, _)| e1.to.clone())
.collect();
pub struct Config {
pub params: HashMap<String, String>,
}
if intermediates.is_empty() { return Err(OrbitalError::NoRoute(format!("{from} -> {to}"))); }
impl Config {
pub fn new() -> Self { Self { params: HashMap::new() } }
pub fn set(&mut self, key: &str, val: &str) -> &mut Self {
self.params.insert(key.to_string(), val.to_string()); self
}
pub fn get(&self, key: &str) -> Result<&str> {
self.params.get(key).map(|s| s.as_str()).ok_or_else(|| XcuError::NotFound(key.to_string()))
}
}
impl Default for Config {
fn default() -> Self { Self::new() }
}
pub struct Engine {
config: Config,
state: Arc<Mutex<EngineState>>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum EngineState {
Idle,
Running,
Paused,
ShuttingDown,
Stopped,
}
impl Engine {
pub fn new(config: Config) -> Result<Self> {
Ok(Self { config, state: Arc::new(Mutex::new(EngineState::Idle)) })
// Score intermediates by latency + load
let mut best_hop = intermediates[0].clone();
let mut best_score = f64::MAX;
for hop in &intermediates {
let key = format!("{from}->{hop}");
let breaker = self.breakers.entry(key).or_insert_with(|| CircuitBreaker::new(self.breaker_threshold));
if !breaker.try_half_open(now, 30) { continue; }
if let Some(node) = self.nodes.get(hop) {
let load_ratio = if node.capacity > 0 { node.current_load as f64 / node.capacity as f64 } else { 1.0 };
let score = node.latency_ms as f64 + load_ratio * 100.0;
if score < best_score { best_score = score; best_hop = hop.clone(); }
}
}
Ok(vec![from.into(), best_hop, to.into()])
}
pub fn start(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::Running;
Ok(())
pub fn report_failure(&mut self, from: &str, to: &str, now: u64) {
let key = format!("{from}->{to}");
let breaker = self.breakers.entry(key).or_insert_with(|| CircuitBreaker::new(self.breaker_threshold));
breaker.record_failure(now);
}
pub fn stop(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::ShuttingDown;
// graceful shutdown logic
*s = EngineState::Stopped;
Ok(())
pub fn report_success(&mut self, from: &str, to: &str) {
let key = format!("{from}->{to}");
if let Some(breaker) = self.breakers.get_mut(&key) { breaker.record_success(); }
}
pub fn state(&self) -> Result<EngineState> {
let s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
Ok(s.clone())
}
pub fn config(&self) -> &Config { &self.config }
pub fn node_count(&self) -> usize { self.nodes.len() }
pub fn open_circuits(&self) -> usize { self.breakers.values().filter(|b| b.is_open).count() }
}
#[cfg(test)]
mod tests {
use super::*;
fn setup() -> OrbitalRouter {
let mut r = OrbitalRouter::new(3);
r.add_node(MeshNode { id: "a".into(), region: "sg".into(), latency_ms: 5, capacity: 100, current_load: 10 });
r.add_node(MeshNode { id: "b".into(), region: "jp".into(), latency_ms: 20, capacity: 100, current_load: 50 });
r.add_node(MeshNode { id: "c".into(), region: "de".into(), latency_ms: 10, capacity: 100, current_load: 20 });
r.add_edge(MeshEdge { from: "a".into(), to: "b".into(), latency_ms: 15, bandwidth_mbps: 100 });
r.add_edge(MeshEdge { from: "a".into(), to: "c".into(), latency_ms: 10, bandwidth_mbps: 100 });
r.add_edge(MeshEdge { from: "c".into(), to: "b".into(), latency_ms: 20, bandwidth_mbps: 50 });
r
}
#[test]
fn test_engine_lifecycle() {
let engine = Engine::new(Config::new()).unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Idle);
engine.start().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Running);
engine.stop().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Stopped);
fn test_direct_route() { let mut r = setup(); let route = r.find_route("a", "b", 1000).unwrap(); assert_eq!(route, vec!["a", "b"]); }
#[test]
fn test_circuit_breaker() {
let mut r = setup();
r.report_failure("a", "b", 100);
r.report_failure("a", "b", 101);
r.report_failure("a", "b", 102);
assert_eq!(r.open_circuits(), 1);
}
}
+130 -40
View File
@@ -1,73 +1,163 @@
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-qcg-wasm -- Quantum Compute Graph WASM Runtime
#![deny(warnings)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-qcg-wasm -- Quantum Code Gen WASM Runtime
//! JIT-compile & execute WASM bytecode with sandboxed memory
use serde::{Serialize, Deserialize};
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum WasmError {
CompileFailed(String),
RuntimeError(String),
MemoryError(String),
LinkError(String),
}
pub enum WasmError { CompileFailed(String), RuntimeError(String), MemoryError(String), LinkError(String) }
impl std::fmt::Display for WasmError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::CompileFailed(e) => write!(f, "Compile: {e}"),
Self::RuntimeError(e) => write!(f, "Runtime: {e}"),
Self::MemoryError(e) => write!(f, "Memory: {e}"),
Self::LinkError(e) => write!(f, "Link: {e}"),
}
match self { Self::CompileFailed(e) => write!(f, "Compile: {e}"), Self::RuntimeError(e) => write!(f, "Runtime: {e}"), Self::MemoryError(e) => write!(f, "Memory: {e}"), Self::LinkError(e) => write!(f, "Link: {e}") }
}
}
impl std::error::Error for WasmError {}
pub type Result<T> = std::result::Result<T, WasmError>;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone)]
pub enum WasmValue { I32(i32), I64(i64), F32(f32), F64(f64) }
#[derive(Debug, Clone)]
pub struct WasmModule {
pub name: String,
pub bytecode: Vec<u8>,
pub imports: Vec<String>,
pub exports: Vec<String>,
pub exports: Vec<WasmExport>,
pub memory_pages: u32,
pub bytecode_size: usize,
}
pub struct WasmRuntime {
modules: Arc<Mutex<HashMap<String, WasmModule>>>,
memory_limit: usize,
#[derive(Debug, Clone)]
pub struct WasmExport { pub name: String, pub kind: ExportKind, pub params: Vec<String>, pub returns: Vec<String> }
#[derive(Debug, Clone)]
pub enum ExportKind { Function, Memory, Table, Global }
/// Sandboxed WASM memory (page-based, 64KB per page)
pub struct WasmMemory {
pages: Vec<Vec<u8>>,
max_pages: u32,
}
impl WasmRuntime {
pub fn new(memory_limit: usize) -> Self {
Self { modules: Arc::new(Mutex::new(HashMap::new())), memory_limit }
impl WasmMemory {
pub fn new(initial_pages: u32, max_pages: u32) -> Result<Self, WasmError> {
if initial_pages > max_pages { return Err(WasmError::MemoryError(format!("{initial_pages} > {max_pages}"))); }
let mut pages = Vec::with_capacity(initial_pages as usize);
for _ in 0..initial_pages { pages.push(vec![0u8; 65536]); }
Ok(Self { pages, max_pages })
}
pub fn load_module(&self, module: WasmModule) -> Result<()> {
if (module.memory_pages as usize) * 65536 > self.memory_limit {
return Err(WasmError::MemoryError("exceeds limit".into()));
pub fn grow(&mut self, delta: u32) -> Result<u32, WasmError> {
let old = self.pages.len() as u32;
if old + delta > self.max_pages { return Err(WasmError::MemoryError(format!("Cannot grow beyond {}", self.max_pages))); }
for _ in 0..delta { self.pages.push(vec![0u8; 65536]); }
Ok(old)
}
pub fn read(&self, offset: usize, len: usize) -> Result<Vec<u8>, WasmError> {
let total = self.pages.len() * 65536;
if offset + len > total { return Err(WasmError::MemoryError(format!("OOB: {offset}+{len} > {total}"))); }
let mut result = Vec::with_capacity(len);
for i in offset..offset + len {
let page = i / 65536;
let off = i % 65536;
result.push(self.pages[page][off]);
}
Ok(result)
}
pub fn write(&mut self, offset: usize, data: &[u8]) -> Result<(), WasmError> {
let total = self.pages.len() * 65536;
if offset + data.len() > total { return Err(WasmError::MemoryError(format!("OOB write"))); }
for (i, &byte) in data.iter().enumerate() {
let addr = offset + i;
let page = addr / 65536;
let off = addr % 65536;
self.pages[page][off] = byte;
}
let mut mods = self.modules.lock().map_err(|e| WasmError::RuntimeError(e.to_string()))?;
mods.insert(module.name.clone(), module);
Ok(())
}
pub fn module_count(&self) -> usize { self.modules.lock().map(|m| m.len()).unwrap_or(0) }
pub fn size_bytes(&self) -> usize { self.pages.len() * 65536 }
pub fn page_count(&self) -> u32 { self.pages.len() as u32 }
}
/// WASM Instance runtime
pub struct WasmInstance {
module: WasmModule,
memory: WasmMemory,
globals: HashMap<String, WasmValue>,
call_count: u64,
}
impl WasmInstance {
pub fn new(module: WasmModule, max_memory_pages: u32) -> Result<Self, WasmError> {
let memory = WasmMemory::new(module.memory_pages, max_memory_pages)?;
Ok(Self { module, memory, globals: HashMap::new(), call_count: 0 })
}
pub fn set_global(&mut self, name: &str, val: WasmValue) { self.globals.insert(name.into(), val); }
pub fn get_global(&self, name: &str) -> Option<&WasmValue> { self.globals.get(name) }
/// Call exported function (simplified interpreter)
pub fn call(&mut self, name: &str, args: &[WasmValue]) -> Result<Vec<WasmValue>, WasmError> {
let export = self.module.exports.iter().find(|e| e.name == name && matches!(e.kind, ExportKind::Function))
.ok_or_else(|| WasmError::LinkError(format!("Export '{name}' not found")))?;
if args.len() != export.params.len() {
return Err(WasmError::RuntimeError(format!("Expected {} args, got {}", export.params.len(), args.len())));
}
self.call_count += 1;
// Simple built-in operations for demonstration
match name {
"add" => {
if let (Some(WasmValue::I32(a)), Some(WasmValue::I32(b))) = (args.get(0), args.get(1)) {
Ok(vec![WasmValue::I32(a.wrapping_add(*b))])
} else { Err(WasmError::RuntimeError("Type mismatch".into())) }
}
"mul" => {
if let (Some(WasmValue::I64(a)), Some(WasmValue::I64(b))) = (args.get(0), args.get(1)) {
Ok(vec![WasmValue::I64(a.wrapping_mul(*b))])
} else { Err(WasmError::RuntimeError("Type mismatch".into())) }
}
_ => Ok(vec![]) // Unknown export returns empty
}
}
pub fn memory(&self) -> &WasmMemory { &self.memory }
pub fn memory_mut(&mut self) -> &mut WasmMemory { &mut self.memory }
pub fn call_count(&self) -> u64 { self.call_count }
}
#[cfg(test)]
mod tests {
use super::*;
fn test_module() -> WasmModule {
WasmModule { name: "test".into(), memory_pages: 1, bytecode_size: 100,
exports: vec![WasmExport { name: "add".into(), kind: ExportKind::Function, params: vec!["i32".into(), "i32".into()], returns: vec!["i32".into()] }] }
}
#[test]
fn test_wasm_runtime() {
let rt = WasmRuntime::new(1_048_576);
rt.load_module(WasmModule {
name: "test".into(), bytecode: vec![0, 0x61, 0x73, 0x6d],
imports: vec![], exports: vec!["main".into()], memory_pages: 1,
}).unwrap();
assert_eq!(rt.module_count(), 1);
fn test_memory_rw() {
let mut mem = WasmMemory::new(1, 4).unwrap();
mem.write(100, &[1, 2, 3, 4]).unwrap();
let data = mem.read(100, 4).unwrap();
assert_eq!(data, vec![1, 2, 3, 4]);
}
#[test]
fn test_memory_grow() {
let mut mem = WasmMemory::new(1, 4).unwrap();
assert_eq!(mem.page_count(), 1);
mem.grow(2).unwrap();
assert_eq!(mem.page_count(), 3);
assert!(mem.grow(5).is_err());
}
#[test]
fn test_call() {
let mut inst = WasmInstance::new(test_module(), 4).unwrap();
let result = inst.call("add", &[WasmValue::I32(10), WasmValue::I32(20)]).unwrap();
if let Some(WasmValue::I32(n)) = result.first() { assert_eq!(*n, 30); }
}
#[test]
fn test_oob() {
let mem = WasmMemory::new(1, 1).unwrap();
assert!(mem.read(70000, 1).is_err());
}
}
+102 -81
View File
@@ -1,104 +1,125 @@
//! [TSM.ID].[11031972] — Platform X Ecosystem
//! xcu-render-pipeline — GPU render pipeline with DAG pass system
#![deny(warnings)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-render-pipeline -- GPU-agnostic Render Graph (DAG-based)
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum XcuError {
InitFailed(String),
InvalidConfig(String),
OperationFailed(String),
ResourceExhausted,
NotFound(String),
Timeout,
}
impl std::fmt::Display for XcuError {
pub enum RenderError { CyclicGraph(String), PassFailed(String), ResourceMissing(String) }
impl std::fmt::Display for RenderError {
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, "Operation failed: {e}"),
Self::ResourceExhausted => write!(f, "Resource exhausted"),
Self::NotFound(e) => write!(f, "Not found: {e}"),
Self::Timeout => write!(f, "Operation timed out"),
match self { Self::CyclicGraph(e) => write!(f, "Cycle: {e}"), Self::PassFailed(e) => write!(f, "Pass: {e}"), Self::ResourceMissing(e) => write!(f, "Missing: {e}") }
}
}
impl std::error::Error for RenderError {}
#[derive(Debug, Clone)]
pub enum GpuBackend { Vulkan, Metal, WebGpu, OpenGl, Software }
#[derive(Debug, Clone)]
pub struct RenderPass { pub name: String, pub inputs: Vec<String>, pub outputs: Vec<String>, pub shader: String }
#[derive(Debug, Clone)]
pub struct RenderResource { pub name: String, pub width: u32, pub height: u32, pub format: String, pub size_bytes: u64 }
pub struct RenderGraph {
passes: Vec<RenderPass>,
resources: HashMap<String, RenderResource>,
execution_order: Vec<usize>,
backend: GpuBackend,
}
impl RenderGraph {
pub fn new(backend: GpuBackend) -> Self {
Self { passes: Vec::new(), resources: HashMap::new(), execution_order: Vec::new(), backend }
}
pub fn add_pass(&mut self, pass: RenderPass) -> usize {
let idx = self.passes.len();
self.passes.push(pass);
idx
}
pub fn add_resource(&mut self, res: RenderResource) { self.resources.insert(res.name.clone(), res); }
/// Topological sort of render passes (DAG)
pub fn compile(&mut self) -> Result<Vec<String>, RenderError> {
let n = self.passes.len();
let mut in_degree = vec![0usize; n];
let mut adj: Vec<Vec<usize>> = vec![Vec::new(); n];
// Build dependency graph: if pass B reads output of pass A, A → B
for (i, pass_b) in self.passes.iter().enumerate() {
for input in &pass_b.inputs {
for (j, pass_a) in self.passes.iter().enumerate() {
if i != j && pass_a.outputs.contains(input) {
adj[j].push(i);
in_degree[i] += 1;
}
}
}
}
}
}
impl std::error::Error for XcuError {}
pub type Result<T> = std::result::Result<T, XcuError>;
pub struct Config {
pub params: HashMap<String, String>,
}
// Kahn's algorithm
let mut queue: Vec<usize> = (0..n).filter(|&i| in_degree[i] == 0).collect();
let mut order = Vec::new();
impl Config {
pub fn new() -> Self { Self { params: HashMap::new() } }
pub fn set(&mut self, key: &str, val: &str) -> &mut Self {
self.params.insert(key.to_string(), val.to_string()); self
}
pub fn get(&self, key: &str) -> Result<&str> {
self.params.get(key).map(|s| s.as_str()).ok_or_else(|| XcuError::NotFound(key.to_string()))
}
}
while let Some(node) = queue.pop() {
order.push(node);
for &next in &adj[node] {
in_degree[next] -= 1;
if in_degree[next] == 0 { queue.push(next); }
}
}
impl Default for Config {
fn default() -> Self { Self::new() }
}
if order.len() != n { return Err(RenderError::CyclicGraph("Dependency cycle detected".into())); }
pub struct Engine {
config: Config,
state: Arc<Mutex<EngineState>>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum EngineState {
Idle,
Running,
Paused,
ShuttingDown,
Stopped,
}
impl Engine {
pub fn new(config: Config) -> Result<Self> {
Ok(Self { config, state: Arc::new(Mutex::new(EngineState::Idle)) })
self.execution_order = order.clone();
Ok(order.iter().map(|&i| self.passes[i].name.clone()).collect())
}
pub fn start(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::Running;
/// Validate all pass inputs are available
pub fn validate(&self) -> Result<(), RenderError> {
let mut available: Vec<String> = self.resources.keys().cloned().collect();
for &idx in &self.execution_order {
let pass = &self.passes[idx];
for input in &pass.inputs {
if !available.contains(input) {
return Err(RenderError::ResourceMissing(format!("Pass '{}' needs '{}' but not produced yet", pass.name, input)));
}
}
for output in &pass.outputs { if !available.contains(output) { available.push(output.clone()); } }
}
Ok(())
}
pub fn stop(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::ShuttingDown;
// graceful shutdown logic
*s = EngineState::Stopped;
Ok(())
}
pub fn state(&self) -> Result<EngineState> {
let s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
Ok(s.clone())
}
pub fn config(&self) -> &Config { &self.config }
/// Estimate VRAM usage
pub fn estimate_vram(&self) -> u64 { self.resources.values().map(|r| r.size_bytes).sum() }
pub fn pass_count(&self) -> usize { self.passes.len() }
pub fn backend(&self) -> &GpuBackend { &self.backend }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_engine_lifecycle() {
let engine = Engine::new(Config::new()).unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Idle);
engine.start().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Running);
engine.stop().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Stopped);
fn test_compile_order() {
let mut g = RenderGraph::new(GpuBackend::WebGpu);
g.add_pass(RenderPass { name: "shadow".into(), inputs: vec![], outputs: vec!["shadow_map".into()], shader: "shadow.wgsl".into() });
g.add_pass(RenderPass { name: "gbuffer".into(), inputs: vec![], outputs: vec!["albedo".into(), "normal".into()], shader: "gbuffer.wgsl".into() });
g.add_pass(RenderPass { name: "lighting".into(), inputs: vec!["albedo".into(), "normal".into(), "shadow_map".into()], outputs: vec!["hdr".into()], shader: "lighting.wgsl".into() });
g.add_pass(RenderPass { name: "tonemap".into(), inputs: vec!["hdr".into()], outputs: vec!["final".into()], shader: "tonemap.wgsl".into() });
let order = g.compile().unwrap();
let light_idx = order.iter().position(|n| n == "lighting").unwrap();
let shadow_idx = order.iter().position(|n| n == "shadow").unwrap();
let gbuf_idx = order.iter().position(|n| n == "gbuffer").unwrap();
assert!(shadow_idx < light_idx);
assert!(gbuf_idx < light_idx);
}
#[test]
fn test_cycle_detection() {
let mut g = RenderGraph::new(GpuBackend::Vulkan);
g.add_pass(RenderPass { name: "a".into(), inputs: vec!["y".into()], outputs: vec!["x".into()], shader: "a".into() });
g.add_pass(RenderPass { name: "b".into(), inputs: vec!["x".into()], outputs: vec!["y".into()], shader: "b".into() });
assert!(g.compile().is_err());
}
}
+181 -2
View File
@@ -1,3 +1,182 @@
#![deny(warnings)]
// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
pub mod server;
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-rpc -- Binary RPC Protocol (zero-copy, schema-driven)
use std::collections::HashMap;
#[derive(Debug)]
pub enum RpcError { MethodNotFound(String), DeserializeFailed(String), Timeout(String), Internal(String) }
impl std::fmt::Display for RpcError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { Self::MethodNotFound(e) => write!(f, "Method: {e}"), Self::DeserializeFailed(e) => write!(f, "Deser: {e}"), Self::Timeout(e) => write!(f, "Timeout: {e}"), Self::Internal(e) => write!(f, "Internal: {e}") }
}
}
impl std::error::Error for RpcError {}
#[derive(Debug, Clone)]
pub enum RpcValue { Null, Bool(bool), Int(i64), Float(f64), Str(String), Bytes(Vec<u8>), Array(Vec<RpcValue>), Map(Vec<(String, RpcValue)>) }
/// Binary frame: [magic(2)][version(1)][flags(1)][method_len(2)][payload_len(4)][method][payload]
#[derive(Debug, Clone)]
pub struct RpcFrame {
pub request_id: u32,
pub method: String,
pub params: Vec<RpcValue>,
pub is_response: bool,
pub error: Option<String>,
}
const MAGIC: [u8; 2] = [0xXC, 0xU1]; // XCU magic
impl RpcFrame {
pub fn request(id: u32, method: &str, params: Vec<RpcValue>) -> Self {
Self { request_id: id, method: method.into(), params, is_response: false, error: None }
}
pub fn response(id: u32, result: Vec<RpcValue>) -> Self {
Self { request_id: id, method: String::new(), params: result, is_response: true, error: None }
}
pub fn error_response(id: u32, err: &str) -> Self {
Self { request_id: id, method: String::new(), params: Vec::new(), is_response: true, error: Some(err.into()) }
}
/// Serialize to binary frame
pub fn encode(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(64);
buf.extend_from_slice(&[0xC0, 0x01]); // magic
buf.push(1); // version
buf.push(if self.is_response { 1 } else { 0 }); // flags
buf.extend_from_slice(&self.request_id.to_be_bytes());
let method_bytes = self.method.as_bytes();
buf.extend_from_slice(&(method_bytes.len() as u16).to_be_bytes());
buf.extend_from_slice(method_bytes);
// Encode params count
buf.extend_from_slice(&(self.params.len() as u16).to_be_bytes());
for p in &self.params { Self::encode_value(&mut buf, p); }
// Error field
if let Some(ref err) = self.error {
buf.push(1);
let err_bytes = err.as_bytes();
buf.extend_from_slice(&(err_bytes.len() as u16).to_be_bytes());
buf.extend_from_slice(err_bytes);
} else { buf.push(0); }
buf
}
fn encode_value(buf: &mut Vec<u8>, val: &RpcValue) {
match val {
RpcValue::Null => buf.push(0),
RpcValue::Bool(b) => { buf.push(1); buf.push(if *b { 1 } else { 0 }); }
RpcValue::Int(n) => { buf.push(2); buf.extend_from_slice(&n.to_be_bytes()); }
RpcValue::Float(n) => { buf.push(3); buf.extend_from_slice(&n.to_be_bytes()); }
RpcValue::Str(s) => { buf.push(4); let b = s.as_bytes(); buf.extend_from_slice(&(b.len() as u32).to_be_bytes()); buf.extend_from_slice(b); }
RpcValue::Bytes(b) => { buf.push(5); buf.extend_from_slice(&(b.len() as u32).to_be_bytes()); buf.extend_from_slice(b); }
RpcValue::Array(arr) => { buf.push(6); buf.extend_from_slice(&(arr.len() as u16).to_be_bytes()); for v in arr { Self::encode_value(buf, v); } }
RpcValue::Map(m) => { buf.push(7); buf.extend_from_slice(&(m.len() as u16).to_be_bytes()); for (k, v) in m { let kb = k.as_bytes(); buf.extend_from_slice(&(kb.len() as u16).to_be_bytes()); buf.extend_from_slice(kb); Self::encode_value(buf, v); } }
}
}
/// Decode from binary
pub fn decode(data: &[u8]) -> Result<Self, RpcError> {
if data.len() < 10 { return Err(RpcError::DeserializeFailed("Too short".into())); }
if data[0] != 0xC0 || data[1] != 0x01 { return Err(RpcError::DeserializeFailed("Bad magic".into())); }
let is_response = data[3] == 1;
let request_id = u32::from_be_bytes([data[4], data[5], data[6], data[7]]);
let method_len = u16::from_be_bytes([data[8], data[9]]) as usize;
let mut pos = 10;
if pos + method_len > data.len() { return Err(RpcError::DeserializeFailed("Method truncated".into())); }
let method = String::from_utf8_lossy(&data[pos..pos + method_len]).to_string();
pos += method_len;
// Params
if pos + 2 > data.len() { return Err(RpcError::DeserializeFailed("No params count".into())); }
let param_count = u16::from_be_bytes([data[pos], data[pos + 1]]) as usize;
pos += 2;
let mut params = Vec::with_capacity(param_count);
for _ in 0..param_count {
let (val, new_pos) = Self::decode_value(data, pos)?;
params.push(val);
pos = new_pos;
}
// Error
let error = if pos < data.len() && data[pos] == 1 {
pos += 1;
if pos + 2 <= data.len() {
let err_len = u16::from_be_bytes([data[pos], data[pos + 1]]) as usize;
pos += 2;
if pos + err_len <= data.len() { Some(String::from_utf8_lossy(&data[pos..pos + err_len]).to_string()) } else { None }
} else { None }
} else { None };
Ok(Self { request_id, method, params, is_response, error })
}
fn decode_value(data: &[u8], pos: usize) -> Result<(RpcValue, usize), RpcError> {
if pos >= data.len() { return Err(RpcError::DeserializeFailed("EOF".into())); }
let tag = data[pos];
let mut p = pos + 1;
match tag {
0 => Ok((RpcValue::Null, p)),
1 => { if p >= data.len() { return Err(RpcError::DeserializeFailed("Bool".into())); } let v = data[p] != 0; Ok((RpcValue::Bool(v), p + 1)) }
2 => { if p + 8 > data.len() { return Err(RpcError::DeserializeFailed("Int".into())); } let n = i64::from_be_bytes([data[p],data[p+1],data[p+2],data[p+3],data[p+4],data[p+5],data[p+6],data[p+7]]); Ok((RpcValue::Int(n), p + 8)) }
3 => { if p + 8 > data.len() { return Err(RpcError::DeserializeFailed("Float".into())); } let n = f64::from_be_bytes([data[p],data[p+1],data[p+2],data[p+3],data[p+4],data[p+5],data[p+6],data[p+7]]); Ok((RpcValue::Float(n), p + 8)) }
4 => { if p + 4 > data.len() { return Err(RpcError::DeserializeFailed("Str len".into())); } let len = u32::from_be_bytes([data[p],data[p+1],data[p+2],data[p+3]]) as usize; p += 4; if p + len > data.len() { return Err(RpcError::DeserializeFailed("Str".into())); } let s = String::from_utf8_lossy(&data[p..p+len]).to_string(); Ok((RpcValue::Str(s), p + len)) }
5 => { if p + 4 > data.len() { return Err(RpcError::DeserializeFailed("Bytes len".into())); } let len = u32::from_be_bytes([data[p],data[p+1],data[p+2],data[p+3]]) as usize; p += 4; if p + len > data.len() { return Err(RpcError::DeserializeFailed("Bytes".into())); } Ok((RpcValue::Bytes(data[p..p+len].to_vec()), p + len)) }
_ => Ok((RpcValue::Null, p)),
}
}
}
/// RPC Router: method → handler dispatch
pub struct RpcRouter {
methods: HashMap<String, Box<dyn Fn(Vec<RpcValue>) -> Result<Vec<RpcValue>, RpcError> + Send + Sync>>,
}
impl RpcRouter {
pub fn new() -> Self { Self { methods: HashMap::new() } }
pub fn register<F>(&mut self, method: &str, handler: F) where F: Fn(Vec<RpcValue>) -> Result<Vec<RpcValue>, RpcError> + Send + Sync + 'static {
self.methods.insert(method.into(), Box::new(handler));
}
pub fn dispatch(&self, frame: RpcFrame) -> RpcFrame {
match self.methods.get(&frame.method) {
Some(handler) => match handler(frame.params) {
Ok(result) => RpcFrame::response(frame.request_id, result),
Err(e) => RpcFrame::error_response(frame.request_id, &e.to_string()),
},
None => RpcFrame::error_response(frame.request_id, &format!("Method '{}' not found", frame.method)),
}
}
pub fn method_count(&self) -> usize { self.methods.len() }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_decode() {
let frame = RpcFrame::request(42, "echo", vec![RpcValue::Str("hello".into()), RpcValue::Int(123)]);
let encoded = frame.encode();
let decoded = RpcFrame::decode(&encoded).unwrap();
assert_eq!(decoded.request_id, 42);
assert_eq!(decoded.method, "echo");
assert_eq!(decoded.params.len(), 2);
}
#[test]
fn test_router() {
let mut router = RpcRouter::new();
router.register("add", |params| {
if let (Some(RpcValue::Int(a)), Some(RpcValue::Int(b))) = (params.get(0), params.get(1)) {
Ok(vec![RpcValue::Int(a + b)])
} else { Err(RpcError::Internal("Bad args".into())) }
});
let req = RpcFrame::request(1, "add", vec![RpcValue::Int(10), RpcValue::Int(20)]);
let resp = router.dispatch(req);
assert!(resp.is_response);
if let Some(RpcValue::Int(n)) = resp.params.first() { assert_eq!(*n, 30); }
}
#[test]
fn test_method_not_found() {
let router = RpcRouter::new();
let req = RpcFrame::request(1, "missing", vec![]);
let resp = router.dispatch(req);
assert!(resp.error.is_some());
}
}
+94 -86
View File
@@ -1,104 +1,112 @@
//! [TSM.ID].[11031972] — Platform X Ecosystem
//! xcu-state-machine — Hierarchical state machine with hot-reload
#![deny(warnings)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-state-machine -- Hierarchical State Machine with hot-reload
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum XcuError {
InitFailed(String),
InvalidConfig(String),
OperationFailed(String),
ResourceExhausted,
NotFound(String),
Timeout,
}
impl std::fmt::Display for XcuError {
pub enum SmError { InvalidTransition(String), StateNotFound(String), GuardFailed(String) }
impl std::fmt::Display for SmError {
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, "Operation failed: {e}"),
Self::ResourceExhausted => write!(f, "Resource exhausted"),
Self::NotFound(e) => write!(f, "Not found: {e}"),
Self::Timeout => write!(f, "Operation timed out"),
match self { Self::InvalidTransition(e) => write!(f, "Invalid: {e}"), Self::StateNotFound(e) => write!(f, "State: {e}"), Self::GuardFailed(e) => write!(f, "Guard: {e}") }
}
}
impl std::error::Error for SmError {}
#[derive(Debug, Clone)]
pub struct State { pub name: String, pub parent: Option<String>, pub is_final: bool }
#[derive(Debug, Clone)]
pub struct Transition { pub from: String, pub to: String, pub event: String, pub guard: Option<String> }
pub struct StateMachine {
states: HashMap<String, State>,
transitions: Vec<Transition>,
current: String,
history: Vec<(String, String, String)>, // (from, event, to)
guards: HashMap<String, Box<dyn Fn() -> bool + Send + Sync>>,
}
impl StateMachine {
pub fn new(initial: &str) -> Self {
let mut states = HashMap::new();
states.insert(initial.into(), State { name: initial.into(), parent: None, is_final: false });
Self { states, transitions: Vec::new(), current: initial.into(), history: Vec::new(), guards: HashMap::new() }
}
pub fn add_state(&mut self, state: State) { self.states.insert(state.name.clone(), state); }
pub fn add_transition(&mut self, t: Transition) { self.transitions.push(t); }
pub fn add_guard<F>(&mut self, name: &str, f: F) where F: Fn() -> bool + Send + Sync + 'static { self.guards.insert(name.into(), Box::new(f)); }
pub fn fire(&mut self, event: &str) -> Result<&str, SmError> {
let matching: Vec<&Transition> = self.transitions.iter()
.filter(|t| t.from == self.current && t.event == event).collect();
if matching.is_empty() {
return Err(SmError::InvalidTransition(format!("No transition from '{}' on '{}'", self.current, event)));
}
}
}
impl std::error::Error for XcuError {}
pub type Result<T> = std::result::Result<T, XcuError>;
pub struct Config {
pub params: HashMap<String, String>,
}
impl Config {
pub fn new() -> Self { Self { params: HashMap::new() } }
pub fn set(&mut self, key: &str, val: &str) -> &mut Self {
self.params.insert(key.to_string(), val.to_string()); self
}
pub fn get(&self, key: &str) -> Result<&str> {
self.params.get(key).map(|s| s.as_str()).ok_or_else(|| XcuError::NotFound(key.to_string()))
}
}
impl Default for Config {
fn default() -> Self { Self::new() }
}
pub struct Engine {
config: Config,
state: Arc<Mutex<EngineState>>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum EngineState {
Idle,
Running,
Paused,
ShuttingDown,
Stopped,
}
impl Engine {
pub fn new(config: Config) -> Result<Self> {
Ok(Self { config, state: Arc::new(Mutex::new(EngineState::Idle)) })
for t in &matching {
if let Some(ref guard_name) = t.guard {
if let Some(guard_fn) = self.guards.get(guard_name) {
if !guard_fn() { continue; }
} else { return Err(SmError::GuardFailed(format!("Guard '{guard_name}' not found"))); }
}
let from = self.current.clone();
self.current = t.to.clone();
self.history.push((from, event.into(), t.to.clone()));
return Ok(&self.current);
}
Err(SmError::GuardFailed(format!("All guards failed for '{event}'")))
}
pub fn start(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::Running;
pub fn current(&self) -> &str { &self.current }
pub fn is_final(&self) -> bool { self.states.get(&self.current).map(|s| s.is_final).unwrap_or(false) }
pub fn history(&self) -> &[(String, String, String)] { &self.history }
/// Serialize state for hot-reload
pub fn snapshot(&self) -> (String, Vec<(String, String, String)>) {
(self.current.clone(), self.history.clone())
}
/// Restore from snapshot
pub fn restore(&mut self, current: &str, history: Vec<(String, String, String)>) -> Result<(), SmError> {
if !self.states.contains_key(current) { return Err(SmError::StateNotFound(current.into())); }
self.current = current.into();
self.history = history;
Ok(())
}
pub fn stop(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::ShuttingDown;
// graceful shutdown logic
*s = EngineState::Stopped;
Ok(())
}
pub fn state(&self) -> Result<EngineState> {
let s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
Ok(s.clone())
}
pub fn config(&self) -> &Config { &self.config }
}
#[cfg(test)]
mod tests {
use super::*;
fn call_sm() -> StateMachine {
let mut sm = StateMachine::new("idle");
sm.add_state(State { name: "ringing".into(), parent: None, is_final: false });
sm.add_state(State { name: "connected".into(), parent: None, is_final: false });
sm.add_state(State { name: "ended".into(), parent: None, is_final: true });
sm.add_transition(Transition { from: "idle".into(), to: "ringing".into(), event: "call".into(), guard: None });
sm.add_transition(Transition { from: "ringing".into(), to: "connected".into(), event: "answer".into(), guard: None });
sm.add_transition(Transition { from: "connected".into(), to: "ended".into(), event: "hangup".into(), guard: None });
sm.add_transition(Transition { from: "ringing".into(), to: "ended".into(), event: "reject".into(), guard: None });
sm
}
#[test]
fn test_engine_lifecycle() {
let engine = Engine::new(Config::new()).unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Idle);
engine.start().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Running);
engine.stop().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Stopped);
fn test_transitions() {
let mut sm = call_sm();
sm.fire("call").unwrap();
assert_eq!(sm.current(), "ringing");
sm.fire("answer").unwrap();
assert_eq!(sm.current(), "connected");
sm.fire("hangup").unwrap();
assert!(sm.is_final());
}
#[test]
fn test_invalid() { let mut sm = call_sm(); assert!(sm.fire("hangup").is_err()); }
#[test]
fn test_snapshot_restore() {
let mut sm = call_sm();
sm.fire("call").unwrap();
let (state, hist) = sm.snapshot();
let mut sm2 = call_sm();
sm2.restore(&state, hist).unwrap();
assert_eq!(sm2.current(), "ringing");
}
}
+102 -83
View File
@@ -1,104 +1,123 @@
//! [TSM.ID].[11031972] — Platform X Ecosystem
//! xcu-thread-weaver — Work-stealing thread pool scheduler
#![deny(warnings)]
use std::collections::HashMap;
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-thread-weaver -- Work-Stealing Thread Pool & NPU Scheduler
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum XcuError {
InitFailed(String),
InvalidConfig(String),
OperationFailed(String),
ResourceExhausted,
NotFound(String),
Timeout,
}
impl std::fmt::Display for XcuError {
pub enum WeaverError { QueueFull(String), WorkerPanicked(String), InvalidConfig(String) }
impl std::fmt::Display for WeaverError {
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, "Operation failed: {e}"),
Self::ResourceExhausted => write!(f, "Resource exhausted"),
Self::NotFound(e) => write!(f, "Not found: {e}"),
Self::Timeout => write!(f, "Operation timed out"),
match self { Self::QueueFull(e) => write!(f, "Full: {e}"), Self::WorkerPanicked(e) => write!(f, "Panic: {e}"), Self::InvalidConfig(e) => write!(f, "Config: {e}") }
}
}
impl std::error::Error for WeaverError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum TaskPriority { Critical = 0, High = 1, Normal = 2, Low = 3, Background = 4 }
#[derive(Debug, Clone)]
pub struct WeaverTask { pub id: String, pub priority: TaskPriority, pub data: Vec<u8>, pub created_at: u64 }
struct WorkerQueue { deque: VecDeque<WeaverTask>, processed: u64, stolen_from: u64 }
impl WorkerQueue {
fn new() -> Self { Self { deque: VecDeque::new(), processed: 0, stolen_from: 0 } }
fn push(&mut self, task: WeaverTask) {
// Insert sorted by priority
let pos = self.deque.iter().position(|t| t.priority > task.priority).unwrap_or(self.deque.len());
self.deque.insert(pos, task);
}
fn pop(&mut self) -> Option<WeaverTask> { let t = self.deque.pop_front(); if t.is_some() { self.processed += 1; } t }
fn steal(&mut self) -> Option<WeaverTask> { let t = self.deque.pop_back(); if t.is_some() { self.stolen_from += 1; } t }
fn len(&self) -> usize { self.deque.len() }
}
pub struct ThreadWeaver {
queues: Vec<Arc<Mutex<WorkerQueue>>>,
worker_count: usize,
next_worker: Mutex<usize>,
}
impl ThreadWeaver {
pub fn new(workers: usize) -> Result<Self, WeaverError> {
if workers == 0 { return Err(WeaverError::InvalidConfig("Workers must be > 0".into())); }
let queues: Vec<_> = (0..workers).map(|_| Arc::new(Mutex::new(WorkerQueue::new()))).collect();
Ok(Self { queues, worker_count: workers, next_worker: Mutex::new(0) })
}
/// Submit task (round-robin assignment)
pub fn submit(&self, task: WeaverTask) -> Result<usize, WeaverError> {
let mut next = self.next_worker.lock().map_err(|_| WeaverError::QueueFull("Lock".into()))?;
let idx = *next % self.worker_count;
*next = (*next + 1) % self.worker_count;
drop(next);
if let Ok(mut q) = self.queues[idx].lock() { q.push(task); Ok(idx) }
else { Err(WeaverError::QueueFull("Worker lock".into())) }
}
/// Worker picks next task (own queue first, then steal)
pub fn pick_task(&self, worker_id: usize) -> Option<WeaverTask> {
// Try own queue first
if let Ok(mut q) = self.queues[worker_id].lock() {
if let Some(task) = q.pop() { return Some(task); }
}
}
}
impl std::error::Error for XcuError {}
pub type Result<T> = std::result::Result<T, XcuError>;
pub struct Config {
pub params: HashMap<String, String>,
}
impl Config {
pub fn new() -> Self { Self { params: HashMap::new() } }
pub fn set(&mut self, key: &str, val: &str) -> &mut Self {
self.params.insert(key.to_string(), val.to_string()); self
}
pub fn get(&self, key: &str) -> Result<&str> {
self.params.get(key).map(|s| s.as_str()).ok_or_else(|| XcuError::NotFound(key.to_string()))
}
}
impl Default for Config {
fn default() -> Self { Self::new() }
}
pub struct Engine {
config: Config,
state: Arc<Mutex<EngineState>>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum EngineState {
Idle,
Running,
Paused,
ShuttingDown,
Stopped,
}
impl Engine {
pub fn new(config: Config) -> Result<Self> {
Ok(Self { config, state: Arc::new(Mutex::new(EngineState::Idle)) })
// Work stealing: try other queues
for i in 0..self.worker_count {
if i == worker_id { continue; }
if let Ok(mut q) = self.queues[i].lock() {
if q.len() > 1 { // Only steal if other has > 1 task
if let Some(task) = q.steal() { return Some(task); }
}
}
}
None
}
pub fn start(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::Running;
Ok(())
/// Get queue stats
pub fn stats(&self) -> Vec<(usize, u64, u64)> {
self.queues.iter().enumerate().map(|(i, q)| {
if let Ok(q) = q.lock() { (q.len(), q.processed, q.stolen_from) }
else { (0, 0, 0) }
}).collect()
}
pub fn stop(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::ShuttingDown;
// graceful shutdown logic
*s = EngineState::Stopped;
Ok(())
pub fn total_pending(&self) -> usize {
self.queues.iter().map(|q| q.lock().map(|q| q.len()).unwrap_or(0)).sum()
}
pub fn state(&self) -> Result<EngineState> {
let s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
Ok(s.clone())
pub fn total_processed(&self) -> u64 {
self.queues.iter().map(|q| q.lock().map(|q| q.processed).unwrap_or(0)).sum()
}
pub fn config(&self) -> &Config { &self.config }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_engine_lifecycle() {
let engine = Engine::new(Config::new()).unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Idle);
engine.start().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Running);
engine.stop().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Stopped);
fn test_submit_pick() {
let w = ThreadWeaver::new(4).unwrap();
w.submit(WeaverTask { id: "t1".into(), priority: TaskPriority::Normal, data: vec![], created_at: 0 }).unwrap();
let task = w.pick_task(0).unwrap();
assert_eq!(task.id, "t1");
}
#[test]
fn test_priority_ordering() {
let w = ThreadWeaver::new(1).unwrap();
w.submit(WeaverTask { id: "low".into(), priority: TaskPriority::Low, data: vec![], created_at: 0 }).unwrap();
w.submit(WeaverTask { id: "crit".into(), priority: TaskPriority::Critical, data: vec![], created_at: 0 }).unwrap();
w.submit(WeaverTask { id: "high".into(), priority: TaskPriority::Critical, data: vec![], created_at: 0 }).unwrap();
let first = w.pick_task(0).unwrap();
assert_eq!(first.id, "crit"); // Critical first
}
#[test]
fn test_work_stealing() {
let w = ThreadWeaver::new(2).unwrap();
// Submit 3 tasks to worker 0
for i in 0..3 {
let idx = w.submit(WeaverTask { id: format!("t{i}"), priority: TaskPriority::Normal, data: vec![], created_at: 0 }).unwrap();
}
// Worker 1 has nothing, should steal
let stolen = w.pick_task(1);
assert!(stolen.is_some());
}
}
+129 -82
View File
@@ -1,104 +1,151 @@
//! [TSM.ID].[11031972] — Platform X Ecosystem
//! xcu-v8-sandbox — JavaScript execution sandbox with resource limits
#![deny(warnings)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-v8-sandbox -- JavaScript Execution Sandbox with Permission System
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum XcuError {
InitFailed(String),
InvalidConfig(String),
OperationFailed(String),
ResourceExhausted,
NotFound(String),
Timeout,
}
impl std::fmt::Display for XcuError {
pub enum SandboxError { PermissionDenied(String), MemoryExceeded(String), TimeoutError(String), ScriptError(String) }
impl std::fmt::Display for SandboxError {
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, "Operation failed: {e}"),
Self::ResourceExhausted => write!(f, "Resource exhausted"),
Self::NotFound(e) => write!(f, "Not found: {e}"),
Self::Timeout => write!(f, "Operation timed out"),
match self { Self::PermissionDenied(e) => write!(f, "Permission: {e}"), Self::MemoryExceeded(e) => write!(f, "Memory: {e}"), Self::TimeoutError(e) => write!(f, "Timeout: {e}"), Self::ScriptError(e) => write!(f, "Script: {e}") }
}
}
impl std::error::Error for SandboxError {}
#[derive(Debug, Clone)]
pub struct SandboxPolicy {
pub max_memory_mb: u64,
pub max_execution_ms: u64,
pub allowed_apis: Vec<String>,
pub denied_apis: Vec<String>,
pub allow_network: bool,
pub allow_fs: bool,
pub allow_eval: bool,
}
impl Default for SandboxPolicy {
fn default() -> Self {
Self { max_memory_mb: 128, max_execution_ms: 5000,
allowed_apis: vec!["console".into(), "Math".into(), "JSON".into(), "Date".into(), "Array".into(), "Object".into(), "String".into()],
denied_apis: vec!["eval".into(), "Function".into(), "require".into(), "import".into(), "process".into(), "fs".into()],
allow_network: false, allow_fs: false, allow_eval: false }
}
}
#[derive(Debug, Clone)]
pub enum JsValue { Undefined, Null, Bool(bool), Number(f64), Str(String), Array(Vec<JsValue>), Object(HashMap<String, JsValue>) }
#[derive(Debug, Clone)]
pub struct ScriptResult { pub value: JsValue, pub memory_used_bytes: u64, pub execution_ms: u64, pub api_calls: Vec<String> }
pub struct JsSandbox {
policy: SandboxPolicy,
globals: HashMap<String, JsValue>,
audit_log: Arc<Mutex<Vec<String>>>,
}
impl JsSandbox {
pub fn new(policy: SandboxPolicy) -> Self {
Self { policy, globals: HashMap::new(), audit_log: Arc::new(Mutex::new(Vec::new())) }
}
pub fn set_global(&mut self, name: &str, value: JsValue) { self.globals.insert(name.into(), value); }
/// Check if API call is permitted
pub fn check_api(&self, api_name: &str) -> Result<(), SandboxError> {
if self.policy.denied_apis.iter().any(|d| api_name.starts_with(d)) {
return Err(SandboxError::PermissionDenied(format!("API '{api_name}' is denied")));
}
if !api_name.contains('.') && !self.policy.allowed_apis.iter().any(|a| api_name.starts_with(a)) {
return Err(SandboxError::PermissionDenied(format!("API '{api_name}' not in allow list")));
}
}
}
impl std::error::Error for XcuError {}
pub type Result<T> = std::result::Result<T, XcuError>;
pub struct Config {
pub params: HashMap<String, String>,
}
impl Config {
pub fn new() -> Self { Self { params: HashMap::new() } }
pub fn set(&mut self, key: &str, val: &str) -> &mut Self {
self.params.insert(key.to_string(), val.to_string()); self
}
pub fn get(&self, key: &str) -> Result<&str> {
self.params.get(key).map(|s| s.as_str()).ok_or_else(|| XcuError::NotFound(key.to_string()))
}
}
impl Default for Config {
fn default() -> Self { Self::new() }
}
pub struct Engine {
config: Config,
state: Arc<Mutex<EngineState>>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum EngineState {
Idle,
Running,
Paused,
ShuttingDown,
Stopped,
}
impl Engine {
pub fn new(config: Config) -> Result<Self> {
Ok(Self { config, state: Arc::new(Mutex::new(EngineState::Idle)) })
}
pub fn start(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::Running;
Ok(())
}
pub fn stop(&self) -> Result<()> {
let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
*s = EngineState::ShuttingDown;
// graceful shutdown logic
*s = EngineState::Stopped;
Ok(())
/// Evaluate simple expression (interpreter for basic math/string ops)
pub fn eval_expr(&mut self, expr: &str) -> Result<ScriptResult, SandboxError> {
if !self.policy.allow_eval && expr.contains("eval(") {
return Err(SandboxError::PermissionDenied("eval() is disabled".into()));
}
let trimmed = expr.trim();
let mut api_calls = Vec::new();
// Check for denied APIs in expression
for denied in &self.policy.denied_apis {
if trimmed.contains(denied.as_str()) {
return Err(SandboxError::PermissionDenied(format!("'{denied}' found in expression")));
}
}
// Simple expression evaluator
let value = if let Ok(n) = trimmed.parse::<f64>() {
JsValue::Number(n)
} else if trimmed.starts_with('"') && trimmed.ends_with('"') {
JsValue::Str(trimmed[1..trimmed.len()-1].to_string())
} else if trimmed == "true" { JsValue::Bool(true) }
else if trimmed == "false" { JsValue::Bool(false) }
else if trimmed == "null" { JsValue::Null }
else if trimmed.starts_with("Math.") {
api_calls.push("Math".into());
match trimmed {
"Math.PI" => JsValue::Number(std::f64::consts::PI),
"Math.E" => JsValue::Number(std::f64::consts::E),
"Math.SQRT2" => JsValue::Number(std::f64::consts::SQRT_2),
_ => JsValue::Undefined,
}
} else if let Some(var) = self.globals.get(trimmed) { var.clone() }
else { JsValue::Undefined };
// Log
if let Ok(mut log) = self.audit_log.lock() { log.push(format!("eval: {trimmed}")); }
Ok(ScriptResult { value, memory_used_bytes: trimmed.len() as u64, execution_ms: 0, api_calls })
}
pub fn state(&self) -> Result<EngineState> {
let s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
Ok(s.clone())
/// Check memory budget
pub fn check_memory(&self, used_bytes: u64) -> Result<(), SandboxError> {
let limit = self.policy.max_memory_mb * 1024 * 1024;
if used_bytes > limit { Err(SandboxError::MemoryExceeded(format!("{}B > {}B", used_bytes, limit))) }
else { Ok(()) }
}
pub fn config(&self) -> &Config { &self.config }
pub fn audit_log(&self) -> Vec<String> { self.audit_log.lock().map(|l| l.clone()).unwrap_or_default() }
pub fn policy(&self) -> &SandboxPolicy { &self.policy }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_engine_lifecycle() {
let engine = Engine::new(Config::new()).unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Idle);
engine.start().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Running);
engine.stop().unwrap();
assert_eq!(engine.state().unwrap(), EngineState::Stopped);
fn test_api_check() {
let sb = JsSandbox::new(SandboxPolicy::default());
assert!(sb.check_api("Math").is_ok());
assert!(sb.check_api("console").is_ok());
assert!(sb.check_api("eval").is_err());
assert!(sb.check_api("require").is_err());
}
#[test]
fn test_eval_number() {
let mut sb = JsSandbox::new(SandboxPolicy::default());
let r = sb.eval_expr("42").unwrap();
if let JsValue::Number(n) = r.value { assert_eq!(n, 42.0); }
}
#[test]
fn test_eval_denied() {
let mut sb = JsSandbox::new(SandboxPolicy::default());
assert!(sb.eval_expr("require('fs')").is_err());
}
#[test]
fn test_eval_math() {
let mut sb = JsSandbox::new(SandboxPolicy::default());
let r = sb.eval_expr("Math.PI").unwrap();
if let JsValue::Number(n) = r.value { assert!((n - std::f64::consts::PI).abs() < 0.001); }
}
#[test]
fn test_globals() {
let mut sb = JsSandbox::new(SandboxPolicy::default());
sb.set_global("x", JsValue::Number(99.0));
let r = sb.eval_expr("x").unwrap();
if let JsValue::Number(n) = r.value { assert_eq!(n, 99.0); }
}
}