ruvector_router_wasm/
lib.rs1use ruvector_router_core::{
4 DistanceMetric as CoreDistanceMetric, SearchQuery as CoreSearchQuery, VectorDB as CoreVectorDB,
5 VectorEntry as CoreVectorEntry,
6};
7use std::collections::HashMap;
8use wasm_bindgen::prelude::*;
9
10#[wasm_bindgen]
11extern "C" {
12 #[wasm_bindgen(js_namespace = console)]
13 fn log(s: &str);
14}
15
16macro_rules! console_log {
17 ($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
18}
19
20#[wasm_bindgen]
21#[derive(Clone, Copy)]
22pub enum DistanceMetric {
23 Euclidean,
24 Cosine,
25 DotProduct,
26 Manhattan,
27}
28
29impl From<DistanceMetric> for CoreDistanceMetric {
30 fn from(metric: DistanceMetric) -> Self {
31 match metric {
32 DistanceMetric::Euclidean => CoreDistanceMetric::Euclidean,
33 DistanceMetric::Cosine => CoreDistanceMetric::Cosine,
34 DistanceMetric::DotProduct => CoreDistanceMetric::DotProduct,
35 DistanceMetric::Manhattan => CoreDistanceMetric::Manhattan,
36 }
37 }
38}
39
40#[wasm_bindgen]
41pub struct VectorDB {
42 db: CoreVectorDB,
43}
44
45#[wasm_bindgen]
46impl VectorDB {
47 #[wasm_bindgen(constructor)]
48 pub fn new(dimensions: usize, storage_path: Option<String>) -> Result<VectorDB, JsValue> {
49 console_log!("Initializing VectorDB with {} dimensions", dimensions);
50
51 let mut builder = CoreVectorDB::builder().dimensions(dimensions);
52
53 if let Some(path) = storage_path {
54 builder = builder.storage_path(path);
55 }
56
57 let db = builder
58 .build()
59 .map_err(|e| JsValue::from_str(&format!("Failed to create database: {}", e)))?;
60
61 Ok(VectorDB { db })
62 }
63
64 #[wasm_bindgen]
65 pub fn insert(&mut self, id: String, vector: Vec<f32>) -> Result<String, JsValue> {
66 let entry = CoreVectorEntry {
67 id: id.clone(),
68 vector,
69 metadata: HashMap::new(),
70 timestamp: 0, };
72
73 self.db
74 .insert(entry)
75 .map_err(|e| JsValue::from_str(&format!("Insert failed: {}", e)))
76 }
77
78 #[wasm_bindgen]
79 pub fn search(&self, vector: Vec<f32>, k: usize) -> Result<JsValue, JsValue> {
80 let query = CoreSearchQuery {
81 vector,
82 k,
83 filters: None,
84 threshold: None,
85 ef_search: None,
86 };
87
88 let results = self
89 .db
90 .search(query)
91 .map_err(|e| JsValue::from_str(&format!("Search failed: {}", e)))?;
92
93 let js_results: Vec<JsValue> = results
95 .into_iter()
96 .map(|r| {
97 let obj = js_sys::Object::new();
98 js_sys::Reflect::set(&obj, &"id".into(), &r.id.into()).ok();
99 js_sys::Reflect::set(&obj, &"score".into(), &r.score.into()).ok();
100 obj.into()
101 })
102 .collect();
103
104 Ok(js_sys::Array::from_iter(js_results).into())
105 }
106
107 #[wasm_bindgen]
108 pub fn delete(&mut self, id: String) -> Result<bool, JsValue> {
109 self.db
110 .delete(&id)
111 .map_err(|e| JsValue::from_str(&format!("Delete failed: {}", e)))
112 }
113
114 #[wasm_bindgen]
115 pub fn count(&self) -> Result<usize, JsValue> {
116 self.db
117 .count()
118 .map_err(|e| JsValue::from_str(&format!("Count failed: {}", e)))
119 }
120}
121
122#[wasm_bindgen(start)]
123pub fn start() {
124 console_log!("Ruvector WASM module loaded");
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use wasm_bindgen_test::*;
131
132 #[wasm_bindgen_test]
133 fn test_vector_db_creation() {
134 let db = VectorDB::new(3, None);
135 assert!(db.is_ok());
136 }
137}