1use serde::{Deserialize, Serialize};
2use web_time::Instant;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6#[cfg_attr(feature = "wasm-bindings", derive(tsify::Tsify))]
7#[cfg_attr(feature = "uniffi-bindings", derive(uniffi::Record))]
8#[serde(rename_all = "camelCase")]
9pub struct PhaseMetric {
10 pub duration_ms: f64,
11}
12
13pub fn phase_metric(start: Instant) -> PhaseMetric {
15 PhaseMetric { duration_ms: start.elapsed().as_secs_f64() * 1000.0 }
16}
17
18#[cfg(test)]
19mod tests {
20 use super::*;
21 use std::thread;
22 use std::time::Duration;
23
24 #[test]
25 fn phase_metric_captures_nonzero_elapsed_time() {
26 let start = Instant::now();
27 thread::sleep(Duration::from_millis(10));
28 let metric = phase_metric(start);
29 assert!(metric.duration_ms >= 5.0, "Expected at least 5ms, got {}ms", metric.duration_ms);
30 }
31
32 #[test]
33 fn phase_metric_serializes_camel_case_field_name() {
34 let metric = PhaseMetric { duration_ms: 42.5 };
35 let json = serde_json::to_string(&metric).unwrap();
36 assert!(json.contains("durationMs"));
37 assert!(json.contains("42.5"));
38 }
39
40 #[test]
41 fn phase_metric_serde_round_trips() {
42 let original = PhaseMetric { duration_ms: 123.456 };
43 let json = serde_json::to_string(&original).unwrap();
44 let deserialized: PhaseMetric = serde_json::from_str(&json).unwrap();
45 assert!((deserialized.duration_ms - 123.456).abs() < f64::EPSILON);
46 }
47}