ruvector_sparsifier_wasm/
lib.rs1use wasm_bindgen::prelude::*;
7
8use ruvector_sparsifier::{
9 AdaptiveGeoSpar, SparseGraph, SparsifierConfig,
10 traits::Sparsifier,
11};
12
13#[wasm_bindgen]
19pub fn init() {
20 console_error_panic_hook::set_once();
21}
22
23#[wasm_bindgen]
25pub fn version() -> String {
26 ruvector_sparsifier::VERSION.to_string()
27}
28
29#[wasm_bindgen]
31pub fn default_config() -> String {
32 serde_json::to_string_pretty(&SparsifierConfig::default()).unwrap_or_default()
33}
34
35#[wasm_bindgen]
41pub struct WasmSparseGraph {
42 inner: SparseGraph,
43}
44
45#[wasm_bindgen]
46impl WasmSparseGraph {
47 #[wasm_bindgen(constructor)]
49 pub fn new(n: u32) -> Self {
50 Self {
51 inner: SparseGraph::with_capacity(n as usize),
52 }
53 }
54
55 #[wasm_bindgen(js_name = addEdge)]
57 pub fn add_edge(&mut self, u: u32, v: u32, weight: f64) -> Result<(), JsValue> {
58 self.inner
59 .insert_edge(u as usize, v as usize, weight)
60 .map_err(|e| JsValue::from_str(&e.to_string()))
61 }
62
63 #[wasm_bindgen(js_name = removeEdge)]
65 pub fn remove_edge(&mut self, u: u32, v: u32) -> Result<(), JsValue> {
66 self.inner
67 .delete_edge(u as usize, v as usize)
68 .map(|_| ())
69 .map_err(|e| JsValue::from_str(&e.to_string()))
70 }
71
72 pub fn degree(&self, u: u32) -> u32 {
74 self.inner.degree(u as usize) as u32
75 }
76
77 #[wasm_bindgen(js_name = numEdges)]
79 pub fn num_edges(&self) -> u32 {
80 self.inner.num_edges() as u32
81 }
82
83 #[wasm_bindgen(js_name = numVertices)]
85 pub fn num_vertices(&self) -> u32 {
86 self.inner.num_vertices() as u32
87 }
88
89 #[wasm_bindgen(js_name = toJson)]
91 pub fn to_json(&self) -> String {
92 let edges: Vec<(usize, usize, f64)> = self.inner.edges().collect();
93 serde_json::to_string(&edges).unwrap_or_default()
94 }
95}
96
97#[wasm_bindgen]
106pub struct WasmSparsifier {
107 inner: AdaptiveGeoSpar,
108}
109
110#[wasm_bindgen]
111impl WasmSparsifier {
112 #[wasm_bindgen(constructor)]
116 pub fn new(config_json: &str) -> Result<WasmSparsifier, JsValue> {
117 let config: SparsifierConfig = serde_json::from_str(config_json)
118 .map_err(|e| JsValue::from_str(&format!("invalid config: {e}")))?;
119 Ok(Self {
120 inner: AdaptiveGeoSpar::new(config),
121 })
122 }
123
124 #[wasm_bindgen(js_name = buildFromEdges)]
126 pub fn build_from_edges(
127 edges_json: &str,
128 config_json: &str,
129 ) -> Result<WasmSparsifier, JsValue> {
130 let edges: Vec<(usize, usize, f64)> = serde_json::from_str(edges_json)
131 .map_err(|e| JsValue::from_str(&format!("invalid edges: {e}")))?;
132 let config: SparsifierConfig = serde_json::from_str(config_json)
133 .map_err(|e| JsValue::from_str(&format!("invalid config: {e}")))?;
134
135 let graph = SparseGraph::from_edges(&edges);
136 let spar = AdaptiveGeoSpar::build(&graph, config)
137 .map_err(|e| JsValue::from_str(&e.to_string()))?;
138
139 Ok(Self { inner: spar })
140 }
141
142 #[wasm_bindgen(js_name = insertEdge)]
144 pub fn insert_edge(&mut self, u: u32, v: u32, weight: f64) -> Result<(), JsValue> {
145 self.inner
146 .insert_edge(u as usize, v as usize, weight)
147 .map_err(|e| JsValue::from_str(&e.to_string()))
148 }
149
150 #[wasm_bindgen(js_name = deleteEdge)]
152 pub fn delete_edge(&mut self, u: u32, v: u32) -> Result<(), JsValue> {
153 self.inner
154 .delete_edge(u as usize, v as usize)
155 .map_err(|e| JsValue::from_str(&e.to_string()))
156 }
157
158 #[wasm_bindgen(js_name = updateEmbedding)]
160 pub fn update_embedding(
161 &mut self,
162 node: u32,
163 old_neighbors_json: &str,
164 new_neighbors_json: &str,
165 ) -> Result<(), JsValue> {
166 let old: Vec<(usize, f64)> = serde_json::from_str(old_neighbors_json)
167 .map_err(|e| JsValue::from_str(&format!("invalid old_neighbors: {e}")))?;
168 let new: Vec<(usize, f64)> = serde_json::from_str(new_neighbors_json)
169 .map_err(|e| JsValue::from_str(&format!("invalid new_neighbors: {e}")))?;
170
171 self.inner
172 .update_embedding(node as usize, &old, &new)
173 .map_err(|e| JsValue::from_str(&e.to_string()))
174 }
175
176 pub fn audit(&self) -> String {
178 let result = self.inner.audit();
179 serde_json::to_string(&result).unwrap_or_default()
180 }
181
182 #[wasm_bindgen(js_name = sparsifierEdges)]
184 pub fn sparsifier_edges(&self) -> String {
185 let edges: Vec<(usize, usize, f64)> = self.inner.sparsifier().edges().collect();
186 serde_json::to_string(&edges).unwrap_or_default()
187 }
188
189 pub fn stats(&self) -> String {
191 serde_json::to_string(self.inner.stats()).unwrap_or_default()
192 }
193
194 #[wasm_bindgen(js_name = compressionRatio)]
196 pub fn compression_ratio(&self) -> f64 {
197 self.inner.compression_ratio()
198 }
199
200 #[wasm_bindgen(js_name = rebuildLocal)]
202 pub fn rebuild_local(&mut self, nodes_json: &str) -> Result<(), JsValue> {
203 let nodes: Vec<usize> = serde_json::from_str(nodes_json)
204 .map_err(|e| JsValue::from_str(&format!("invalid nodes: {e}")))?;
205 self.inner
206 .rebuild_local(&nodes)
207 .map_err(|e| JsValue::from_str(&e.to_string()))
208 }
209
210 #[wasm_bindgen(js_name = rebuildFull)]
212 pub fn rebuild_full(&mut self) -> Result<(), JsValue> {
213 self.inner
214 .rebuild_full()
215 .map_err(|e| JsValue::from_str(&e.to_string()))
216 }
217
218 #[wasm_bindgen(js_name = numVertices)]
220 pub fn num_vertices(&self) -> u32 {
221 self.inner.full_graph().num_vertices() as u32
222 }
223
224 #[wasm_bindgen(js_name = numEdges)]
226 pub fn num_edges(&self) -> u32 {
227 self.inner.full_graph().num_edges() as u32
228 }
229
230 #[wasm_bindgen(js_name = sparsifierNumEdges)]
232 pub fn sparsifier_num_edges(&self) -> u32 {
233 self.inner.sparsifier().num_edges() as u32
234 }
235}