1pub mod error;
7pub mod io;
8
9#[doc(inline)]
10pub use error::DOSIOSError;
11#[doc(inline)]
12pub use io::IO;
13
14#[macro_export]
22macro_rules! ios {
23    ($name:ident) => {
25        $crate::io::jar::$name::io::<()>()
26    };
27    ($name:ident($value:expr)) => {
29        $crate::io::jar::$name::io_with($value)
30    };
31    ($($name:ident),+) => {
33        vec![$($crate::io::jar::$name::io::<()>()),+]
34    };
35    ($($name:ident($value:expr)),+) => {
37        vec![$($crate::io::jar::$name::io_with($value)),+]
38    };
39}
40
41pub trait IOVec {
43    type Output: std::cmp::PartialEq<IO<()>>
44        + std::cmp::PartialEq<IO<Vec<f64>>>
45        + std::cmp::PartialEq;
46    fn pop_these(&mut self, vals: Vec<IO<()>>) -> Option<Vec<Self::Output>>;
48    fn pop_this(&mut self, val: IO<()>) -> Option<Self::Output> {
50        self.pop_these(vec![val]).and_then(|mut x| x.pop())
51    }
52    fn swap_these(&mut self, vals: Vec<Self::Output>);
54    fn swap_this(&mut self, val: Self::Output) {
56        self.swap_these(vec![val])
57    }
58}
59impl<T: std::cmp::PartialEq<IO<()>> + std::cmp::PartialEq<IO<Vec<f64>>> + std::cmp::PartialEq> IOVec
60    for Vec<T>
61{
62    type Output = T;
63    fn pop_these(&mut self, vals: Vec<IO<()>>) -> Option<Vec<Self::Output>> {
64        vals.into_iter()
65            .map(|val| {
66                self.iter()
67                    .position(|io| *io == val)
68                    .map(|idx| self.remove(idx))
69            })
70            .collect()
71    }
72    fn swap_these(&mut self, vals: Vec<T>) {
73        vals.into_iter().for_each(|val| {
74            if let Some(idx) = self.iter().position(|io| *io == val) {
75                self[idx] = val;
76            }
77        });
78    }
79}
80
81pub trait IOTags {
83    fn outputs_tags(&self) -> Vec<IO<()>>;
85    fn inputs_tags(&self) -> Vec<IO<()>>;
87}
88
89pub trait Dos {
91    type Input;
93    type Output;
95
96    fn outputs(&mut self) -> Option<Vec<IO<Self::Output>>>;
98
99    fn inputs(&mut self, data: Option<Vec<IO<Self::Input>>>) -> Result<&mut Self, DOSIOSError>;
101
102    fn step(&mut self) -> Result<&mut Self, DOSIOSError>
104    where
105        Self: Sized + Iterator,
106    {
107        self.next()
108            .and(Some(self))
109            .ok_or_else(|| "DOS next step has issued None".into())
110            .map_err(DOSIOSError::Step)
111    }
112
113    fn in_step_out(
117        &mut self,
118        data: Option<Vec<IO<Self::Input>>>,
119    ) -> Result<Option<Vec<IO<Self::Output>>>, DOSIOSError>
120    where
121        Self: Sized + Iterator,
122    {
123        Ok(self.inputs(data)?.step()?.outputs())
124    }
125}