use crate::exec::error::ExecutionError;
use crate::exec::result::Row;
pub trait RowIterator: Iterator<Item = Result<Row, ExecutionError>> {
#[allow(dead_code)] fn size_hint_rows(&self) -> Option<usize> {
None
}
#[allow(dead_code)] fn is_sorted_by(&self, _field: &str) -> bool {
false
}
#[allow(dead_code)] fn boxed(self) -> Box<dyn RowIterator>
where
Self: Sized + 'static,
{
Box::new(self)
}
}
pub struct VecRowIterator {
rows: std::vec::IntoIter<Row>,
#[allow(dead_code)]
count: usize,
}
impl VecRowIterator {
#[allow(dead_code)] pub fn new(rows: Vec<Row>) -> Self {
let count = rows.len();
Self {
rows: rows.into_iter(),
count,
}
}
}
impl Iterator for VecRowIterator {
type Item = Result<Row, ExecutionError>;
fn next(&mut self) -> Option<Self::Item> {
self.rows.next().map(Ok)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.rows.size_hint()
}
}
impl RowIterator for VecRowIterator {
fn size_hint_rows(&self) -> Option<usize> {
Some(self.count)
}
fn is_sorted_by(&self, _field: &str) -> bool {
false
}
}
#[allow(dead_code)]
pub struct EmptyRowIterator;
impl Iterator for EmptyRowIterator {
type Item = Result<Row, ExecutionError>;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
impl RowIterator for EmptyRowIterator {
fn size_hint_rows(&self) -> Option<usize> {
Some(0)
}
fn is_sorted_by(&self, _field: &str) -> bool {
true }
}
pub struct ErrorRowIterator {
error: Option<ExecutionError>,
}
impl ErrorRowIterator {
#[allow(dead_code)] pub fn new(error: ExecutionError) -> Self {
Self { error: Some(error) }
}
}
impl Iterator for ErrorRowIterator {
type Item = Result<Row, ExecutionError>;
fn next(&mut self) -> Option<Self::Item> {
self.error.take().map(Err)
}
}
impl RowIterator for ErrorRowIterator {
fn size_hint_rows(&self) -> Option<usize> {
Some(0)
}
}
#[allow(dead_code)] pub fn collect_rows<I>(iter: I) -> Result<Vec<Row>, ExecutionError>
where
I: Iterator<Item = Result<Row, ExecutionError>>,
{
iter.collect()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::storage::Value;
use std::collections::HashMap;
fn create_test_row(id: usize) -> Row {
let mut values = HashMap::new();
values.insert("id".to_string(), Value::Number(id as f64));
Row {
values,
positional_values: vec![],
source_entities: HashMap::new(),
text_score: None,
highlight_snippet: None,
}
}
#[test]
fn test_vec_row_iterator() {
let rows = vec![create_test_row(1), create_test_row(2), create_test_row(3)];
let iter = VecRowIterator::new(rows);
assert_eq!(iter.size_hint_rows(), Some(3));
let collected: Vec<Row> = iter.map(|r| r.unwrap()).collect();
assert_eq!(collected.len(), 3);
}
#[test]
fn test_empty_row_iterator() {
let mut iter = EmptyRowIterator;
assert_eq!(iter.size_hint_rows(), Some(0));
assert!(iter.next().is_none());
assert!(RowIterator::is_sorted_by(&iter, "any_field"));
}
#[test]
fn test_error_row_iterator() {
let error = ExecutionError::UnsupportedOperator("test error".to_string());
let mut iter = ErrorRowIterator::new(error);
assert_eq!(iter.size_hint_rows(), Some(0));
let result = iter.next();
assert!(result.is_some());
assert!(result.unwrap().is_err());
assert!(iter.next().is_none());
}
#[test]
fn test_collect_rows() {
let rows = vec![create_test_row(1), create_test_row(2)];
let iter = VecRowIterator::new(rows);
let collected = collect_rows(iter).unwrap();
assert_eq!(collected.len(), 2);
}
#[test]
fn test_collect_rows_with_error() {
let error = ExecutionError::UnsupportedOperator("test".to_string());
let iter = ErrorRowIterator::new(error);
let result = collect_rows(iter);
assert!(result.is_err());
}
}