jaq_std/
input.rs

1//! Native implementations of `inputs` and `input`.
2use crate::{v, Filter};
3use alloc::{boxed::Box, string::String};
4use jaq_core::{Cv, DataT, Error, Exn, RunPtr, ValX};
5
6/// Iterator over value results returned by the `inputs` filter.
7pub type Inputs<'i, V> = &'i RcIter<dyn Iterator<Item = Result<V, String>> + 'i>;
8
9/// A more flexible version of `&mut impl Iterator`.
10pub 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    /// Construct a new mutable iterator.
21    pub const fn new(iter: I) -> Self {
22        Self(core::cell::RefCell::new(iter))
23    }
24}
25
26/// Global data that provides mutable access to input values.
27pub trait HasInputs<'a, V> {
28    /// Obtain the inputs from global data.
29    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
38/// The `inputs` and `input` filters.
39pub 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}