ruvllm_wasm/utils.rs
1//! Utility functions for WASM environment
2//!
3//! Provides helper functions for panic handling, logging, and
4//! JavaScript interop utilities.
5
6use wasm_bindgen::prelude::*;
7
8/// Set panic hook for better error messages in the browser console.
9///
10/// This function should be called once at initialization to enable
11/// better panic messages in the browser's developer console.
12///
13/// # Example
14///
15/// ```rust,ignore
16/// use ruvllm_wasm::utils::set_panic_hook;
17///
18/// // Call at app startup
19/// set_panic_hook();
20/// ```
21pub fn set_panic_hook() {
22 // When the `console_error_panic_hook` feature is enabled, we can call the
23 // `set_panic_hook` function at least once during initialization, and then
24 // we will get better error messages if our code ever panics.
25 //
26 // For more details see
27 // https://github.com/rustwasm/console_error_panic_hook#readme
28 #[cfg(feature = "console_error_panic_hook")]
29 console_error_panic_hook::set_once();
30}
31
32/// Log a message to the browser console.
33///
34/// # Arguments
35///
36/// * `message` - The message to log
37#[wasm_bindgen]
38pub fn log(message: &str) {
39 web_sys::console::log_1(&message.into());
40}
41
42/// Log a warning to the browser console.
43///
44/// # Arguments
45///
46/// * `message` - The warning message
47#[wasm_bindgen]
48pub fn warn(message: &str) {
49 web_sys::console::warn_1(&message.into());
50}
51
52/// Log an error to the browser console.
53///
54/// # Arguments
55///
56/// * `message` - The error message
57#[wasm_bindgen]
58pub fn error(message: &str) {
59 web_sys::console::error_1(&message.into());
60}
61
62/// Get current timestamp in milliseconds using Performance API.
63///
64/// Returns high-resolution timestamp for performance measurements.
65#[wasm_bindgen]
66pub fn now_ms() -> f64 {
67 web_sys::window()
68 .and_then(|w| w.performance())
69 .map(|p| p.now())
70 .unwrap_or(0.0)
71}
72
73/// Simple timer for measuring elapsed time in WASM.
74#[wasm_bindgen]
75pub struct Timer {
76 start: f64,
77 label: String,
78}
79
80#[wasm_bindgen]
81impl Timer {
82 /// Create a new timer with the given label.
83 ///
84 /// # Arguments
85 ///
86 /// * `label` - A descriptive label for the timer
87 #[wasm_bindgen(constructor)]
88 pub fn new(label: &str) -> Timer {
89 Timer {
90 start: now_ms(),
91 label: label.to_string(),
92 }
93 }
94
95 /// Get elapsed time in milliseconds.
96 #[wasm_bindgen]
97 pub fn elapsed_ms(&self) -> f64 {
98 now_ms() - self.start
99 }
100
101 /// Log elapsed time to console and return the duration.
102 #[wasm_bindgen]
103 pub fn stop(&self) -> f64 {
104 let elapsed = self.elapsed_ms();
105 log(&format!("{}: {:.2}ms", self.label, elapsed));
106 elapsed
107 }
108
109 /// Reset the timer.
110 #[wasm_bindgen]
111 pub fn reset(&mut self) {
112 self.start = now_ms();
113 }
114}
115
116/// Convert a Rust Result to a JavaScript-friendly format.
117///
118/// On success, returns the value. On error, throws a JavaScript exception.
119pub fn result_to_js<T, E: std::fmt::Display>(result: Result<T, E>) -> Result<T, JsValue> {
120 result.map_err(|e| JsValue::from_str(&e.to_string()))
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 // set_panic_hook requires console_error_panic_hook which only works on wasm32
128 #[cfg(target_arch = "wasm32")]
129 #[test]
130 fn test_set_panic_hook() {
131 // Should not panic
132 set_panic_hook();
133 }
134
135 // Non-wasm32 version just verifies the function exists
136 #[cfg(not(target_arch = "wasm32"))]
137 #[test]
138 fn test_set_panic_hook_noop() {
139 // On non-wasm32, this is a no-op
140 set_panic_hook();
141 }
142}