1use std::collections::HashMap;
2use std::fmt::Debug;
3use std::io::{Read, Seek, SeekFrom};
4use std::marker::PhantomData;
5use std::ops::Range;
6
7use chrono::{DateTime, Utc};
8use ordered_float::OrderedFloat;
9
10use crate::static_btree::error::{Error, Result};
11use crate::static_btree::key::{FixedStringKey, Key, KeyType};
12use crate::static_btree::query::types::{Operator, QueryCondition};
13use crate::static_btree::stree::Stree;
14
15#[derive(Debug, Clone)]
17pub struct StreamIndex<K: Key> {
18 num_items: usize,
20 branching_factor: u16,
22 index_offset: u64,
24 length: u64,
26 _marker: PhantomData<K>,
28}
29
30impl<K: Key> StreamIndex<K> {
31 pub fn new(num_items: usize, branching_factor: u16, index_offset: u64, length: u64) -> Self {
33 Self {
34 num_items,
35 branching_factor,
36 index_offset,
37 length,
38 _marker: PhantomData,
39 }
40 }
41
42 pub fn num_items(&self) -> usize {
44 self.num_items
45 }
46
47 pub fn branching_factor(&self) -> u16 {
49 self.branching_factor
50 }
51
52 pub fn index_offset(&self) -> u64 {
54 self.index_offset
55 }
56
57 pub fn length(&self) -> u64 {
59 self.length
60 }
61
62 pub fn find_exact_with_reader<R: Read + Seek + ?Sized>(
64 &self,
65 reader: &mut R,
66 key: K,
67 ) -> Result<Vec<u64>> {
68 let results = Stree::stream_find_exact(reader, self.num_items, self.branching_factor, key)?;
69
70 Ok(results.into_iter().map(|item| item.offset as u64).collect())
71 }
72
73 pub fn find_range_strict_with_reader<R: Read + Seek + ?Sized>(
82 &self,
83 reader: &mut R,
84 start: Option<K>,
85 start_strict: bool,
86 end: Option<K>,
87 end_strict: bool,
88 ) -> Result<Vec<u64>> {
89 let start_position = reader.stream_position()?;
90 let lower = start.unwrap_or_else(K::min_value);
91 let upper = end.unwrap_or_else(K::max_value);
92 let results = Stree::stream_find_range_strict(
93 reader,
94 self.num_items,
95 self.branching_factor,
96 lower,
97 start_strict,
98 upper,
99 end_strict,
100 );
101 reader.seek(SeekFrom::Start(start_position))?;
102 Ok(results?
103 .into_iter()
104 .map(|item| item.offset as u64)
105 .collect())
106 }
107
108 pub fn find_range_with_reader<R: Read + Seek + ?Sized>(
110 &self,
111 reader: &mut R,
112 start: Option<K>,
113 end: Option<K>,
114 ) -> Result<Vec<u64>> {
115 let start_position = reader.stream_position()?;
117 let results = match (start, end) {
118 (Some(start_key), Some(end_key)) => {
119 let results = Stree::stream_find_range(
120 reader,
121 self.num_items,
122 self.branching_factor,
123 start_key,
124 end_key,
125 )?;
126 Ok(results.into_iter().map(|item| item.offset as u64).collect())
127 }
128 (Some(start_key), None) => {
129 let results = Stree::stream_find_range(
131 reader,
132 self.num_items,
133 self.branching_factor,
134 start_key,
135 K::max_value(),
136 )?;
137 Ok(results.into_iter().map(|item| item.offset as u64).collect())
138 }
139 (None, Some(end_key)) => {
140 let results = Stree::stream_find_range(
142 reader,
143 self.num_items,
144 self.branching_factor,
145 K::min_value(),
146 end_key,
147 )?;
148 Ok(results.into_iter().map(|item| item.offset as u64).collect())
149 }
150 (None, None) => Err(Error::QueryError(
151 "find_range requires at least one bound".to_string(),
152 )),
153 };
154
155 reader.seek(SeekFrom::Start(start_position))?;
156 results
157 }
158}
159
160pub trait ReadSeek: Read + Seek {}
162impl<T: Read + Seek> ReadSeek for T {}
163
164pub trait TypedStreamSearchIndex: Send + Sync {
166 fn execute_query_condition(
168 &self,
169 reader: &mut dyn ReadSeek,
170 condition: &QueryCondition,
171 ) -> Result<Vec<u64>>;
172}
173
174macro_rules! impl_typed_stream_search_index {
176 ($key_type:ty, $enum_variant:path) => {
177 impl TypedStreamSearchIndex for StreamIndex<$key_type> {
178 fn execute_query_condition(
179 &self,
180 reader: &mut dyn ReadSeek,
181 condition: &QueryCondition,
182 ) -> Result<Vec<u64>> {
183 let start_position = reader.stream_position()?;
184 let key = match &condition.key {
186 $enum_variant(val) => val.clone(),
187 _ => {
188 return Err(Error::QueryError(format!(
189 "key type mismatch: expected {}, got {:?}",
190 stringify!($key_type),
191 condition.key
192 )))
193 }
194 };
195 let items = match condition.operator {
197 Operator::Eq => self.find_exact_with_reader(reader, key)?,
198 Operator::Ne => {
202 let mut results = self.find_range_strict_with_reader(
203 reader,
204 None,
205 false,
206 Some(key.clone()),
207 true,
208 )?;
209 let above = self.find_range_strict_with_reader(
210 reader,
211 Some(key),
212 true,
213 None,
214 false,
215 )?;
216 results.extend(above);
217 results
218 }
219 Operator::Gt => {
220 self.find_range_strict_with_reader(reader, Some(key), true, None, false)?
221 }
222 Operator::Lt => {
223 self.find_range_strict_with_reader(reader, None, false, Some(key), true)?
224 }
225 Operator::Ge => {
226 self.find_range_strict_with_reader(reader, Some(key), false, None, false)?
227 }
228 Operator::Le => {
229 self.find_range_strict_with_reader(reader, None, false, Some(key), false)?
230 }
231 };
232 reader.seek(SeekFrom::Start(start_position))?;
233 Ok(items)
234 }
235 }
236 };
237}
238
239impl_typed_stream_search_index!(i8, KeyType::Int8);
241impl_typed_stream_search_index!(u8, KeyType::UInt8);
242impl_typed_stream_search_index!(i16, KeyType::Int16);
243impl_typed_stream_search_index!(u16, KeyType::UInt16);
244impl_typed_stream_search_index!(i32, KeyType::Int32);
245impl_typed_stream_search_index!(i64, KeyType::Int64);
246impl_typed_stream_search_index!(u32, KeyType::UInt32);
247impl_typed_stream_search_index!(u64, KeyType::UInt64);
248impl_typed_stream_search_index!(OrderedFloat<f32>, KeyType::Float32);
249impl_typed_stream_search_index!(OrderedFloat<f64>, KeyType::Float64);
250impl_typed_stream_search_index!(bool, KeyType::Bool);
251impl_typed_stream_search_index!(DateTime<Utc>, KeyType::DateTime);
252impl_typed_stream_search_index!(FixedStringKey<20>, KeyType::StringKey20);
253impl_typed_stream_search_index!(FixedStringKey<50>, KeyType::StringKey50);
254impl_typed_stream_search_index!(FixedStringKey<100>, KeyType::StringKey100);
255
256pub struct StreamMultiIndex {
258 indices: HashMap<String, Box<dyn TypedStreamSearchIndex>>,
259 index_offsets: HashMap<String, Range<usize>>,
260}
261
262impl StreamMultiIndex {
263 pub fn new() -> Self {
265 Self {
266 indices: HashMap::new(),
267 index_offsets: HashMap::new(),
268 }
269 }
270
271 pub fn add_index<K: Key + 'static>(&mut self, field: String, index: StreamIndex<K>)
273 where
274 StreamIndex<K>: TypedStreamSearchIndex,
275 {
276 self.indices.insert(field, Box::new(index));
277 }
278
279 fn add_index_offset(&mut self, field: String, length: u64) {
280 let largest_offset = self
283 .index_offsets
284 .values()
285 .map(|v| v.end)
286 .max()
287 .unwrap_or(0);
288 self.index_offsets
289 .insert(field, largest_offset..largest_offset + length as usize);
290 }
291
292 pub fn add_string_index20(
294 &mut self,
295 field: String,
296 index: StreamIndex<FixedStringKey<20>>,
297 length: u64,
298 ) {
299 self.indices.insert(field.clone(), Box::new(index));
300 self.add_index_offset(field, length);
301 }
302
303 pub fn add_string_index50(
305 &mut self,
306 field: String,
307 index: StreamIndex<FixedStringKey<50>>,
308 length: u64,
309 ) {
310 self.indices.insert(field.clone(), Box::new(index));
311 self.add_index_offset(field, length);
312 }
313
314 pub fn add_string_index100(
316 &mut self,
317 field: String,
318 index: StreamIndex<FixedStringKey<100>>,
319 length: u64,
320 ) {
321 self.indices.insert(field.clone(), Box::new(index));
322 self.add_index_offset(field, length);
323 }
324
325 pub fn add_i8_index(&mut self, field: String, index: StreamIndex<i8>, length: u64) {
327 self.indices.insert(field.clone(), Box::new(index));
328 self.add_index_offset(field, length);
329 }
330
331 pub fn add_u8_index(&mut self, field: String, index: StreamIndex<u8>, length: u64) {
333 self.indices.insert(field.clone(), Box::new(index));
334 self.add_index_offset(field, length);
335 }
336
337 pub fn add_i16_index(&mut self, field: String, index: StreamIndex<i16>, length: u64) {
339 self.indices.insert(field.clone(), Box::new(index));
340 self.add_index_offset(field, length);
341 }
342
343 pub fn add_u16_index(&mut self, field: String, index: StreamIndex<u16>, length: u64) {
345 self.indices.insert(field.clone(), Box::new(index));
346 self.add_index_offset(field, length);
347 }
348
349 pub fn add_i32_index(&mut self, field: String, index: StreamIndex<i32>, length: u64) {
351 self.indices.insert(field.clone(), Box::new(index));
352 self.add_index_offset(field, length);
353 }
354
355 pub fn add_i64_index(&mut self, field: String, index: StreamIndex<i64>, length: u64) {
357 self.indices.insert(field.clone(), Box::new(index));
358 self.add_index_offset(field, length);
359 }
360
361 pub fn add_u32_index(&mut self, field: String, index: StreamIndex<u32>, length: u64) {
363 self.indices.insert(field.clone(), Box::new(index));
364 self.add_index_offset(field, length);
365 }
366
367 pub fn add_u64_index(&mut self, field: String, index: StreamIndex<u64>, length: u64) {
369 self.indices.insert(field.clone(), Box::new(index));
370 self.add_index_offset(field, length);
371 }
372
373 pub fn add_f32_index(
375 &mut self,
376 field: String,
377 index: StreamIndex<OrderedFloat<f32>>,
378 length: u64,
379 ) {
380 self.indices.insert(field.clone(), Box::new(index));
381 self.add_index_offset(field, length);
382 }
383
384 pub fn add_f64_index(
386 &mut self,
387 field: String,
388 index: StreamIndex<OrderedFloat<f64>>,
389 length: u64,
390 ) {
391 self.indices.insert(field.clone(), Box::new(index));
392 self.add_index_offset(field, length);
393 }
394
395 pub fn add_bool_index(&mut self, field: String, index: StreamIndex<bool>, length: u64) {
397 self.indices.insert(field.clone(), Box::new(index));
398 self.add_index_offset(field, length);
399 }
400
401 pub fn add_datetime_index(
403 &mut self,
404 field: String,
405 index: StreamIndex<DateTime<Utc>>,
406 length: u64,
407 ) {
408 self.indices.insert(field.clone(), Box::new(index));
409 self.add_index_offset(field, length);
410 }
411
412 pub fn query(
414 &self,
415 reader: &mut dyn ReadSeek,
416 conditions: &[QueryCondition],
417 ) -> Result<Vec<u64>> {
418 if conditions.is_empty() {
419 return Err(Error::QueryError("query cannot be empty".to_string()));
420 }
421 let first = &conditions[0];
422 let indexer = self.indices.get(&first.field).ok_or_else(|| {
423 Error::QueryError(format!("no index found for field '{}'", first.field))
424 })?;
425 let index_range = self.index_offsets.get(&first.field).ok_or_else(|| {
426 Error::QueryError(format!("no index range found for field '{}'", first.field))
427 })?;
428
429 let start_position = reader.stream_position()?;
432 reader.seek(SeekFrom::Start(start_position + index_range.start as u64))?;
434
435 let mut result_set = indexer.execute_query_condition(reader, first)?;
436 reader.seek(SeekFrom::Start(start_position))?;
440 if result_set.is_empty() {
441 return Ok(vec![]);
442 }
443
444 for cond in &conditions[1..] {
445 let start_position = reader.stream_position()?;
446 let indexer = self.indices.get(&cond.field).ok_or_else(|| {
447 Error::QueryError(format!("no index found for field '{}'", cond.field))
448 })?;
449 let index_range = self.index_offsets.get(&cond.field).ok_or_else(|| {
450 Error::QueryError(format!("no index range found for field '{}'", cond.field))
451 })?;
452 let index_start = start_position + index_range.start as u64;
453 reader.seek(SeekFrom::Start(index_start))?;
455 println!("index_start: {index_start}");
456 println!("start_position: {start_position}");
457 println!("query condition: {cond:?}");
458 let condition_results = indexer.execute_query_condition(reader, cond)?;
459 reader.seek(SeekFrom::Start(start_position))?;
461 result_set.retain(|offset| condition_results.contains(offset));
462 if result_set.is_empty() {
463 return Ok(vec![]); }
465 }
466 reader.seek(SeekFrom::Start(start_position))?;
468 Ok(result_set)
469 }
470}
471
472impl Default for StreamMultiIndex {
473 fn default() -> Self {
474 Self::new()
475 }
476}