use arangors_lite::{Cursor, Database};
use crate::query::QueryResult;
use crate::{DatabaseRecord, Record};
#[derive(Debug)]
pub struct QueryCursor<T> {
pub(crate) cursor: Cursor<DatabaseRecord<T>>,
pub(crate) database: Database,
#[cfg(feature = "blocking")]
pending_result: Option<QueryResult<T>>,
}
impl<T: Record> QueryCursor<T> {
#[must_use]
#[inline]
#[allow(clippy::missing_const_for_fn)]
pub(crate) fn new(cursor: Cursor<DatabaseRecord<T>>, database: Database) -> Self {
Self {
#[cfg(feature = "blocking")]
pending_result: Some(cursor.result.clone().into()),
cursor,
database,
}
}
#[must_use]
#[inline]
pub fn result(&self) -> QueryResult<T> {
self.cursor.result.clone().into()
}
#[must_use]
#[inline]
#[allow(clippy::missing_const_for_fn)]
pub fn has_more(&self) -> bool {
self.cursor.more
}
#[must_use]
pub fn full_count(&self) -> Option<usize> {
self.cursor.extra.as_ref()?.stats.as_ref()?.full_count
}
#[maybe_async::maybe_async]
pub async fn next_batch(&mut self) -> Option<QueryResult<T>> {
if !self.has_more() {
return None;
}
if let Some(ref id) = self.cursor.id {
self.cursor = match self.database.aql_next_batch(id).await {
Ok(cursor) => cursor,
Err(error) => {
log::error!("Failed to get next batch: {}", error);
return None;
}
};
Some(self.result())
} else {
log::error!("No `id` associated to Aql Cursor");
None
}
}
}
#[cfg(feature = "blocking")]
impl<T: Record> Iterator for QueryCursor<T> {
type Item = QueryResult<T>;
fn next(&mut self) -> Option<Self::Item> {
match self.pending_result.clone() {
None => self.next_batch(),
Some(result) => {
self.pending_result = None;
Some(result)
}
}
}
}