use std::sync::Arc;
use minijinja::{
Value,
value::{Enumerator, Object, ObjectRepr},
};
use taganak_core::{
graphs::{Graph, GraphView},
terms::Term,
};
use tokio::runtime::Handle;
use tracing::trace;
use crate::ParamsWithEnv;
struct GraphListIter<'e, G> {
params: ParamsWithEnv<'e, G>,
current: Option<Arc<Term>>,
}
impl<G> Iterator for GraphListIter<'_, G>
where
G: Graph + std::fmt::Debug + Sync + 'static,
Self: 'static,
{
type Item = Value;
fn next(&mut self) -> Option<Self::Item> {
let current = self.current.take()?;
trace!(?current, "iterator step for");
let handle = Handle::current();
let first = handle
.block_on(async {
let graph = self.params.graph.read().unwrap();
graph
.view()
.await
.object(
Some(&*current),
Some(
&"<http://www.w3.org/1999/02/22-rdf-syntax-ns#first>"
.try_into()
.expect("static IRI"),
),
)
.await
})
.ok()?;
trace!(?current, ?first, "list element is");
let rest = handle
.block_on(async {
let graph = self.params.graph.read().unwrap();
graph
.view()
.await
.object(
Some(&*current),
Some(
&"<http://www.w3.org/1999/02/22-rdf-syntax-ns#rest>"
.try_into()
.expect("static IRI"),
),
)
.await
})
.ok()?;
trace!(?current, ?rest, "next list item will be");
self.current = rest;
first.and_then(|t| super::term_to_value(self.params.clone(), &t))
}
}
#[derive(Debug, Clone)]
pub(crate) struct GraphList<'e, G> {
params: ParamsWithEnv<'e, G>,
}
impl<'e, G> GraphList<'e, G>
where
G: Graph + std::fmt::Debug + Sync + 'static,
{
pub(crate) fn new(params: ParamsWithEnv<'e, G>) -> Self {
trace!(?params.graph, ?params.base, "GraphList for");
Self { params }
}
}
impl<G> Object for GraphList<'_, G>
where
G: Graph + std::fmt::Debug + Sync + 'static,
Self: 'static,
{
fn repr(self: &Arc<Self>) -> ObjectRepr {
ObjectRepr::Iterable
}
fn enumerate(self: &Arc<Self>) -> Enumerator {
trace!(?self.params.base, "starting iteration from");
Enumerator::Iter(Box::new(GraphListIter {
params: self.params.clone(),
current: self.params.base.clone(),
}))
}
}