rtlola_interpreter/api/
input.rs

1//! This module contains necessary traits and types to interface your datastructures with the interpreter.
2//! Most notably, the [EventFactory] trait represents a factory for events such that you can feed events of type [EventFactory::Record] to the monitor.
3//! To easy the implementation, there are helper traits like [InputMap] which works together with the [MappedFactory].
4//!
5//! Note: A struct implementing [EventFactory] for a given type can often be derived. For that take a look at the rtlola-interpreter-macros crate and the [AssociatedEventFactory] trait.
6
7// ######## Traits ############
8
9use std::collections::{HashMap, HashSet};
10use std::convert::Infallible;
11use std::error::Error;
12use std::fmt::{Display, Formatter};
13use std::marker::PhantomData;
14
15use itertools::Itertools;
16use rtlola_frontend::mir::InputReference;
17
18use crate::monitor::Event;
19use crate::{CondDeserialize, CondSerialize, Value, ValueConvertError};
20
21/// This trait provides the functionality to pass inputs to the monitor.
22/// You can either implement this trait for your own Datatype or use one of the predefined input methods.
23/// See [MappedFactory], [ArrayFactory], and [VectorFactory]
24pub trait EventFactory: Sized {
25    /// The type from which an event is generated by the input source.
26    type Record: Send;
27
28    /// The error type returned by the input source on IO errors or parsing issues.
29    type Error: Into<EventFactoryError> + Send + 'static;
30
31    /// Arbitrary type of the data provided to the input source at creation time.
32    type CreationData: Clone + Send;
33
34    /// Creates a new input source from a HashMap mapping the names of the inputs in the specification to their position in the event.
35    fn new(
36        map: HashMap<String, InputReference>,
37        setup_data: Self::CreationData,
38    ) -> Result<Self, EventFactoryError> {
39        let all = map.keys().cloned().collect::<HashSet<_>>();
40        let (i, found) = Self::try_new(map, setup_data)?;
41        let found = found.into_iter().collect::<HashSet<_>>();
42        let missing: Vec<String> = all.difference(&found).cloned().collect();
43        if !missing.is_empty() {
44            Err(EventFactoryError::InputStreamUnknown(missing))
45        } else {
46            Ok(i)
47        }
48    }
49
50    /// Construction the input for only a subset of the required input streams. Enables the combination of multiple Input implementors into one.
51    /// The returned Vector contains the names of the input streams that can be served by this input.
52    /// The constructed input should return `Value::None` for all inputs that are unknown to it.
53    fn try_new(
54        map: HashMap<String, InputReference>,
55        setup_data: Self::CreationData,
56    ) -> Result<(Self, Vec<String>), EventFactoryError>;
57
58    /// This function converts a record to an event.
59    fn get_event(&self, rec: Self::Record) -> Result<Event, EventFactoryError>;
60}
61
62/// This trait provides functionality to parse a type into an event.
63/// For that, getter functions for the different input streams are provided through the `func_for_input` method.
64/// Note: The [AssociatedEventFactory] trait is automatically implemented for all types that implement this trait.
65pub trait InputMap: Send {
66    /// Arbitrary type of the data provided at creation time to help initializing the input method.
67    type CreationData: Clone + Send;
68    /// The error returned if anything goes wrong.
69    type Error: Into<EventFactoryError> + Send + 'static;
70    /// Given the name of an input this function returns a function that given self returns the value for that input.
71    fn func_for_input(
72        name: &str,
73        data: Self::CreationData,
74    ) -> Result<ValueGetter<Self, Self::Error>, Self::Error>;
75}
76
77/// A trait to annotate Self with an [EventFactory] that accepts Self as a Record.
78pub trait AssociatedEventFactory {
79    /// The associated factory.
80    type Factory: EventFactory<Record = Self> + Sized;
81}
82
83// ######## Implementation ######################
84
85/// A function Type that projects a reference to `From` to a `Value`
86pub type ValueGetter<From, E> = Box<dyn (Fn(&From) -> Result<Value, E>)>;
87
88#[derive(Debug)]
89/// A generic Error to be used by [EventFactory]s
90pub enum EventFactoryError {
91    /// Could not find an associated struct field for the input streams.
92    InputStreamUnknown(Vec<String>),
93    /// The value of the struct field is not supported by the interpreter.
94    ///
95    /// *Help*: ```TryFrom<YourType> for Value``` has to be implemented.
96    ValueNotSupported(ValueConvertError),
97    /// The variant of the enum identified by the string was ignored when deriving the Input, yet it was received as an input.
98    VariantIgnored(String),
99    /// An unknown error occurred
100    Other(Box<dyn Error + Send + 'static>),
101}
102impl Display for EventFactoryError {
103    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
104        match self {
105            EventFactoryError::InputStreamUnknown(name) => {
106                write!(
107                    f,
108                    "The following input stream(s) cannot be served by the input: {}",
109                    name.join(", ")
110                )
111            }
112            EventFactoryError::ValueNotSupported(val) => {
113                write!(
114                    f,
115                    "The type of {val:?} is not supported by the interpreter."
116                )
117            }
118            EventFactoryError::Other(e) => {
119                write!(f, "Event Factory Error: {e}.")
120            }
121            EventFactoryError::VariantIgnored(variant) => {
122                write!(f, "Received ignored variant: {variant}.")
123            }
124        }
125    }
126}
127impl Error for EventFactoryError {
128    fn source(&self) -> Option<&(dyn Error + 'static)> {
129        match self {
130            EventFactoryError::InputStreamUnknown(_)
131            | EventFactoryError::ValueNotSupported(_)
132            | EventFactoryError::VariantIgnored(_) => None,
133            EventFactoryError::Other(e) => Some(e.as_ref()),
134        }
135    }
136}
137impl From<ValueConvertError> for EventFactoryError {
138    fn from(value: ValueConvertError) -> Self {
139        EventFactoryError::ValueNotSupported(value)
140    }
141}
142impl From<Infallible> for EventFactoryError {
143    fn from(_value: Infallible) -> Self {
144        unreachable!()
145    }
146}
147
148/// An input method for types that implement the [InputMap] trait. Useful if you do not want to bother with the order of the input streams in an event.
149/// Assuming the specification has 3 inputs: 'a', 'b' and 'c'. You could implement this trait for your custom 'MyType' as follows:
150/// ```
151/// use std::fmt::Formatter;
152///
153/// use rtlola_interpreter::input::{EventFactoryError, InputMap};
154/// use rtlola_interpreter::Value;
155/// #[cfg(feature = "serde")]
156/// use serde::{Deserialize, Serialize};
157///
158/// #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
159/// struct MyType {
160///     a: u64,
161///     b: Option<bool>,
162///     c: String,
163/// }
164///
165/// impl MyType {
166///     // Generate a new value for input stream 'a'
167///     fn a(rec: &Self) -> Result<Value, EventFactoryError> {
168///         Ok(Value::from(rec.a))
169///     }
170///
171///     // Generate a new value for input stream 'b'
172///     fn b(rec: &Self) -> Result<Value, EventFactoryError> {
173///         Ok(rec.b.map(|b| Value::from(b)).unwrap_or(Value::None))
174///     }
175///
176///     // Generate a new value for input stream 'c'
177///     fn c(rec: &Self) -> Result<Value, EventFactoryError> {
178///         Ok(Value::Str(rec.c.clone().into_boxed_str()))
179///     }
180/// }
181///
182/// impl InputMap for MyType {
183///     type CreationData = ();
184///     type Error = EventFactoryError;
185///
186///     fn func_for_input(
187///         name: &str,
188///         _data: Self::CreationData,
189///     ) -> Result<Box<dyn (Fn(&MyType) -> Result<Value, EventFactoryError>)>, EventFactoryError>
190///     {
191///         match name {
192///             "a" => Ok(Box::new(Self::a)),
193///             "b" => Ok(Box::new(Self::b)),
194///             "c" => Ok(Box::new(Self::c)),
195///             x => Err(EventFactoryError::InputStreamUnknown(vec![x.to_string()])),
196///         }
197///     }
198/// }
199/// ```
200#[allow(missing_debug_implementations)]
201pub struct MappedFactory<Inner: InputMap> {
202    translators: Vec<ValueGetter<Inner, Inner::Error>>,
203}
204
205impl<M: InputMap> AssociatedEventFactory for M {
206    type Factory = MappedFactory<M>;
207}
208impl<Inner: InputMap> EventFactory for MappedFactory<Inner> {
209    type CreationData = Inner::CreationData;
210    type Error = Inner::Error;
211    type Record = Inner;
212
213    fn try_new(
214        map: HashMap<String, InputReference>,
215        setup_data: Self::CreationData,
216    ) -> Result<(Self, Vec<String>), EventFactoryError> {
217        let mut translators: Vec<Option<_>> = (0..map.len()).map(|_| None).collect();
218        let mut found = Vec::with_capacity(map.len());
219        let default_fn = Box::new(|_r: &Inner| Ok(Value::None));
220        for (input_name, index) in map {
221            match Inner::func_for_input(input_name.as_str(), setup_data.clone()) {
222                Ok(projection) => {
223                    translators[index] = Some(projection);
224                    found.push(input_name.clone());
225                }
226                Err(e) => {
227                    let ie: EventFactoryError = e.into();
228                    if matches!(ie, EventFactoryError::InputStreamUnknown(_)) {
229                        translators[index] = Some(default_fn.clone())
230                    } else {
231                        return Err(ie);
232                    }
233                }
234            }
235        }
236        let translators = translators.into_iter().map(Option::unwrap).collect();
237        Ok((Self { translators }, found))
238    }
239
240    fn get_event(&self, rec: Inner) -> Result<Event, EventFactoryError> {
241        self.translators
242            .iter()
243            .map(|f| f(&rec).map_err(|e| e.into()))
244            .collect()
245    }
246}
247
248#[derive(Debug, Clone, Copy)]
249/// An error type for the [ArrayFactory]
250pub struct ArrayFactoryError<I: Error + Send + 'static>(I);
251impl<I: Error + Send + 'static> Display for ArrayFactoryError<I> {
252    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
253        <I as Display>::fmt(&self.0, f)
254    }
255}
256impl<I: Error + Send + 'static> Error for ArrayFactoryError<I> {
257    fn source(&self) -> Option<&(dyn Error + 'static)> {
258        Some(&self.0)
259    }
260}
261impl<I: Error + Send + 'static> From<ArrayFactoryError<I>> for EventFactoryError {
262    fn from(value: ArrayFactoryError<I>) -> Self {
263        Self::Other(Box::new(value.0))
264    }
265}
266/// The simplest input method to the monitor. It accepts any type that can be turned into `[Value; N]` where `N` is ideally the number of input streams.
267/// If N is smaller than the number of windows the array is extended with `Value::None`.
268/// The conversion to values and the order of inputs must be handled externally.
269#[derive(Debug, Clone)]
270pub struct ArrayFactory<
271    const N: usize,
272    I: Error + Send + 'static,
273    E: TryInto<[Value; N], Error = I> + CondSerialize + CondDeserialize,
274> {
275    num_inputs: usize,
276    phantom: PhantomData<E>,
277}
278
279impl<
280        const N: usize,
281        I: Error + Send + 'static,
282        E: TryInto<[Value; N], Error = I> + Send + CondSerialize + CondDeserialize,
283    > EventFactory for ArrayFactory<N, I, E>
284{
285    type CreationData = ();
286    type Error = ArrayFactoryError<I>;
287    type Record = E;
288
289    fn try_new(
290        map: HashMap<String, InputReference>,
291        _setup_data: Self::CreationData,
292    ) -> Result<(Self, Vec<String>), EventFactoryError> {
293        let num_inputs = map.len();
294        let found: Vec<_> = map
295            .into_iter()
296            .sorted_by(|a, b| Ord::cmp(&a.1, &b.1))
297            .map(|(name, _)| name)
298            .take(N)
299            .collect();
300        Ok((
301            ArrayFactory {
302                num_inputs,
303                phantom: PhantomData,
304            },
305            found,
306        ))
307    }
308
309    fn get_event(&self, rec: Self::Record) -> Result<Event, EventFactoryError> {
310        let arr = rec.try_into().map_err(ArrayFactoryError)?;
311        let mut v = Vec::from(arr);
312        // Fill rest of the event with nones;
313        v.resize(self.num_inputs, Value::None);
314        Ok(v)
315    }
316}
317
318#[derive(Debug, Clone, Copy)]
319/// An error type for the [VectorFactory]
320pub enum VectorFactoryError<I: Error + Send + 'static> {
321    /// Error while creating the Vector in the [VectorFactory]
322    Inner(I),
323    /// Size of the generated ``Vec<Value>`` is different from the specified size while creating the [VectorFactory]
324    InvalidSize {
325        #[allow(missing_docs)]
326        expected: usize,
327        #[allow(missing_docs)]
328        got: usize,
329    },
330}
331impl<I: Error + Send + 'static> Display for VectorFactoryError<I> {
332    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
333        match self {
334            VectorFactoryError::Inner(inner) => <I as Display>::fmt(inner, f),
335            VectorFactoryError::InvalidSize { expected, got } => {
336                write!(f, "Invalid size(expected: {expected}, got: {got})")
337            }
338        }
339    }
340}
341impl<I: Error + Send + 'static> Error for VectorFactoryError<I> {
342    fn source(&self) -> Option<&(dyn Error + 'static)> {
343        match self {
344            VectorFactoryError::Inner(i) => Some(i),
345            VectorFactoryError::InvalidSize { .. } => None,
346        }
347    }
348}
349impl<I: Error + Send + 'static> From<VectorFactoryError<I>> for EventFactoryError {
350    fn from(value: VectorFactoryError<I>) -> Self {
351        Self::Other(Box::new(value))
352    }
353}
354
355/// One of the simplest input method to the monitor. It accepts any type that can be turned into `Vec<Value>`.
356/// If the length of the vector is smaller than the number of windows the vector is extended with `Value::None`.
357/// The conversion to values and the order of inputs must be handled externally. When creating the [VectorFactory]
358/// the user must provide the length of the vector that is returned in the conversion. The implementation then checks
359/// dynamically if this size is satisfied.
360#[derive(Debug, Clone)]
361pub struct VectorFactory<
362    I: Error + Send + 'static,
363    E: TryInto<Vec<Value>, Error = I> + CondSerialize + CondDeserialize,
364> {
365    num_inputs: usize,
366    len_vector: usize,
367    phantom: PhantomData<E>,
368}
369
370impl<
371        I: Error + Send + 'static,
372        E: TryInto<Vec<Value>, Error = I> + Send + CondSerialize + CondDeserialize,
373    > EventFactory for VectorFactory<I, E>
374{
375    type CreationData = usize;
376    type Error = VectorFactoryError<I>;
377    type Record = E;
378
379    fn try_new(
380        map: HashMap<String, InputReference>,
381        setup_data: Self::CreationData,
382    ) -> Result<(Self, Vec<String>), EventFactoryError> {
383        let num_inputs = map.len();
384        let len_vector = setup_data;
385        let found: Vec<_> = map
386            .into_iter()
387            .sorted_by(|a, b| Ord::cmp(&a.1, &b.1))
388            .map(|(name, _)| name)
389            .take(len_vector)
390            .collect();
391        Ok((
392            Self {
393                num_inputs,
394                len_vector,
395                phantom: PhantomData,
396            },
397            found,
398        ))
399    }
400
401    fn get_event(&self, rec: Self::Record) -> Result<Event, EventFactoryError> {
402        let mut vec: Vec<_> = rec.try_into().map_err(VectorFactoryError::Inner)?;
403        if vec.len() != self.len_vector {
404            Err(VectorFactoryError::<I>::InvalidSize {
405                expected: self.len_vector,
406                got: vec.len(),
407            }
408            .into())
409        } else {
410            // Fill rest of the event with nones;
411            vec.resize(self.num_inputs, Value::None);
412            Ok(vec)
413        }
414    }
415}
416
417impl AssociatedEventFactory for Vec<Value> {
418    type Factory = VectorFactory<Infallible, Vec<Value>>;
419}
420
421/// A dummy event factory, that never produces a value for an input stream.
422#[derive(Debug, Copy, Clone)]
423pub struct EmptyFactory<T: Send>(usize, PhantomData<T>);
424
425/// A type that represents the event in which no input streams gets a new value
426#[derive(Debug, Copy, Clone, Default)]
427pub struct NoEvent;
428
429impl<T: Send> EventFactory for EmptyFactory<T> {
430    type CreationData = ();
431    type Error = Infallible;
432    type Record = T;
433
434    fn try_new(
435        map: HashMap<String, InputReference>,
436        _setup_data: Self::CreationData,
437    ) -> Result<(Self, Vec<String>), EventFactoryError> {
438        Ok((Self(map.len(), PhantomData), vec![]))
439    }
440
441    fn get_event(&self, _rec: Self::Record) -> Result<Event, EventFactoryError> {
442        Ok(vec![Value::None; self.0])
443    }
444}
445
446impl AssociatedEventFactory for NoEvent {
447    type Factory = EmptyFactory<NoEvent>;
448}