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