1use spatio::{Point, SetOptions, Spatio};
2use std::time::Duration;
3
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("Spatio - Comprehensive Demo");
6 println!("===========================");
7
8 let db = Spatio::memory()?;
10 println!("Created in-memory database");
11
12 println!("\nBasic Key-Value Operations");
14
15 db.insert("app:name", b"Spatio Demo App", None)?;
17 db.insert("app:version", b"1.0.0", None)?;
18 db.insert("app:author", b"Spatio Team", None)?;
19
20 let app_name = db.get("app:name")?.unwrap();
22 println!(" App: {}", String::from_utf8_lossy(&app_name));
23
24 println!("\nTTL (Time-to-Live) Operations");
26
27 let session_opts = SetOptions::with_ttl(Duration::from_secs(10));
29 db.insert("session:user123", b"active", Some(session_opts))?;
30 println!(" Created session with 10-second TTL");
31
32 let cache_opts = SetOptions::with_ttl(Duration::from_secs(300)); db.insert("cache:weather", b"sunny, 22C", Some(cache_opts.clone()))?;
35 db.insert(
36 "cache:news",
37 b"Latest tech news...",
38 Some(cache_opts.clone()),
39 )?;
40 println!(" Cached data with 5-minute TTL");
41
42 println!("\nAtomic Batch Operations");
44
45 db.atomic(|batch| {
47 batch.insert("user:123:name", b"Alice Johnson", None)?;
48 batch.insert("user:123:email", b"alice@example.com", None)?;
49 batch.insert("user:123:role", b"admin", None)?;
50 batch.insert("user:123:created", b"2024-01-01", None)?;
51 Ok(())
52 })?;
53 println!(" Created user profile atomically");
54
55 db.atomic(|batch| {
57 batch.insert("sensor:temp", b"23.5", None)?;
58 batch.insert("sensor:humidity", b"68", None)?;
59 batch.insert("sensor:pressure", b"1013.2", None)?;
60 batch.insert("sensor:timestamp", b"1640995200", None)?;
61 Ok(())
62 })?;
63 println!(" Recorded sensor readings atomically");
64
65 println!("\nSpatial Point Operations");
67
68 let cities = vec![
70 ("New York", Point::new(40.7128, -74.0060)),
71 ("London", Point::new(51.5074, -0.1278)),
72 ("Tokyo", Point::new(35.6762, 139.6503)),
73 ("Paris", Point::new(48.8566, 2.3522)),
74 ("Sydney", Point::new(-33.8688, 151.2093)),
75 ("São Paulo", Point::new(-23.5505, -46.6333)),
76 ("Mumbai", Point::new(19.0760, 72.8777)),
77 ("Cairo", Point::new(30.0444, 31.2357)),
78 ];
79
80 for (name, point) in &cities {
82 db.insert_point("cities", point, name.as_bytes(), None)?;
83 }
84 println!(
85 " Added {} cities with automatic spatial indexing",
86 cities.len()
87 );
88
89 let london = Point::new(51.5074, -0.1278);
91 let paris = Point::new(48.8566, 2.3522);
92 let distance_km = london.distance_to(&paris) / 1000.0;
93 println!(" London ↔ Paris: {:.0} km", distance_km);
94
95 let nearby_london = db.find_nearby("cities", &london, 1_000_000.0, 5)?;
97 println!(" Cities within 1000km of London:");
98 for (point, data) in &nearby_london {
99 let city_name = String::from_utf8_lossy(data);
100 let distance = london.distance_to(point) / 1000.0;
101 println!(" - {} ({:.0} km)", city_name, distance);
102 }
103
104 println!("\nPoints of Interest");
106
107 let london_restaurants = vec![
108 ("The Shard Restaurant", Point::new(51.5045, -0.0865)),
109 ("Sketch", Point::new(51.5115, -0.1442)),
110 ("Dishoom", Point::new(51.5145, -0.1270)),
111 ("Borough Market", Point::new(51.5055, -0.0931)),
112 ];
113
114 for (name, point) in &london_restaurants {
115 db.insert_point("london_food", point, name.as_bytes(), None)?;
116 }
117 println!(" Added {} London restaurants", london_restaurants.len());
118
119 let covent_garden = Point::new(51.5118, -0.1226);
121 let nearby_food = db.find_nearby("london_food", &covent_garden, 2000.0, 10)?;
122 println!(" Restaurants within 2km of Covent Garden:");
123 for (point, data) in &nearby_food {
124 let restaurant_name = String::from_utf8_lossy(data);
125 let distance = covent_garden.distance_to(point);
126 println!(" - {} ({:.0}m away)", restaurant_name, distance);
127 }
128
129 println!("\nTrajectory Tracking");
131
132 let delivery_route = vec![
134 (Point::new(51.5074, -0.1278), 1640995200), (Point::new(51.5055, -0.0931), 1640995260), (Point::new(51.5045, -0.0865), 1640995320), (Point::new(51.4994, -0.1245), 1640995380), (Point::new(51.5014, -0.1419), 1640995440), (Point::new(51.5118, -0.1226), 1640995500), ];
141
142 db.insert_trajectory("delivery:truck001", &delivery_route, None)?;
143 println!(
144 " Stored delivery truck trajectory ({} waypoints)",
145 delivery_route.len()
146 );
147
148 let taxi_route = vec![
150 (Point::new(51.4700, -0.4543), 1640995200), (Point::new(51.4900, -0.1743), 1640995800), (Point::new(51.5074, -0.1278), 1640996100), ];
154
155 db.insert_trajectory("taxi:cab042", &taxi_route, None)?;
156 println!(" Stored taxi trajectory ({} waypoints)", taxi_route.len());
157
158 let truck_morning = db.query_trajectory("delivery:truck001", 1640995200, 1640995380)?;
160 println!(
161 " Truck trajectory (first 3 minutes): {} points",
162 truck_morning.len()
163 );
164
165 let taxi_full = db.query_trajectory("taxi:cab042", 1640995200, 1640996200)?;
166 println!(" Full taxi journey: {} points", taxi_full.len());
167
168 println!("\nIoT Sensor Network");
170
171 let sensors = vec![
173 ("sensor001", Point::new(51.5074, -0.1278), "22.5°C"), ("sensor002", Point::new(51.5200, -0.1000), "21.8°C"), ("sensor003", Point::new(51.4900, -0.1500), "23.1°C"), ("sensor004", Point::new(51.5100, -0.0800), "22.9°C"), ("sensor005", Point::new(51.5000, -0.1800), "21.5°C"), ];
179
180 for (sensor_id, point, reading) in &sensors {
181 db.insert_point(
182 "sensors",
183 point,
184 format!("{}:{}", sensor_id, reading).as_bytes(),
185 None,
186 )?;
187 }
188 println!(" Deployed {} temperature sensors", sensors.len());
189
190 let monitoring_center = Point::new(51.5100, -0.1200);
192 let nearby_sensors = db.find_nearby("sensors", &monitoring_center, 5000.0, 10)?;
193 println!(" Sensors within 5km of monitoring center:");
194 for (point, data) in &nearby_sensors {
195 let sensor_info = String::from_utf8_lossy(data);
196 let distance = monitoring_center.distance_to(point);
197 println!(" - {} ({:.0}m away)", sensor_info, distance);
198 }
199
200 println!("\nReal-time Updates");
202
203 db.insert_point(
205 "sensors",
206 &Point::new(51.5074, -0.1278),
207 b"sensor001:24.2C",
208 None,
209 )?;
210 println!(" Updated sensor001 reading");
211
212 let bus_route = vec![
214 (Point::new(51.5155, -0.0922), 1640995600), (Point::new(51.5074, -0.1278), 1640995660), ];
217 db.insert_trajectory("bus:route25", &bus_route, None)?;
218 println!(" Added new bus to tracking system");
219
220 println!("\nDatabase Statistics");
222
223 let stats = db.stats()?;
224 println!(" Total keys: {}", stats.key_count);
225 println!(" Operations performed: {}", stats.operations_count);
226
227 let mut namespace_counts = std::collections::HashMap::new();
229 namespace_counts.insert("cities", cities.len());
231 namespace_counts.insert("restaurants", london_restaurants.len());
232 namespace_counts.insert("sensors", sensors.len());
233 namespace_counts.insert("trajectories", 3); println!(" Data distribution:");
236 for (namespace, count) in &namespace_counts {
237 println!(" - {}: {} items", namespace, count);
238 }
239
240 println!("\nCleanup & TTL Demo");
242
243 if let Some(_session) = db.get("session:user123")? {
245 println!(" Session still active");
246 } else {
247 println!(" Session expired as expected");
248 }
249
250 db.delete("app:version")?;
252 println!(" Removed app version info");
253
254 let final_stats = db.stats()?;
256 println!(" Final key count: {}", final_stats.key_count);
257
258 println!("\nComprehensive demo completed successfully!");
259 println!("\nFeatures demonstrated:");
260 println!("- Key-value storage with TTL");
261 println!("- Atomic batch operations");
262 println!("- Automatic spatial indexing");
263 println!("- Geographic point queries");
264 println!("- Distance calculations");
265 println!("- Trajectory tracking");
266 println!("- Multi-namespace organization");
267 println!("- Real-time updates");
268 println!("- Data expiration");
269
270 Ok(())
271}