#![allow(unexpected_cfgs)]
use std::collections::HashMap;
use std::os::unix::io::RawFd;
use std::sync::{Arc, Mutex};
use std::time::{Duration, SystemTime};
use crate::parser::WasmaConfig;
use crate::uclient::SectionMemory;
use crate::wasma_client_unix_posix_raw_app::{posix, UClientEngine};
use crate::window_handling::{WindowGeometry, WindowState, WindowType};
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ArchKind {
Amd64,
Aarch64,
RiscV64,
OpenRisc,
PowerPc64,
Sparc64,
Sisd,
Unknown,
}
impl ArchKind {
pub const fn current() -> Self {
#[cfg(target_arch = "x86_64")]
{
return Self::Amd64;
}
#[cfg(target_arch = "aarch64")]
{
return Self::Aarch64;
}
#[cfg(target_arch = "riscv64")]
{
return Self::RiscV64;
}
#[cfg(target_arch = "or1k")]
{
return Self::OpenRisc;
}
#[cfg(target_arch = "powerpc64")]
{
return Self::PowerPc64;
}
#[cfg(target_arch = "sparc64")]
{
return Self::Sparc64;
}
#[cfg(any(
target_arch = "x86",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
))]
{
return Self::Sisd;
}
#[allow(unreachable_code)]
Self::Unknown
}
pub fn name(&self) -> &'static str {
match self {
Self::Amd64 => "x86_64 (AMD64)",
Self::Aarch64 => "AArch64 (ARM64)",
Self::RiscV64 => "RISC-V 64",
Self::OpenRisc => "OpenRISC 1000",
Self::PowerPc64 => "PowerPC 64",
Self::Sparc64 => "SPARC 64",
Self::Sisd => "SISD (partial support)",
Self::Unknown => "Unknown (scalar fallback)",
}
}
pub fn supports_simd(&self) -> bool {
matches!(
self,
Self::Amd64 | Self::Aarch64 | Self::PowerPc64 | Self::Sparc64
)
}
pub fn supports_avx(&self) -> bool {
matches!(self, Self::Amd64)
}
pub fn is_partial(&self) -> bool {
matches!(self, Self::Sisd | Self::Unknown)
}
pub fn pointer_width(&self) -> u8 {
match self {
Self::Sisd => 32,
_ => 64,
}
}
}
pub const CURRENT_ARCH: ArchKind = ArchKind::current();
pub struct ArchBackend;
impl ArchBackend {
pub fn process_chunk(data: &[u8]) -> usize {
match CURRENT_ARCH {
ArchKind::Amd64 => Self::process_amd64(data),
ArchKind::Aarch64 => Self::process_aarch64(data),
ArchKind::RiscV64 => Self::process_riscv64(data),
ArchKind::OpenRisc => Self::process_openrisc(data),
ArchKind::PowerPc64 => Self::process_powerpc64(data),
ArchKind::Sparc64 => Self::process_sparc64(data),
ArchKind::Sisd => Self::process_sisd(data),
ArchKind::Unknown => Self::process_scalar_fallback(data),
}
}
pub fn dispatch_pixels(data: &[u8], renderer: &str) -> usize {
match CURRENT_ARCH {
ArchKind::Amd64 => Self::dispatch_amd64(data, renderer),
ArchKind::Aarch64 => Self::dispatch_aarch64(data, renderer),
ArchKind::RiscV64 => Self::dispatch_riscv64(data, renderer),
ArchKind::OpenRisc => Self::dispatch_openrisc(data, renderer),
ArchKind::PowerPc64 => Self::dispatch_powerpc64(data, renderer),
ArchKind::Sparc64 => Self::dispatch_sparc64(data, renderer),
ArchKind::Sisd => Self::dispatch_sisd(data, renderer),
ArchKind::Unknown => Self::dispatch_scalar_fallback(data, renderer),
}
}
#[cfg(target_arch = "x86_64")]
fn process_amd64(data: &[u8]) -> usize {
#[cfg(target_feature = "avx2")]
{
return Self::process_avx2(data);
}
#[cfg(target_feature = "sse2")]
{
return Self::process_sse2(data);
}
#[allow(unreachable_code)]
Self::process_scalar_fallback(data)
}
#[cfg(not(target_arch = "x86_64"))]
fn process_amd64(data: &[u8]) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(all(target_arch = "x86_64", target_feature = "avx2"))]
fn process_avx2(data: &[u8]) -> usize {
let mut processed = 0;
let chunks = data.chunks_exact(32);
let remainder = chunks.remainder();
for chunk in chunks {
let _sum: u32 = chunk.iter().map(|&b| b as u32).sum();
processed += 32;
}
processed += Self::process_scalar_fallback(remainder);
processed
}
#[cfg(all(target_arch = "x86_64", not(target_feature = "avx2")))]
fn process_avx2(data: &[u8]) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
fn process_sse2(data: &[u8]) -> usize {
let mut processed = 0;
let chunks = data.chunks_exact(16);
let remainder = chunks.remainder();
for chunk in chunks {
let _sum: u32 = chunk.iter().map(|&b| b as u32).sum();
processed += 16;
}
processed += Self::process_scalar_fallback(remainder);
processed
}
#[cfg(all(target_arch = "x86_64", not(target_feature = "sse2")))]
fn process_sse2(data: &[u8]) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "x86_64")]
fn dispatch_amd64(data: &[u8], renderer: &str) -> usize {
match renderer {
"glx_renderer" => {
Self::process_amd64(data)
}
"renderer_opencl" => {
Self::process_amd64(data)
}
_ => Self::process_scalar_fallback(data),
}
}
#[cfg(not(target_arch = "x86_64"))]
fn dispatch_amd64(data: &[u8], _renderer: &str) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "aarch64")]
fn process_aarch64(data: &[u8]) -> usize {
let mut processed = 0;
let chunks = data.chunks_exact(16);
let remainder = chunks.remainder();
for chunk in chunks {
let _sum: u32 = chunk.iter().map(|&b| b as u32).sum();
processed += 16;
}
processed += Self::process_scalar_fallback(remainder);
processed
}
#[cfg(not(target_arch = "aarch64"))]
fn process_aarch64(data: &[u8]) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "aarch64")]
fn dispatch_aarch64(data: &[u8], renderer: &str) -> usize {
match renderer {
"renderer_mali" | "mali" => Self::process_aarch64(data),
"renderer_panfrost" => Self::process_aarch64(data),
"renderer_metal" => Self::process_aarch64(data),
_ => Self::process_aarch64(data),
}
}
#[cfg(not(target_arch = "aarch64"))]
fn dispatch_aarch64(data: &[u8], _renderer: &str) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "riscv64")]
fn process_riscv64(data: &[u8]) -> usize {
let mut processed = 0;
for chunk in data.chunks(8) {
let _sum: u64 = chunk.iter().map(|&b| b as u64).sum();
processed += chunk.len();
}
processed
}
#[cfg(not(target_arch = "riscv64"))]
fn process_riscv64(data: &[u8]) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "riscv64")]
fn dispatch_riscv64(data: &[u8], _renderer: &str) -> usize {
Self::process_riscv64(data)
}
#[cfg(not(target_arch = "riscv64"))]
fn dispatch_riscv64(data: &[u8], _renderer: &str) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "or1k")]
fn process_openrisc(data: &[u8]) -> usize {
let mut processed = 0;
for chunk in data.chunks(4) {
let _sum: u32 = chunk.iter().map(|&b| b as u32).sum();
processed += chunk.len();
}
processed
}
#[cfg(not(target_arch = "or1k"))]
fn process_openrisc(data: &[u8]) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "or1k")]
fn dispatch_openrisc(data: &[u8], _renderer: &str) -> usize {
Self::process_openrisc(data)
}
#[cfg(not(target_arch = "or1k"))]
fn dispatch_openrisc(data: &[u8], _renderer: &str) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "powerpc64")]
fn process_powerpc64(data: &[u8]) -> usize {
let mut processed = 0;
let chunks = data.chunks_exact(16);
let remainder = chunks.remainder();
for chunk in chunks {
let _sum: u32 = chunk.iter().map(|&b| b as u32).sum();
processed += 16;
}
processed += Self::process_scalar_fallback(remainder);
processed
}
#[cfg(not(target_arch = "powerpc64"))]
fn process_powerpc64(data: &[u8]) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "powerpc64")]
fn dispatch_powerpc64(data: &[u8], _renderer: &str) -> usize {
Self::process_powerpc64(data)
}
#[cfg(not(target_arch = "powerpc64"))]
fn dispatch_powerpc64(data: &[u8], _renderer: &str) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "sparc64")]
fn process_sparc64(data: &[u8]) -> usize {
let mut processed = 0;
let chunks = data.chunks_exact(8);
let remainder = chunks.remainder();
for chunk in chunks {
let _sum: u32 = chunk.iter().map(|&b| b as u32).sum();
processed += 8;
}
processed += Self::process_scalar_fallback(remainder);
processed
}
#[cfg(not(target_arch = "sparc64"))]
fn process_sparc64(data: &[u8]) -> usize {
Self::process_scalar_fallback(data)
}
#[cfg(target_arch = "sparc64")]
fn dispatch_sparc64(data: &[u8], _renderer: &str) -> usize {
Self::process_sparc64(data)
}
#[cfg(not(target_arch = "sparc64"))]
fn dispatch_sparc64(data: &[u8], _renderer: &str) -> usize {
Self::process_scalar_fallback(data)
}
fn process_sisd(data: &[u8]) -> usize {
let mut processed = 0;
for chunk in data.chunks(4) {
let _sum: u32 = chunk.iter().map(|&b| b as u32).sum();
processed += chunk.len();
}
processed
}
fn dispatch_sisd(data: &[u8], _renderer: &str) -> usize {
Self::process_sisd(data)
}
fn process_scalar_fallback(data: &[u8]) -> usize {
let mut processed = 0;
for chunk in data.chunks(1024) {
let _sum: u32 = chunk.iter().map(|&b| b as u32).sum();
processed += chunk.len();
}
processed
}
fn dispatch_scalar_fallback(data: &[u8], _renderer: &str) -> usize {
Self::process_scalar_fallback(data)
}
}
#[derive(Debug, Clone)]
pub enum UniversalEndpoint {
UnixSocket(String),
TcpSocket { ip: String, port: u16 },
NamedPipe(String),
CharDevice(String),
}
impl UniversalEndpoint {
pub fn display(&self) -> String {
match self {
Self::UnixSocket(p) => format!("unix:{}", p),
Self::TcpSocket { ip, port } => format!("tcp:{}:{}", ip, port),
Self::NamedPipe(p) => format!("pipe:{}", p),
Self::CharDevice(p) => format!("dev:{}", p),
}
}
pub fn from_config(config: &WasmaConfig) -> Self {
if let Some(proto) = config.uri_handling.protocols.first() {
let sock_path = format!("/run/wasma/universal_{}.sock", proto.port);
if std::path::Path::new(&sock_path).exists() {
return Self::UnixSocket(sock_path);
}
return Self::TcpSocket {
ip: proto.ip.to_string(),
port: proto.port,
};
}
Self::UnixSocket("/run/wasma/universal.sock".to_string())
}
}
pub struct UniversalTransport {
fd: Option<RawFd>,
endpoint: UniversalEndpoint,
connected: bool,
bytes_sent: u64,
bytes_received: u64,
}
impl UniversalTransport {
pub fn new(endpoint: UniversalEndpoint) -> Self {
Self {
fd: None,
endpoint,
connected: false,
bytes_sent: 0,
bytes_received: 0,
}
}
pub fn connect(&mut self) -> Result<(), std::io::Error> {
let fd = match &self.endpoint {
UniversalEndpoint::UnixSocket(path) => {
use std::os::unix::io::AsRawFd;
use std::os::unix::net::UnixStream;
let s = UnixStream::connect(path)?;
let fd = s.as_raw_fd();
let _ = std::mem::ManuallyDrop::new(s);
fd
}
UniversalEndpoint::TcpSocket { ip, port } => {
use std::net::TcpStream;
use std::os::unix::io::AsRawFd;
let s = TcpStream::connect(format!("{}:{}", ip, port))?;
let fd = s.as_raw_fd();
let _ = std::mem::ManuallyDrop::new(s);
fd
}
UniversalEndpoint::NamedPipe(path) | UniversalEndpoint::CharDevice(path) => {
posix::posix_open(path, libc::O_RDWR)?
}
};
self.fd = Some(fd);
self.connected = true;
println!(
"🔌 UniversalTransport [{}]: Connected → {}",
CURRENT_ARCH.name(),
self.endpoint.display()
);
Ok(())
}
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
let fd = self.fd.ok_or_else(|| {
std::io::Error::new(std::io::ErrorKind::NotConnected, "Transport not connected")
})?;
let n = posix::posix_read(fd, buf)?;
self.bytes_received += n as u64;
Ok(n)
}
pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), std::io::Error> {
let fd = self.fd.ok_or_else(|| {
std::io::Error::new(std::io::ErrorKind::NotConnected, "Transport not connected")
})?;
posix::posix_read_exact(fd, buf)?;
self.bytes_received += buf.len() as u64;
Ok(())
}
pub fn write(&mut self, data: &[u8]) -> Result<usize, std::io::Error> {
let fd = self.fd.ok_or_else(|| {
std::io::Error::new(std::io::ErrorKind::NotConnected, "Transport not connected")
})?;
let mut written = 0;
while written < data.len() {
let n = unsafe {
libc::write(
fd,
data[written..].as_ptr() as *const libc::c_void,
data.len() - written,
)
};
match n {
-1 => return Err(std::io::Error::last_os_error()),
0 => {
return Err(std::io::Error::new(
std::io::ErrorKind::WriteZero,
"write() returned zero",
))
}
n => written += n as usize,
}
}
self.bytes_sent += written as u64;
Ok(written)
}
pub fn poll(&self, timeout_ms: i32) -> Result<bool, std::io::Error> {
match self.fd {
Some(fd) => posix::posix_poll_readable(fd, timeout_ms),
None => Err(std::io::Error::new(
std::io::ErrorKind::NotConnected,
"Transport not connected",
)),
}
}
pub fn is_connected(&self) -> bool {
self.connected
}
pub fn fd(&self) -> Option<RawFd> {
self.fd
}
pub fn bytes_sent(&self) -> u64 {
self.bytes_sent
}
pub fn bytes_received(&self) -> u64 {
self.bytes_received
}
}
impl Drop for UniversalTransport {
fn drop(&mut self) {
if let Some(fd) = self.fd.take() {
if fd > 2 {
let _ = posix::posix_close(fd);
}
}
}
}
#[derive(Debug, Clone)]
pub struct UniversalWindowRecord {
pub id: u64,
pub title: String,
pub app_id: String,
pub geometry: WindowGeometry,
pub state: WindowState,
pub kind: WindowType,
pub visible: bool,
pub focused: bool,
pub arch: ArchKind,
pub created_at: SystemTime,
}
impl UniversalWindowRecord {
pub fn new(id: u64, title: impl Into<String>, app_id: impl Into<String>) -> Self {
Self {
id,
title: title.into(),
app_id: app_id.into(),
geometry: WindowGeometry {
x: 0,
y: 0,
width: 800,
height: 600,
},
state: WindowState::Normal,
kind: WindowType::Normal,
visible: true,
focused: false,
arch: CURRENT_ARCH,
created_at: SystemTime::now(),
}
}
}
pub struct UniversalWindowOps {
registry: Arc<Mutex<HashMap<u64, UniversalWindowRecord>>>,
next_id: Arc<Mutex<u64>>,
focused: Arc<Mutex<Option<u64>>>,
transport: Arc<Mutex<UniversalTransport>>,
}
impl UniversalWindowOps {
pub fn new(transport: Arc<Mutex<UniversalTransport>>) -> Self {
Self {
registry: Arc::new(Mutex::new(HashMap::new())),
next_id: Arc::new(Mutex::new(1)),
focused: Arc::new(Mutex::new(None)),
transport,
}
}
fn alloc_id(&self) -> u64 {
let mut n = self.next_id.lock().unwrap();
let id = *n;
*n += 1;
id
}
pub fn create_window(
&self,
title: impl Into<String>,
app_id: impl Into<String>,
geometry: WindowGeometry,
kind: WindowType,
) -> Result<u64, String> {
let id = self.alloc_id();
let title = title.into();
let app_id = app_id.into();
let mut pkt: Vec<u8> = Vec::new();
pkt.extend_from_slice(b"WCrW");
pkt.extend_from_slice(&id.to_le_bytes());
pkt.extend_from_slice(&geometry.width.to_le_bytes());
pkt.extend_from_slice(&geometry.height.to_le_bytes());
pkt.extend_from_slice(&geometry.x.to_le_bytes());
pkt.extend_from_slice(&geometry.y.to_le_bytes());
let tb = title.as_bytes();
pkt.extend_from_slice(&(tb.len() as u16).to_le_bytes());
pkt.extend_from_slice(tb);
let _ = self.transport.lock().unwrap().write(&pkt);
let mut record = UniversalWindowRecord::new(id, &title, &app_id);
record.geometry = geometry;
record.kind = kind;
self.registry.lock().unwrap().insert(id, record);
println!(
"🪟 UniversalWindowOps [{}]: Window {} created — {}x{}",
CURRENT_ARCH.name(),
id,
geometry.width,
geometry.height
);
Ok(id)
}
pub fn destroy_window(&self, id: u64) -> Result<(), String> {
let children: Vec<u64> = Vec::new(); for cid in children {
let _ = self.destroy_window(cid);
}
let mut pkt = Vec::new();
pkt.extend_from_slice(b"WDeW");
pkt.extend_from_slice(&id.to_le_bytes());
let _ = self.transport.lock().unwrap().write(&pkt);
if self.registry.lock().unwrap().remove(&id).is_some() {
let mut focused = self.focused.lock().unwrap();
if *focused == Some(id) {
*focused = None;
}
println!("🗑️ UniversalWindowOps: Window {} destroyed", id);
Ok(())
} else {
Err(format!("Window {} not found", id))
}
}
pub fn set_geometry(&self, id: u64, geo: WindowGeometry) -> Result<(), String> {
let mut pkt = Vec::new();
pkt.extend_from_slice(b"WStG");
pkt.extend_from_slice(&id.to_le_bytes());
pkt.extend_from_slice(&geo.x.to_le_bytes());
pkt.extend_from_slice(&geo.y.to_le_bytes());
pkt.extend_from_slice(&geo.width.to_le_bytes());
pkt.extend_from_slice(&geo.height.to_le_bytes());
let _ = self.transport.lock().unwrap().write(&pkt);
let mut reg = self.registry.lock().unwrap();
match reg.get_mut(&id) {
Some(r) => {
r.geometry = geo;
Ok(())
}
None => Err(format!("Window {} not found", id)),
}
}
pub fn get_geometry(&self, id: u64) -> Result<WindowGeometry, String> {
let reg = self.registry.lock().unwrap();
reg.get(&id)
.map(|r| r.geometry)
.ok_or_else(|| format!("Window {} not found", id))
}
pub fn set_state(&self, id: u64, state: WindowState) -> Result<(), String> {
let state_byte: u8 = match state {
WindowState::Normal => 0,
WindowState::Minimized => 1,
WindowState::Maximized => 2,
WindowState::Fullscreen => 3,
WindowState::Hidden => 4,
};
let mut pkt = Vec::new();
pkt.extend_from_slice(b"WStS");
pkt.extend_from_slice(&id.to_le_bytes());
pkt.push(state_byte);
let _ = self.transport.lock().unwrap().write(&pkt);
let mut reg = self.registry.lock().unwrap();
match reg.get_mut(&id) {
Some(r) => {
r.state = state;
Ok(())
}
None => Err(format!("Window {} not found", id)),
}
}
pub fn get_state(&self, id: u64) -> Result<WindowState, String> {
let reg = self.registry.lock().unwrap();
reg.get(&id)
.map(|r| r.state.clone())
.ok_or_else(|| format!("Window {} not found", id))
}
pub fn set_focus(&self, id: u64) -> Result<(), String> {
{
let mut reg = self.registry.lock().unwrap();
for r in reg.values_mut() {
r.focused = false;
}
}
let mut pkt = Vec::new();
pkt.extend_from_slice(b"WStF");
pkt.extend_from_slice(&id.to_le_bytes());
let _ = self.transport.lock().unwrap().write(&pkt);
let mut reg = self.registry.lock().unwrap();
match reg.get_mut(&id) {
Some(r) => {
r.focused = true;
*self.focused.lock().unwrap() = Some(id);
Ok(())
}
None => Err(format!("Window {} not found", id)),
}
}
pub fn get_focused(&self) -> Option<u64> {
*self.focused.lock().unwrap()
}
pub fn set_visible(&self, id: u64, visible: bool) -> Result<(), String> {
let mut reg = self.registry.lock().unwrap();
match reg.get_mut(&id) {
Some(r) => {
r.visible = visible;
Ok(())
}
None => Err(format!("Window {} not found", id)),
}
}
pub fn set_title(&self, id: u64, title: impl Into<String>) -> Result<(), String> {
let title = title.into();
let mut reg = self.registry.lock().unwrap();
match reg.get_mut(&id) {
Some(r) => {
r.title = title;
Ok(())
}
None => Err(format!("Window {} not found", id)),
}
}
pub fn get_window(&self, id: u64) -> Option<UniversalWindowRecord> {
self.registry.lock().unwrap().get(&id).cloned()
}
pub fn list_windows(&self) -> Vec<UniversalWindowRecord> {
let reg = self.registry.lock().unwrap();
let mut v: Vec<_> = reg.values().cloned().collect();
v.sort_by_key(|w| w.id);
v
}
pub fn render_frame(&self, data: &[u8], renderer: &str) -> usize {
ArchBackend::dispatch_pixels(data, renderer)
}
}
pub struct UniversalClient {
config: Arc<WasmaConfig>,
transport: Arc<Mutex<UniversalTransport>>,
window_ops: UniversalWindowOps,
memory: SectionMemory,
active: bool,
}
impl UniversalClient {
pub fn new(config: WasmaConfig) -> Self {
let endpoint = UniversalEndpoint::from_config(&config);
let transport = Arc::new(Mutex::new(UniversalTransport::new(endpoint)));
let window_ops = UniversalWindowOps::new(transport.clone());
let level = config.resource_limits.scope_level;
Self {
transport,
window_ops,
memory: SectionMemory::new(level),
active: false,
config: Arc::new(config),
}
}
pub fn from_config(config: Arc<WasmaConfig>) -> Self {
let endpoint = UniversalEndpoint::from_config(&config);
let transport = Arc::new(Mutex::new(UniversalTransport::new(endpoint)));
let window_ops = UniversalWindowOps::new(transport.clone());
let level = config.resource_limits.scope_level;
Self {
transport,
window_ops,
memory: SectionMemory::new(level),
active: false,
config,
}
}
pub fn with_endpoint(mut self, endpoint: UniversalEndpoint) -> Self {
let transport = Arc::new(Mutex::new(UniversalTransport::new(endpoint)));
self.window_ops = UniversalWindowOps::new(transport.clone());
self.transport = transport;
self
}
pub fn create_window(
&self,
title: impl Into<String>,
app_id: impl Into<String>,
geometry: WindowGeometry,
kind: WindowType,
) -> Result<u64, String> {
self.window_ops.create_window(title, app_id, geometry, kind)
}
pub fn destroy_window(&self, id: u64) -> Result<(), String> {
self.window_ops.destroy_window(id)
}
pub fn set_geometry(&self, id: u64, geo: WindowGeometry) -> Result<(), String> {
self.window_ops.set_geometry(id, geo)
}
pub fn get_geometry(&self, id: u64) -> Result<WindowGeometry, String> {
self.window_ops.get_geometry(id)
}
pub fn set_state(&self, id: u64, state: WindowState) -> Result<(), String> {
self.window_ops.set_state(id, state)
}
pub fn get_state(&self, id: u64) -> Result<WindowState, String> {
self.window_ops.get_state(id)
}
pub fn set_focus(&self, id: u64) -> Result<(), String> {
self.window_ops.set_focus(id)
}
pub fn get_focused(&self) -> Option<u64> {
self.window_ops.get_focused()
}
pub fn set_visible(&self, id: u64, visible: bool) -> Result<(), String> {
self.window_ops.set_visible(id, visible)
}
pub fn set_title(&self, id: u64, title: impl Into<String>) -> Result<(), String> {
self.window_ops.set_title(id, title)
}
pub fn get_window(&self, id: u64) -> Option<UniversalWindowRecord> {
self.window_ops.get_window(id)
}
pub fn list_windows(&self) -> Vec<UniversalWindowRecord> {
self.window_ops.list_windows()
}
pub fn transport_stats(&self) -> (u64, u64) {
let t = self.transport.lock().unwrap();
(t.bytes_sent(), t.bytes_received())
}
pub fn arch(&self) -> ArchKind {
CURRENT_ARCH
}
}
impl UClientEngine for UniversalClient {
fn start_engine(&mut self) -> Result<(), Box<dyn std::error::Error>> {
let level = self.config.resource_limits.scope_level;
let renderer = self.config.resource_limits.renderer.clone();
println!("🔌 UniversalClient: Connecting transport...");
if let Err(e) = self.transport.lock().unwrap().connect() {
eprintln!(
"⚠️ Transport connection failed, running disconnected: {}",
e
);
}
self.active = true;
println!("🟢 WASMA UniversalClient: Engine Started");
println!("🖥️ Architecture: {}", CURRENT_ARCH.name());
println!("📐 Pointer width: {}-bit", CURRENT_ARCH.pointer_width());
println!("⚡ SIMD support: {}", CURRENT_ARCH.supports_simd());
println!("🚀 AVX support: {}", CURRENT_ARCH.supports_avx());
if CURRENT_ARCH.is_partial() {
println!("⚠️ PARTIAL SUPPORT MODE — scalar fallback active");
}
println!("🎨 Renderer: {}", renderer);
println!(
"📡 Mode: {}",
if level == 0 {
"NULL_EXCEPTION (raw stream)"
} else {
"Partitioned"
}
);
let fd = match self.transport.lock().unwrap().fd() {
Some(fd) => fd,
None => {
println!("📭 No transport — running in local processing mode");
self.active = false;
return Ok(());
}
};
if level == 0 {
let mut raw_buf = vec![0u8; 4096];
loop {
if !self.active {
break;
}
match posix::posix_poll_readable(fd, 100) {
Ok(false) => continue,
Ok(true) => {}
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
Err(e) => {
eprintln!("⚠️ Poll error: {}", e);
break;
}
}
match posix::posix_read(fd, &mut raw_buf) {
Ok(0) => {
println!("📭 Transport EOF — engine stopping");
break;
}
Ok(n) => {
self.dispatch_data(&raw_buf[..n]);
}
Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
std::thread::sleep(Duration::from_millis(1));
}
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
Err(e) => {
eprintln!("⚠️ Read error: {}", e);
break;
}
}
}
} else {
loop {
if !self.active {
break;
}
let mut all_ok = true;
for i in 0..self.memory.cell_count {
let cell = self.memory.get_cell_mut(i);
match posix::posix_read_exact(fd, cell) {
Ok(_) => {
let data = self.memory.get_cell(i).to_vec();
self.dispatch_data(&data);
}
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
println!("📭 Data stream complete");
all_ok = false;
break;
}
Err(e) => {
eprintln!("⚠️ Cell read error: {}", e);
all_ok = false;
break;
}
}
}
if !all_ok {
break;
}
}
}
self.active = false;
Ok(())
}
fn dispatch_data(&self, data: &[u8]) {
let renderer = &self.config.resource_limits.renderer;
let processed = self.window_ops.render_frame(data, renderer);
if processed >= 4096 {
println!(
"📦 UniversalClient [{}]: Dispatched {} bytes via {}",
CURRENT_ARCH.name(),
processed,
renderer
);
}
}
fn memory_usage(&self) -> (usize, usize, usize) {
(
self.memory.raw_storage.len(),
self.memory.cell_count,
self.memory.cell_size,
)
}
fn get_config(&self) -> &WasmaConfig {
&self.config
}
fn shutdown(&mut self) -> Result<(), Box<dyn std::error::Error>> {
self.active = false;
let ids: Vec<u64> = self
.window_ops
.list_windows()
.iter()
.map(|w| w.id)
.collect();
for id in ids {
let _ = self.window_ops.destroy_window(id);
}
println!(
"🛑 UniversalClient [{}]: Shutdown complete",
CURRENT_ARCH.name()
);
Ok(())
}
fn is_active(&self) -> bool {
self.active
}
}
pub struct UniversalClientBuilder {
config: Option<WasmaConfig>,
endpoint: Option<UniversalEndpoint>,
}
impl UniversalClientBuilder {
pub fn new() -> Self {
Self {
config: None,
endpoint: None,
}
}
pub fn with_config(mut self, config: WasmaConfig) -> Self {
self.config = Some(config);
self
}
pub fn with_endpoint(mut self, endpoint: UniversalEndpoint) -> Self {
self.endpoint = Some(endpoint);
self
}
pub fn build(self) -> Result<UniversalClient, String> {
let config = self.config.ok_or("Config required")?;
let mut client = UniversalClient::new(config);
if let Some(ep) = self.endpoint {
client = client.with_endpoint(ep);
}
Ok(client)
}
}
impl Default for UniversalClientBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parser::ConfigParser;
fn make_config() -> WasmaConfig {
let parser = ConfigParser::new(None);
let content = parser.generate_default_config();
parser.parse(&content).unwrap()
}
#[test]
fn test_arch_detection() {
let arch = CURRENT_ARCH;
println!("✅ Detected arch: {}", arch.name());
println!(
" SIMD: {} | AVX: {} | Partial: {} | Ptr: {}-bit",
arch.supports_simd(),
arch.supports_avx(),
arch.is_partial(),
arch.pointer_width()
);
assert!(arch.name().len() > 0);
}
#[test]
fn test_arch_backend_process() {
let data = vec![1u8; 4096];
let processed = ArchBackend::process_chunk(&data);
assert_eq!(processed, 4096);
println!(
"✅ ArchBackend::process_chunk [{}]: {} bytes",
CURRENT_ARCH.name(),
processed
);
}
#[test]
fn test_arch_backend_dispatch_pixels() {
let data = vec![0xAAu8; 1024];
let n = ArchBackend::dispatch_pixels(&data, "cpu_renderer");
assert_eq!(n, 1024);
println!(
"✅ ArchBackend::dispatch_pixels [{}]: {} bytes",
CURRENT_ARCH.name(),
n
);
}
#[test]
fn test_arch_backend_avx_chunks() {
let data = vec![1u8; 96]; let processed = ArchBackend::process_chunk(&data);
assert_eq!(processed, 96);
println!("✅ ArchBackend AVX chunk alignment working");
}
#[test]
fn test_universal_client_creation() {
let config = make_config();
let client = UniversalClient::new(config);
assert!(!client.is_active());
assert_eq!(client.arch(), CURRENT_ARCH);
let (sent, recv) = client.transport_stats();
assert_eq!(sent, 0);
assert_eq!(recv, 0);
println!("✅ UniversalClient creation working");
}
#[test]
fn test_window_lifecycle() {
let config = make_config();
let client = UniversalClient::new(config);
let geo = WindowGeometry {
x: 0,
y: 0,
width: 1280,
height: 720,
};
let id = client
.create_window("Test", "test.app", geo, WindowType::Normal)
.unwrap();
assert!(client.get_window(id).is_some());
let w = client.get_window(id).unwrap();
assert_eq!(w.geometry.width, 1280);
assert_eq!(w.arch, CURRENT_ARCH);
client.destroy_window(id).unwrap();
assert!(client.get_window(id).is_none());
println!("✅ Universal window lifecycle working");
}
#[test]
fn test_window_state_and_geometry() {
let config = make_config();
let client = UniversalClient::new(config);
let geo = WindowGeometry {
x: 10,
y: 20,
width: 800,
height: 600,
};
let id = client
.create_window("W", "a", geo, WindowType::Normal)
.unwrap();
client.set_state(id, WindowState::Maximized).unwrap();
assert_eq!(client.get_state(id).unwrap(), WindowState::Maximized);
let new_geo = WindowGeometry {
x: 0,
y: 0,
width: 1920,
height: 1080,
};
client.set_geometry(id, new_geo).unwrap();
assert_eq!(client.get_geometry(id).unwrap().width, 1920);
println!("✅ Universal window state and geometry working");
}
#[test]
fn test_focus_management() {
let config = make_config();
let client = UniversalClient::new(config);
let geo = WindowGeometry {
x: 0,
y: 0,
width: 800,
height: 600,
};
let id1 = client
.create_window("W1", "a1", geo, WindowType::Normal)
.unwrap();
let id2 = client
.create_window("W2", "a2", geo, WindowType::Normal)
.unwrap();
client.set_focus(id1).unwrap();
assert_eq!(client.get_focused(), Some(id1));
client.set_focus(id2).unwrap();
assert_eq!(client.get_focused(), Some(id2));
println!("✅ Universal focus management working");
}
#[test]
fn test_list_windows_sorted() {
let config = make_config();
let client = UniversalClient::new(config);
let geo = WindowGeometry {
x: 0,
y: 0,
width: 800,
height: 600,
};
for i in 0..5 {
client
.create_window(format!("W{}", i), "app", geo, WindowType::Normal)
.unwrap();
}
let windows = client.list_windows();
assert_eq!(windows.len(), 5);
for pair in windows.windows(2) {
assert!(pair[0].id < pair[1].id);
}
println!("✅ Window listing sorted correctly");
}
#[test]
fn test_uclient_engine_trait_object() {
let config = make_config();
let client: Box<dyn UClientEngine> = Box::new(UniversalClient::new(config));
assert!(!client.is_active());
let (total, cells, _) = client.memory_usage();
assert!(total > 0 && cells > 0);
println!("✅ UClientEngine trait object (UniversalClient) working");
}
#[test]
fn test_builder() {
let config = make_config();
let client = UniversalClientBuilder::new()
.with_config(config)
.with_endpoint(UniversalEndpoint::UnixSocket("/tmp/test.sock".to_string()))
.build()
.unwrap();
assert!(!client.is_active());
println!("✅ UniversalClientBuilder working");
}
#[test]
fn test_endpoint_display() {
assert_eq!(
UniversalEndpoint::UnixSocket("/run/wasma/u.sock".into()).display(),
"unix:/run/wasma/u.sock"
);
assert_eq!(
UniversalEndpoint::TcpSocket {
ip: "127.0.0.1".into(),
port: 9000
}
.display(),
"tcp:127.0.0.1:9000"
);
println!("✅ UniversalEndpoint display working");
}
#[test]
fn test_sisd_partial_support() {
let data = vec![0xFFu8; 512];
let mut processed = 0;
for chunk in data.chunks(4) {
let _s: u32 = chunk.iter().map(|&b| b as u32).sum();
processed += chunk.len();
}
assert_eq!(processed, 512);
println!("✅ SISD scalar path working (partial support mode)");
}
}