dosio/
lib.rs

1//! Interface for the GMT Dynamic Optics Simulation
2//!
3//! All components of GMT Dynamic Optics Simulations must implement the [`inputs`](Dos::inputs) and [`outputs`](Dos::outputs) method of the [`Dos`] trait.
4//! All inputs and outputs must be a variant of the enum type [`IO`].
5
6pub mod error;
7pub mod io;
8
9#[doc(inline)]
10pub use error::DOSIOSError;
11#[doc(inline)]
12pub use io::IO;
13
14///  Create IO enum
15///
16/// Return a single IO enum or a vector of IO enums, either empty or with values
17/// ios!(variant)
18/// ios!(variant(value))
19/// ios!(variant1, variant2, ...)
20/// ios!(variant1(value1), variant2(value2), ...)
21#[macro_export]
22macro_rules! ios {
23    // ios!(variant)
24    ($name:ident) => {
25        $crate::io::jar::$name::io::<()>()
26    };
27    // ios!(variant(value))
28    ($name:ident($value:expr)) => {
29        $crate::io::jar::$name::io_with($value)
30    };
31    // ios!(variant1, variant2, ...)
32   ($($name:ident),+) => {
33        vec![$($crate::io::jar::$name::io::<()>()),+]
34    };
35    // ios!(variant1(value1), variant2(value2), ...)
36    ($($name:ident($value:expr)),+) => {
37        vec![$($crate::io::jar::$name::io_with($value)),+]
38    };
39}
40
41/// Specialization of [`Vec`] of [`IO`]
42pub trait IOVec {
43    type Output: std::cmp::PartialEq<IO<()>>
44        + std::cmp::PartialEq<IO<Vec<f64>>>
45        + std::cmp::PartialEq;
46    /// Removes and returns all the elements of a [`Vec`] that are equal to the elements in `vals`
47    fn pop_these(&mut self, vals: Vec<IO<()>>) -> Option<Vec<Self::Output>>;
48    /// Removes and returns the element of [`Vec`] that is equal to `val`
49    fn pop_this(&mut self, val: IO<()>) -> Option<Self::Output> {
50        self.pop_these(vec![val]).and_then(|mut x| x.pop())
51    }
52    /// Replaces all the elements of a [`Vec`] that are equal to the elements in `vals` by the corresponding value
53    fn swap_these(&mut self, vals: Vec<Self::Output>);
54    /// Replaces the element of [`Vec`] that is equal to `val` by `val`
55    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
81/// Used to get the list of inputs or outputs
82pub trait IOTags {
83    /// Return the list of outputs
84    fn outputs_tags(&self) -> Vec<IO<()>>;
85    /// Return the list of inputs
86    fn inputs_tags(&self) -> Vec<IO<()>>;
87}
88
89/// Dynamic Optics Simulation interface
90pub trait Dos {
91    /// `Self` inputs type
92    type Input;
93    /// `Self` outputs type
94    type Output;
95
96    /// Returns a [`IO`] output vector from `Self`
97    fn outputs(&mut self) -> Option<Vec<IO<Self::Output>>>;
98
99    /// Passe a [`IO`] input vector to `Self`
100    fn inputs(&mut self, data: Option<Vec<IO<Self::Input>>>) -> Result<&mut Self, DOSIOSError>;
101
102    /// Invokes the `next` method of `Self`
103    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    /// Combines `inputs`, `step` and `outputs` in a single method
114    ///
115    /// This is equivalent to `.inputs(...)?.step()?.outputs()?`
116    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}