1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*!
# [Actor]s clients

The module holds the implementation of the different clients that can be assigned to [Actor]s.

Any structure can become a client to an Actor if it implements the [Update] trait with either or both [Read] and [Write] traits.

# Example

## Logging

A simple logger with a single entry:
```
use gmt_dos_clients::Logging;
let logging = Logging::<f64>::default();
```
A logger with 2 entries and pre-allocated with 1000 elements:
```
use gmt_dos_clients::Logging;
let logging = Logging::<f64>::default().n_entry(2).capacity(1_000);
```
## Signals

A constant signal for 100 steps
```
use gmt_dos_clients::{Signals, Signal};
let signal: Signals = Signals::new(1, 100).signals(Signal::Constant(3.14));
```

A 2 outputs signal made of a constant and a sinusoid for 100 steps
```
use gmt_dos_clients::{Signals, Signal};
let signal: Signals = Signals::new(2, 100)
               .output_signal(0, Signal::Constant(3.14))
               .output_signal(1, Signal::Sinusoid{
                                        amplitude: 1f64,
                                        sampling_frequency_hz: 1000f64,
                                        frequency_hz: 20f64,
                                        phase_s: 0f64
               });
```
## Rate transitionner

A rate transition actor for a named output/input pair sampling a [Vec]
```
use gmt_dos_clients::Sampler;
#[derive(interface::UID)]
enum MyIO {};
let sampler = Sampler::<Vec<f64>, MyIO>::default();
```

## Alias to input/output UID

Creating an alias to an already existing [UniqueIdentifier] (UID)
```
use std::sync::Arc;
use interface::{Data, Write, UniqueIdentifier,Size, UID, Update};

// Original UID
#[derive(UID)]
#[uid(data = u8)]
pub enum A {}
pub struct Client {}
impl Update for Client {}
impl Write<A> for Client {
    fn write(&mut self) -> Option<Data<A>> {
        Some(Data::new(10u8))
    }
}
impl Size<A> for Client {
    fn len(&self) -> usize {
        123
    }
}

// A alias with `Write` and `Size` trait implementation for `Client`
#[derive(UID)]
#[uid(data = u8)]
#[alias(name = A, client = Client, traits = Write ,Size)]
pub enum B {}

let _: <A as UniqueIdentifier>::DataType = 1u8;
let _: <B as UniqueIdentifier>::DataType = 2u8;

let mut client = Client {};
 println!(
    "Client Write<B>: {:?}",
    <Client as Write<B>>::write(&mut client)
);
println!(
    "Client Size<B>: {:?}",
    <Client as Size<B>>::len(&mut client)
);
```

[Actor]: https://docs.rs/gmt_dos-actors
[Update]: https://docs.rs/gmt_dos-actors-clients_interface/latest/gmt_dos_actors-clients_interface/struct.Update.html
[Read]: https://docs.rs/gmt_dos-actors-clients_interface/latest/gmt_dos_actors-clients_interface/struct.Read.html
[Write]: https://docs.rs/gmt_dos-actors-clients_interface/latest/gmt_dos_actors-clients_interface/struct.Write.html
[UniqueIdentifier]: https://docs.rs/gmt_dos-actors-clients_interface/latest/gmt_dos_actors-clients_interface/struct.UniqueIdentifier.html
*/

pub use interface::Tick;
use interface::{Data, Read, TimerMarker, UniqueIdentifier, Update, Write};
use std::mem::take;

pub mod signals;
pub mod multiplex;
pub mod low_pass_filter;
pub mod fill;
pub use signals::{OneSignal, Signal, Signals};
pub mod timer;
pub use timer::Timer;
pub mod logging;
pub use logging::Logging;
pub mod sampler;
pub use sampler::Sampler;
pub mod pulse;
pub use pulse::Pulse;
pub mod integrator;
pub use integrator::{Integrator, Offset};
pub mod smooth;
pub use smooth::{Smooth, Weight};
pub mod average;
pub use average::Average;
#[cfg(feature = "nalgebra")]
mod gain;
#[cfg(feature = "nalgebra")]
pub use gain::Gain;
pub mod leftright;
pub mod once;
pub mod operator;
pub mod print;
pub mod select;

/// Concatenates data into a [Vec]
pub struct Concat<T>(Vec<T>);
impl<T: Default> Default for Concat<T> {
    fn default() -> Self {
        Self(Vec::new())
    }
}
impl<T> Update for Concat<T> where T: Send + Sync {}
impl<T, U> Read<U> for Concat<T>
where
    T: Clone + Default + Send + Sync,
    U: UniqueIdentifier<DataType = T>,
{
    fn read(&mut self, data: Data<U>) {
        self.0.push((*data).clone());
    }
}
impl<T, U> Write<U> for Concat<T>
where
    T: Clone + Send + Sync,
    U: UniqueIdentifier<DataType = Vec<T>>,
{
    fn write(&mut self) -> Option<Data<U>> {
        Some(Data::new(take(&mut self.0)))
    }
}

/// Discrete data sets
pub struct Source<T> {
    n: usize,
    data: Vec<T>,
}
impl<T> Source<T> {
    pub fn new(data: Vec<T>, n: usize) -> Self {
        Source { n, data }
    }
}
impl<T> TimerMarker for Source<T> {}
impl<T> Update for Source<T> where T: Send + Sync {}

impl<T, V> Write<V> for Source<T>
where
    V: UniqueIdentifier<DataType = Vec<T>>,
    T: Send + Sync,
{
    fn write(&mut self) -> Option<Data<V>> {
        if self.data.is_empty() {
            None
        } else {
            let y: Vec<T> = self.data.drain(..self.n).collect();
            Some(Data::new(y))
        }
    }
}

pub trait Progress {
    fn progress<S: Into<String>>(name: S, len: usize) -> Self;
    fn increment(&mut self);
    fn finish(&mut self) {}
}

impl Progress for indicatif::ProgressBar {
    fn progress<S: Into<String>>(name: S, len: usize) -> Self {
        let progress = indicatif::ProgressBar::new(len as u64);
        progress.set_style(
            indicatif::ProgressStyle::with_template(
                "{msg} [{eta_precise}] {bar:50.cyan/blue} {percent:>3}%",
            )
            .unwrap(),
        );
        progress.set_message(name.into());
        // let bar: Bar = progress.bar(self.tick, "Timer:");
        progress
    }
    #[inline]
    fn increment(&mut self) {
        self.inc(1)
    }
    #[inline]
    fn finish(&mut self) {
        Self::finish(self);
    }
}