1use spatio::{Point, SetOptions, Spatio, TemporalPoint};
2use std::time::{Duration, UNIX_EPOCH};
3
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("=== Spatio - Comprehensive Demo ===\n");
6
7 let mut db = Spatio::memory()?;
8 println!("✓ Created in-memory database\n");
9
10 println!("1. Basic Key-Value Operations");
12 println!("------------------------------");
13
14 db.insert("app:name", b"Spatio Demo", None)?;
15 db.insert("app:version", b"1.0.0", None)?;
16 db.insert("user:alice", b"Alice Johnson", None)?;
17
18 let app_name = db.get("app:name")?.unwrap();
19 println!(" Stored: {}", String::from_utf8_lossy(&app_name));
20
21 let count = db.stats().key_count;
22 println!(" Total keys: {}\n", count);
23
24 println!("2. TTL (Time-to-Live)");
26 println!("---------------------");
27
28 let session_opts = SetOptions::with_ttl(Duration::from_secs(10));
29 db.insert("session:temp", b"expires_soon", Some(session_opts))?;
30 println!(" Created session with 10-second TTL");
31
32 let cache_opts = SetOptions::with_ttl(Duration::from_secs(300));
33 db.insert("cache:weather", b"sunny, 22C", Some(cache_opts))?;
34 println!(" Cached data with 5-minute TTL\n");
35
36 println!("3. Atomic Batch Operations");
38 println!("--------------------------");
39
40 db.atomic(|batch| {
41 batch.insert("sensor:temp", b"23.5", None)?;
42 batch.insert("sensor:humidity", b"68", None)?;
43 batch.insert("sensor:pressure", b"1013", None)?;
44 Ok(())
45 })?;
46 println!(" Atomically inserted 3 sensor readings\n");
47
48 println!("4. Spatial Point Storage");
50 println!("------------------------");
51
52 let cities = vec![
53 ("New York", Point::new(-74.0060, 40.7128)),
54 ("London", Point::new(-0.1278, 51.5074)),
55 ("Paris", Point::new(2.3522, 48.8566)),
56 ("Tokyo", Point::new(139.6503, 35.6762)),
57 ("Sydney", Point::new(151.2093, -33.8688)),
58 ];
59
60 for (name, point) in &cities {
61 db.insert_point("cities", point, name.as_bytes(), None)?;
62 }
63 println!(" Stored {} cities with spatial indexing", cities.len());
64
65 let london = Point::new(-0.1278, 51.5074);
67 let nearby = db.query_within_radius("cities", &london, 1_000_000.0, 10)?;
68 println!(" Cities within 1000km of London: {}", nearby.len());
69 for (_, data, _) in &nearby {
70 println!(" - {}", String::from_utf8_lossy(data));
71 }
72 println!();
73
74 println!("5. Spatial Query Methods");
76 println!("------------------------");
77
78 let has_nearby = db.intersects_radius("cities", &london, 500_000.0)?;
80 println!(" Cities within 500km of London exist: {}", has_nearby);
81
82 let count = db.count_within_radius("cities", &london, 2_000_000.0)?;
84 println!(" Cities within 2000km of London: {}", count);
85
86 let europe = db.find_within_bounds("cities", -10.0, 40.0, 20.0, 60.0, 10)?;
88 println!(" Cities in European bounding box: {}", europe.len());
89 for (_point, data) in europe {
90 println!(" - {}", String::from_utf8_lossy(&data));
91 }
92 println!();
93
94 println!("6. Multiple Namespaces (POI)");
96 println!("----------------------------");
97
98 let landmarks = vec![
99 ("Big Ben", Point::new(-0.1245, 51.4994)),
100 ("Tower Bridge", Point::new(-0.0754, 51.5055)),
101 ("London Eye", Point::new(-0.1195, 51.5033)),
102 ];
103
104 for (name, point) in &landmarks {
105 db.insert_point("landmarks", point, name.as_bytes(), None)?;
106 }
107 println!(" Added {} London landmarks", landmarks.len());
108
109 let nearby_landmarks = db.query_within_radius("landmarks", &london, 5_000.0, 10)?;
111 println!(
112 " Landmarks within 5km of London: {}",
113 nearby_landmarks.len()
114 );
115 for (_, data, _) in &nearby_landmarks {
116 println!(" - {}", String::from_utf8_lossy(data));
117 }
118 println!();
119
120 println!("7. Trajectory Tracking");
122 println!("----------------------");
123
124 let delivery_route = vec![
125 TemporalPoint {
126 point: Point::new(-0.1278, 51.5074),
127 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
128 },
129 TemporalPoint {
130 point: Point::new(-0.0931, 51.5055),
131 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
132 },
133 TemporalPoint {
134 point: Point::new(-0.0865, 51.5045),
135 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
136 },
137 TemporalPoint {
138 point: Point::new(-0.1245, 51.4994),
139 timestamp: UNIX_EPOCH + Duration::from_secs(1640995380),
140 },
141 ];
142
143 db.insert_trajectory("delivery:truck001", &delivery_route, None)?;
144 println!(
145 " Stored delivery trajectory ({} waypoints)",
146 delivery_route.len()
147 );
148
149 let path = db.query_trajectory("delivery:truck001", 1640995200, 1640995320)?;
151 println!(
152 " Retrieved {} waypoints for first 2 minutes\n",
153 path.len()
154 );
155
156 println!("8. Updates and Deletes");
158 println!("----------------------");
159
160 db.insert("app:version", b"1.0.1", None)?;
162 let new_version = db.get("app:version")?.unwrap();
163 println!(
164 " Updated version to: {}",
165 String::from_utf8_lossy(&new_version)
166 );
167
168 let deleted = db.delete("user:alice")?;
170 println!(" Deleted key: {}", deleted.is_some());
171 println!();
172
173 println!("9. Database Statistics");
175 println!("----------------------");
176
177 let stats = db.stats();
178 println!(" Total keys: {}", stats.key_count);
179 println!(" Total operations: {}\n", stats.operations_count);
180
181 println!("10. TTL Expiration (lazy deletion)");
183 println!("-----------------------------------");
184
185 std::thread::sleep(Duration::from_secs(11));
186
187 match db.get("session:temp")? {
188 Some(_) => println!(" Session still active (unexpected)"),
189 None => println!(" ✓ Session expired (lazy check on read)\n"),
190 }
191
192 println!("11. Manual Cleanup");
194 println!("------------------");
195 let removed = db.cleanup_expired()?;
196 println!(" Removed {} expired keys from storage\n", removed);
197
198 println!("=== Comprehensive Demo Complete! ===");
199 println!("\nFeatures Demonstrated:");
200 println!(" • Key-value storage");
201 println!(" • TTL (lazy expiration + manual cleanup)");
202 println!(" • Atomic batch operations");
203 println!(" • Spatial point indexing");
204 println!(" • Radius queries");
205 println!(" • Bounding box queries");
206 println!(" • Multiple namespaces");
207 println!(" • Trajectory tracking");
208 println!(" • Updates and deletes");
209 println!(" • Manual expired key cleanup");
210
211 Ok(())
212}