Skip to main content

gmt_dos_actors/
system.rs

1//! # System
2//!
3//! A system is a collection of actors that are hidden behind the [Sys] client.
4//! The actors of a system are given as fields of a user-defined structure `S` that is passed to [Sys].
5//!
6//! The user-defined structure `S` must implement the following traits:
7//!   * [System]` for S`
8//!   * [IntoIterator]`<`[Box]`<&'a dyn `[Check]>>` for &'a S`
9//!   * [IntoIterator]`<`[Box]`<dyn `[Task]`>> for `[Box]`<S>`
10//!   * [SystemInput]`<Gateway> for S`
11//!   * [SystemOutput]`<Gateway> for S`
12//!
13//! `Gateway` is a system's actor that receives inputs from other clients to this system ([SystemInput]`<Gateway>`)
14//! or send outputs from the system to other clients (([SystemOutput]`<Gateway>`))
15
16use std::any::type_name;
17use std::convert::Infallible;
18use std::marker::PhantomData;
19use std::{
20    fmt::Display,
21    ops::{Deref, DerefMut},
22};
23
24use crate::actor::Actor;
25use crate::framework::model::{Check, Task};
26use crate::framework::network::{ActorOutputsError, OutputRx};
27use crate::prelude::FlowChart;
28
29mod implementations;
30mod interfaces;
31
32pub use interfaces::{System, SystemInput, SystemOutput};
33
34pub enum New {}
35pub enum Built {}
36
37#[derive(Debug, thiserror::Error)]
38pub enum SystemError {
39    #[error("failed to build system")]
40    Ouputs(#[from] ActorOutputsError),
41    #[error("{0}")]
42    SubSystem(String),
43    #[error("not an error")]
44    NoError(#[from] Infallible),
45}
46impl<U, CO, const NO: usize, const NI: usize> From<OutputRx<U, CO, NI, NO>> for SystemError
47where
48    U: 'static + interface::UniqueIdentifier,
49    CO: interface::TryWrite<U>,
50{
51    fn from(value: OutputRx<U, CO, NI, NO>) -> Self {
52        SystemError::Ouputs(ActorOutputsError {
53            actor: value.actor,
54            output: value.output,
55        })
56    }
57}
58
59/// System client  
60#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
61pub struct Sys<T: System, S = Built> {
62    pub sys: T,
63    verbose: bool,
64    state: PhantomData<S>,
65}
66
67impl<T: System, S> Sys<T, S> {
68    pub fn quiet(mut self) -> Self {
69        self.verbose = false;
70        self
71    }
72    pub fn verbose(mut self) -> Self {
73        self.verbose = true;
74        self
75    }
76}
77impl<T: System, S> Clone for Sys<T, S> {
78    fn clone(&self) -> Self {
79        let mut sys = self.sys.clone();
80        sys.build().unwrap();
81        Self {
82            sys,
83            verbose: self.verbose,
84            state: PhantomData,
85        }
86    }
87}
88
89impl<T: System> Deref for Sys<T> {
90    type Target = T;
91
92    fn deref(&self) -> &Self::Target {
93        &self.sys
94    }
95}
96
97impl<T: System> DerefMut for Sys<T> {
98    fn deref_mut(&mut self) -> &mut Self::Target {
99        &mut self.sys
100    }
101}
102impl<T: System> Sys<T, New> {
103    pub fn new(sys: T) -> Self {
104        Self {
105            sys,
106            verbose: false,
107            state: PhantomData,
108        }
109    }
110
111    pub fn build(self) -> Result<Sys<T>, SystemError> {
112        log::info!("building Sys<{}>", type_name::<T>());
113        let mut this: Sys<T> = Sys {
114            sys: self.sys,
115            verbose: self.verbose,
116            state: PhantomData,
117        };
118        <T as System>::build(&mut this.sys)?;
119        Ok(this)
120    }
121}
122impl<T: System + FlowChart> Sys<T> {
123    /*     pub fn flowchart(self) -> Self {
124        self.sys.flowchart();
125        self
126    }
127    pub fn sys_flowchart(&self) {
128        self.sys.flowchart();
129    } */
130    pub fn sys_graph(&self) -> Option<crate::graph::Graph> {
131        self.sys.graph()
132    }
133}
134
135impl<T: System> Display for Sys<T> {
136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        write!(f, "{}", self.sys)
138    }
139}
140
141impl<'a, T: System> IntoIterator for &'a Sys<T>
142where
143    &'a T: IntoIterator<
144        Item = Box<&'a dyn Check>,
145        IntoIter = std::vec::IntoIter<<&'a T as IntoIterator>::Item>,
146    >,
147{
148    type Item = Box<&'a dyn Check>;
149
150    type IntoIter = std::vec::IntoIter<Self::Item>;
151
152    fn into_iter(self) -> Self::IntoIter {
153        self.sys.into_iter()
154    }
155}
156
157impl<T: System> IntoIterator for Box<Sys<T>>
158where
159    Box<T>: IntoIterator<
160        Item = Box<dyn Task>,
161        IntoIter = std::vec::IntoIter<<Box<T> as IntoIterator>::Item>,
162    >,
163{
164    type Item = Box<dyn Task>;
165
166    type IntoIter = std::vec::IntoIter<Self::Item>;
167
168    fn into_iter(self) -> Self::IntoIter {
169        let q = *self;
170        let w = q.sys;
171        let b = Box::new(w);
172        b.into_iter()
173    }
174}
175
176impl<
177        T: System + SystemInput<C, NI, NO>,
178        C: interface::TryUpdate,
179        const NI: usize,
180        const NO: usize,
181    > SystemInput<C, NI, NO> for Sys<T>
182{
183    fn input(&mut self) -> &mut Actor<C, NI, NO> {
184        self.sys.input()
185    }
186}
187
188impl<
189        T: System + SystemOutput<C, NI, NO>,
190        C: interface::TryUpdate,
191        const NI: usize,
192        const NO: usize,
193    > SystemOutput<C, NI, NO> for Sys<T>
194{
195    fn output(&mut self) -> &mut Actor<C, NI, NO> {
196        self.sys.output()
197    }
198}
199
200#[cfg(feature = "filing")]
201impl<T> interface::filing::Codec for Sys<T> where
202    T: Sized + System + serde::ser::Serialize + for<'de> serde::de::Deserialize<'de>
203{
204}