use parking_lot::RwLock;
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct WasmConfig {
pub max_memory_mb: usize,
pub shared_memory: bool,
pub simd_enabled: bool,
pub threads_enabled: bool,
pub storage_backend: StorageBackend,
pub debug: bool,
}
impl Default for WasmConfig {
fn default() -> Self {
Self {
max_memory_mb: 256,
shared_memory: false,
simd_enabled: true,
threads_enabled: false,
storage_backend: StorageBackend::IndexedDb,
debug: false,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum StorageBackend {
IndexedDb,
LocalStorage,
Memory,
Opfs,
Custom(String),
}
#[derive(Debug, Clone, PartialEq)]
pub enum WasmPlatform {
Browser,
CloudflareWorkers,
DenoRuntime,
NodeJs,
FastlyCompute,
VercelEdge,
Unknown,
}
pub struct WasmRuntime {
config: WasmConfig,
platform: WasmPlatform,
memory_usage: Arc<RwLock<MemoryStats>>,
databases: Arc<RwLock<HashMap<String, WasmDatabase>>>,
}
#[derive(Debug, Clone, Default)]
pub struct MemoryStats {
pub heap_used: usize,
pub heap_total: usize,
pub external: usize,
pub array_buffers: usize,
}
pub struct WasmDatabase {
pub name: String,
pub tables: HashMap<String, WasmTable>,
pub vector_stores: HashMap<String, WasmVectorStore>,
pub branches: HashMap<String, WasmBranch>,
}
pub struct WasmTable {
pub name: String,
pub columns: Vec<WasmColumn>,
pub row_count: usize,
}
#[derive(Debug, Clone)]
pub struct WasmColumn {
pub name: String,
pub data_type: String,
pub nullable: bool,
pub primary_key: bool,
}
pub struct WasmVectorStore {
pub name: String,
pub dimensions: usize,
pub metric: String,
pub count: usize,
}
pub struct WasmBranch {
pub name: String,
pub parent: Option<String>,
pub created_at: u64,
}
impl WasmRuntime {
pub fn new(config: WasmConfig) -> Self {
let platform = Self::detect_platform();
Self {
config,
platform,
memory_usage: Arc::new(RwLock::new(MemoryStats::default())),
databases: Arc::new(RwLock::new(HashMap::new())),
}
}
fn detect_platform() -> WasmPlatform {
WasmPlatform::Browser
}
pub fn platform(&self) -> &WasmPlatform {
&self.platform
}
pub fn has_simd(&self) -> bool {
self.config.simd_enabled && self.check_simd_support()
}
fn check_simd_support(&self) -> bool {
true
}
pub fn has_threads(&self) -> bool {
self.config.threads_enabled && self.config.shared_memory
}
pub fn memory_stats(&self) -> MemoryStats {
self.memory_usage.read().clone()
}
pub fn update_memory_stats(&self, stats: MemoryStats) {
*self.memory_usage.write() = stats;
}
pub fn create_database(&self, name: &str) -> Result<(), WasmError> {
let mut dbs = self.databases.write();
if dbs.contains_key(name) {
return Err(WasmError::DatabaseExists(name.to_string()));
}
let db = WasmDatabase {
name: name.to_string(),
tables: HashMap::new(),
vector_stores: HashMap::new(),
branches: {
let mut branches = HashMap::new();
branches.insert("main".to_string(), WasmBranch {
name: "main".to_string(),
parent: None,
created_at: Self::current_timestamp(),
});
branches
},
};
dbs.insert(name.to_string(), db);
Ok(())
}
pub fn database(&self, name: &str) -> Option<String> {
let dbs = self.databases.read();
dbs.get(name).map(|db| db.name.clone())
}
pub fn list_databases(&self) -> Vec<String> {
let dbs = self.databases.read();
dbs.keys().cloned().collect()
}
fn current_timestamp() -> u64 {
0
}
pub fn execute_sql(&self, db_name: &str, sql: &str, _branch: &str) -> Result<QueryResult, WasmError> {
let dbs = self.databases.read();
if !dbs.contains_key(db_name) {
return Err(WasmError::DatabaseNotFound(db_name.to_string()));
}
let sql_lower = sql.to_lowercase();
if sql_lower.starts_with("select") {
Ok(QueryResult {
rows: Vec::new(),
columns: Vec::new(),
rows_affected: 0,
execution_time_ms: 0,
})
} else if sql_lower.starts_with("insert") {
Ok(QueryResult {
rows: Vec::new(),
columns: Vec::new(),
rows_affected: 1,
execution_time_ms: 0,
})
} else if sql_lower.starts_with("create table") {
Ok(QueryResult {
rows: Vec::new(),
columns: Vec::new(),
rows_affected: 0,
execution_time_ms: 0,
})
} else {
Err(WasmError::UnsupportedOperation(sql.to_string()))
}
}
pub fn vector_search(
&self,
_db_name: &str,
_store_name: &str,
_vector: &[f32],
_top_k: usize,
) -> Result<Vec<VectorSearchResult>, WasmError> {
Ok(Vec::new())
}
pub fn store_vector(
&self,
_db_name: &str,
_store_name: &str,
_id: &str,
_vector: &[f32],
_metadata: Option<&str>,
) -> Result<(), WasmError> {
Ok(())
}
pub fn storage_info(&self) -> StorageInfo {
StorageInfo {
backend: format!("{:?}", self.config.storage_backend),
available: true,
quota_bytes: match self.config.storage_backend {
StorageBackend::LocalStorage => Some(5 * 1024 * 1024), StorageBackend::IndexedDb => None, StorageBackend::Opfs => None,
StorageBackend::Memory => Some(self.config.max_memory_mb * 1024 * 1024),
StorageBackend::Custom(_) => None,
},
used_bytes: 0,
}
}
pub fn persist(&self) -> Result<(), WasmError> {
match &self.config.storage_backend {
StorageBackend::Memory => Ok(()), StorageBackend::LocalStorage => {
Ok(())
}
StorageBackend::IndexedDb => {
Ok(())
}
StorageBackend::Opfs => {
Ok(())
}
StorageBackend::Custom(handler) => {
log::debug!("Custom persist handler: {}", handler);
Ok(())
}
}
}
pub fn hydrate(&self) -> Result<(), WasmError> {
match &self.config.storage_backend {
StorageBackend::Memory => Ok(()), _ => {
Ok(())
}
}
}
}
#[derive(Debug, Clone)]
pub struct QueryResult {
pub rows: Vec<Vec<serde_json::Value>>,
pub columns: Vec<String>,
pub rows_affected: usize,
pub execution_time_ms: u64,
}
#[derive(Debug, Clone)]
pub struct VectorSearchResult {
pub id: String,
pub score: f32,
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone)]
pub struct StorageInfo {
pub backend: String,
pub available: bool,
pub quota_bytes: Option<usize>,
pub used_bytes: usize,
}
#[derive(Debug, thiserror::Error)]
pub enum WasmError {
#[error("Database not found: {0}")]
DatabaseNotFound(String),
#[error("Database already exists: {0}")]
DatabaseExists(String),
#[error("Table not found: {0}")]
TableNotFound(String),
#[error("Vector store not found: {0}")]
VectorStoreNotFound(String),
#[error("Branch not found: {0}")]
BranchNotFound(String),
#[error("Storage error: {0}")]
Storage(String),
#[error("Memory limit exceeded")]
MemoryExceeded,
#[error("Unsupported operation: {0}")]
UnsupportedOperation(String),
#[error("JavaScript interop error: {0}")]
JsError(String),
#[error("Serialization error: {0}")]
Serialization(String),
}
#[derive(Debug, Clone)]
pub struct WasmFeatures {
pub full_sql: bool,
pub vector_search: bool,
pub branching: bool,
pub agent_memory: bool,
pub nl_query: bool,
pub rag: bool,
}
impl Default for WasmFeatures {
fn default() -> Self {
Self {
full_sql: true,
vector_search: true,
branching: true,
agent_memory: true,
nl_query: false, rag: false, }
}
}
pub fn available_features() -> WasmFeatures {
WasmFeatures::default()
}