use crate::{v, Filter};
use alloc::{boxed::Box, string::String};
use jaq_core::{Cv, DataT, Error, Exn, RunPtr, ValX};
pub type Inputs<'i, V> = &'i RcIter<dyn Iterator<Item = Result<V, String>> + 'i>;
pub struct RcIter<I: ?Sized>(core::cell::RefCell<I>);
impl<T, I: Iterator<Item = T> + ?Sized> Iterator for &RcIter<I> {
type Item = T;
fn next(&mut self) -> Option<T> {
self.0.borrow_mut().next()
}
}
impl<I> RcIter<I> {
pub const fn new(iter: I) -> Self {
Self(core::cell::RefCell::new(iter))
}
}
pub trait HasInputs<'a, V> {
fn inputs(&self) -> Inputs<'a, V>;
}
impl<'a, V> HasInputs<'a, V> for Inputs<'a, V> {
fn inputs(&self) -> Inputs<'a, V> {
self
}
}
pub fn funs<D: DataT>() -> Box<[Filter<RunPtr<D>>]>
where
for<'a> D::Data<'a>: HasInputs<'a, D::V<'a>>,
{
Box::new([
("inputs", v(0), |cv| Box::new(inputs(cv))),
("input", v(0), |cv| Box::new(inputs(cv).next().into_iter())),
])
}
fn inputs<'a, D: DataT>(cv: Cv<'a, D>) -> impl Iterator<Item = ValX<'a, D::V<'a>>> + 'a
where
D::Data<'a>: HasInputs<'a, D::V<'a>>,
{
let inputs = cv.0.data().inputs();
inputs.map(|r| r.map_err(|e| Exn::from(Error::str(e))))
}