1use crate::{v, Filter};
3use alloc::{boxed::Box, string::String};
4use jaq_core::{Cv, DataT, Error, Exn, RunPtr, ValX};
5
6pub type Inputs<'i, V> = &'i RcIter<dyn Iterator<Item = Result<V, String>> + 'i>;
8
9pub struct RcIter<I: ?Sized>(core::cell::RefCell<I>);
11
12impl<T, I: Iterator<Item = T> + ?Sized> Iterator for &RcIter<I> {
13 type Item = T;
14 fn next(&mut self) -> Option<T> {
15 self.0.borrow_mut().next()
16 }
17}
18
19impl<I> RcIter<I> {
20 pub const fn new(iter: I) -> Self {
22 Self(core::cell::RefCell::new(iter))
23 }
24}
25
26pub trait HasInputs<'a, V> {
28 fn inputs(&self) -> Inputs<'a, V>;
30}
31
32impl<'a, V> HasInputs<'a, V> for Inputs<'a, V> {
33 fn inputs(&self) -> Inputs<'a, V> {
34 self
35 }
36}
37
38pub fn funs<D: DataT>() -> Box<[Filter<RunPtr<D>>]>
40where
41 for<'a> D::Data<'a>: HasInputs<'a, D::V<'a>>,
42{
43 Box::new([
44 ("inputs", v(0), |cv| Box::new(inputs(cv))),
45 ("input", v(0), |cv| Box::new(inputs(cv).next().into_iter())),
46 ])
47}
48
49fn inputs<'a, D: DataT>(cv: Cv<'a, D>) -> impl Iterator<Item = ValX<D::V<'a>>> + 'a
50where
51 D::Data<'a>: HasInputs<'a, D::V<'a>>,
52{
53 let inputs = cv.0.data().inputs();
54 inputs.map(|r| r.map_err(|e| Exn::from(Error::str(e))))
55}