ruvector_robotics/bridge/
search.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7pub enum AlertSeverity {
8 Critical,
10 Warning,
12 Info,
14}
15
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18pub struct Neighbor {
19 pub id: u64,
21 pub distance: f32,
23 pub position: [f32; 3],
25}
26
27#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
29pub struct SearchResult {
30 pub query_id: u64,
32 pub neighbors: Vec<Neighbor>,
34 pub latency_us: u64,
36}
37
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
40pub struct ObstacleAlert {
41 pub obstacle_id: u64,
43 pub distance: f32,
45 pub direction: [f32; 3],
47 pub severity: AlertSeverity,
49}
50
51#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn test_neighbor_serde_roundtrip() {
61 let n = Neighbor {
62 id: 42,
63 distance: 1.5,
64 position: [1.0, 2.0, 3.0],
65 };
66 let json = serde_json::to_string(&n).unwrap();
67 let restored: Neighbor = serde_json::from_str(&json).unwrap();
68 assert_eq!(n, restored);
69 }
70
71 #[test]
72 fn test_search_result_serde_roundtrip() {
73 let sr = SearchResult {
74 query_id: 7,
75 neighbors: vec![
76 Neighbor {
77 id: 1,
78 distance: 0.5,
79 position: [0.0, 0.0, 0.0],
80 },
81 Neighbor {
82 id: 2,
83 distance: 1.2,
84 position: [1.0, 1.0, 1.0],
85 },
86 ],
87 latency_us: 150,
88 };
89 let json = serde_json::to_string(&sr).unwrap();
90 let restored: SearchResult = serde_json::from_str(&json).unwrap();
91 assert_eq!(sr, restored);
92 }
93
94 #[test]
95 fn test_obstacle_alert_serde_roundtrip() {
96 let alert = ObstacleAlert {
97 obstacle_id: 99,
98 distance: 0.3,
99 direction: [1.0, 0.0, 0.0],
100 severity: AlertSeverity::Critical,
101 };
102 let json = serde_json::to_string(&alert).unwrap();
103 let restored: ObstacleAlert = serde_json::from_str(&json).unwrap();
104 assert_eq!(alert, restored);
105 }
106
107 #[test]
108 fn test_alert_severity_all_variants() {
109 for severity in [
110 AlertSeverity::Critical,
111 AlertSeverity::Warning,
112 AlertSeverity::Info,
113 ] {
114 let json = serde_json::to_string(&severity).unwrap();
115 let restored: AlertSeverity = serde_json::from_str(&json).unwrap();
116 assert_eq!(severity, restored);
117 }
118 }
119
120 #[test]
121 fn test_search_result_empty_neighbors() {
122 let sr = SearchResult {
123 query_id: 0,
124 neighbors: vec![],
125 latency_us: 0,
126 };
127 let json = serde_json::to_string(&sr).unwrap();
128 let restored: SearchResult = serde_json::from_str(&json).unwrap();
129 assert!(restored.neighbors.is_empty());
130 }
131
132 #[test]
133 fn test_neighbor_debug_format() {
134 let n = Neighbor {
135 id: 1,
136 distance: 0.0,
137 position: [0.0, 0.0, 0.0],
138 };
139 let dbg = format!("{:?}", n);
140 assert!(dbg.contains("Neighbor"));
141 }
142
143 #[test]
144 fn test_obstacle_alert_direction_preserved() {
145 let alert = ObstacleAlert {
146 obstacle_id: 1,
147 distance: 5.0,
148 direction: [0.577, 0.577, 0.577],
149 severity: AlertSeverity::Warning,
150 };
151 let json = serde_json::to_string(&alert).unwrap();
152 let restored: ObstacleAlert = serde_json::from_str(&json).unwrap();
153 for i in 0..3 {
154 assert!((alert.direction[i] - restored.direction[i]).abs() < 1e-6);
155 }
156 }
157
158 #[test]
159 fn test_search_result_json_structure() {
160 let sr = SearchResult {
161 query_id: 10,
162 neighbors: vec![Neighbor {
163 id: 5,
164 distance: 2.5,
165 position: [3.0, 4.0, 5.0],
166 }],
167 latency_us: 42,
168 };
169 let json = serde_json::to_string_pretty(&sr).unwrap();
170 assert!(json.contains("query_id"));
171 assert!(json.contains("neighbors"));
172 assert!(json.contains("latency_us"));
173 }
174}