Skip to main content

connect_stream_types/
lib.rs

1pub mod sample_table;
2
3use std::slice::IterMut;
4
5pub use sample_table::*;
6use serde::Deserialize;
7use serde::Deserializer;
8use serde::Serialize;
9use serde::de::Error as _;
10
11/// A value taken from a channel.
12#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
13#[serde(untagged)]
14pub enum Value {
15    String(String),
16    Double(f64),
17    Integer(i64),
18}
19
20impl From<String> for Value {
21    fn from(value: String) -> Self {
22        Value::String(value)
23    }
24}
25
26impl From<&str> for Value {
27    fn from(value: &str) -> Self {
28        Value::String(value.to_owned())
29    }
30}
31
32impl From<f64> for Value {
33    fn from(value: f64) -> Self {
34        Value::Double(value)
35    }
36}
37
38impl From<i64> for Value {
39    fn from(value: i64) -> Self {
40        Value::Integer(value)
41    }
42}
43
44impl Default for Value {
45    fn default() -> Value {
46        Value::Double(0.0)
47    }
48}
49
50impl Value {
51    pub fn into_series(self) -> ValueSeries {
52        self.into()
53    }
54}
55
56#[derive(Clone, Copy, Debug, PartialEq)]
57pub enum ValueRef<'value> {
58    String(&'value str),
59    Double(&'value f64),
60    Integer(&'value i64),
61}
62
63pub enum ValueRefMut<'value> {
64    String(&'value mut String),
65    Double(&'value mut f64),
66    Integer(&'value mut i64),
67}
68
69impl PartialEq<Value> for ValueRef<'_> {
70    fn eq(&self, other: &Value) -> bool {
71        match (*self, other) {
72            (ValueRef::String(s), Value::String(s2)) => s == s2,
73            (ValueRef::Double(d), Value::Double(d2)) => d == d2,
74            (ValueRef::Integer(i), Value::Integer(i2)) => i == i2,
75            _ => false,
76        }
77    }
78}
79
80/// A series of values. Mirrors the `nominal-streaming::PointsType` enum. We
81/// avoid simply re-using that type to avoid coupling the app to the api too
82/// closely.
83#[derive(Clone, Serialize, Deserialize, Debug)]
84#[serde(untagged)]
85pub enum ValueSeries {
86    String(Vec<String>),
87    Double(Vec<f64>),
88    Integer(Vec<i64>),
89}
90
91impl ValueSeries {
92    pub fn get(&self, index: usize) -> Option<ValueRef<'_>> {
93        match self {
94            ValueSeries::String(values) => values.get(index).map(|s| ValueRef::String(s.as_str())),
95            ValueSeries::Double(values) => values.get(index).map(ValueRef::Double),
96            ValueSeries::Integer(values) => values.get(index).map(ValueRef::Integer),
97        }
98    }
99
100    fn transpose_inner<T: Into<Value>>(values: Vec<T>) -> Vec<ValueSeries> {
101        values.into_iter().map(|v| v.into().into_series()).collect()
102    }
103
104    pub fn transpose(self) -> Vec<ValueSeries> {
105        match self {
106            Self::String(v) => Self::transpose_inner(v),
107            Self::Double(v) => Self::transpose_inner(v),
108            Self::Integer(v) => Self::transpose_inner(v),
109        }
110    }
111}
112
113#[derive(Debug)]
114pub struct ValueSeriesIter<'values> {
115    values: &'values ValueSeries,
116    index: usize,
117}
118
119#[derive(Debug)]
120pub enum ValueSeriesIterMut<'values> {
121    String(IterMut<'values, String>),
122    Double(IterMut<'values, f64>),
123    Integer(IterMut<'values, i64>),
124}
125
126impl<'values> ValueSeriesIter<'values> {
127    fn new(values: &'values ValueSeries) -> Self {
128        Self { values, index: 0 }
129    }
130}
131
132impl<'values> ValueSeriesIterMut<'values> {
133    fn new(values: &'values mut ValueSeries) -> Self {
134        match values {
135            ValueSeries::String(values) => ValueSeriesIterMut::String(values.iter_mut()),
136            ValueSeries::Double(values) => ValueSeriesIterMut::Double(values.iter_mut()),
137            ValueSeries::Integer(values) => ValueSeriesIterMut::Integer(values.iter_mut()),
138        }
139    }
140}
141
142impl<'values> Iterator for ValueSeriesIter<'values> {
143    type Item = ValueRef<'values>;
144
145    fn next(&mut self) -> Option<Self::Item> {
146        self.values.get(self.index).inspect(|_| {
147            self.index = self.index.saturating_add(1);
148        })
149    }
150}
151
152impl<'values> Iterator for ValueSeriesIterMut<'values> {
153    type Item = ValueRefMut<'values>;
154
155    fn next(&mut self) -> Option<Self::Item> {
156        match self {
157            ValueSeriesIterMut::String(values) => values.next().map(ValueRefMut::String),
158            ValueSeriesIterMut::Double(values) => values.next().map(ValueRefMut::Double),
159            ValueSeriesIterMut::Integer(values) => values.next().map(ValueRefMut::Integer),
160        }
161    }
162}
163
164impl<'values> IntoIterator for &'values ValueSeries {
165    type Item = ValueRef<'values>;
166    type IntoIter = ValueSeriesIter<'values>;
167
168    fn into_iter(self) -> Self::IntoIter {
169        ValueSeriesIter::new(self)
170    }
171}
172
173impl From<Vec<String>> for ValueSeries {
174    fn from(values: Vec<String>) -> Self {
175        ValueSeries::String(values)
176    }
177}
178
179impl From<Vec<&str>> for ValueSeries {
180    fn from(values: Vec<&str>) -> Self {
181        ValueSeries::String(values.into_iter().map(|s| s.to_owned()).collect())
182    }
183}
184
185impl From<Vec<f64>> for ValueSeries {
186    fn from(values: Vec<f64>) -> Self {
187        ValueSeries::Double(values)
188    }
189}
190
191impl From<Vec<i64>> for ValueSeries {
192    fn from(values: Vec<i64>) -> Self {
193        ValueSeries::Integer(values)
194    }
195}
196
197impl From<Value> for ValueSeries {
198    fn from(value: Value) -> Self {
199        match value {
200            Value::String(string) => ValueSeries::String(vec![string]),
201            Value::Double(double) => ValueSeries::Double(vec![double]),
202            Value::Integer(int) => ValueSeries::Integer(vec![int]),
203        }
204    }
205}
206
207impl Default for ValueSeries {
208    fn default() -> ValueSeries {
209        ValueSeries::Double(Vec::new())
210    }
211}
212
213impl ValueSeries {
214    pub fn iter(&self) -> ValueSeriesIter<'_> {
215        ValueSeriesIter::new(self)
216    }
217
218    pub fn iter_mut(&mut self) -> ValueSeriesIterMut<'_> {
219        ValueSeriesIterMut::new(self)
220    }
221
222    pub const fn len(&self) -> usize {
223        match self {
224            ValueSeries::String(values) => values.len(),
225            ValueSeries::Double(values) => values.len(),
226            ValueSeries::Integer(values) => values.len(),
227        }
228    }
229
230    pub fn is_empty(&self) -> bool {
231        self.len() == 0
232    }
233
234    /// Returns an iterator over numeric values cast to `f64`.
235    /// Returns `None` for `String` variants.
236    pub fn iter_numeric_as_f64(&self) -> Option<Box<dyn Iterator<Item = f64> + '_>> {
237        match self {
238            ValueSeries::Double(vals) => Some(Box::new(vals.iter().copied())),
239            ValueSeries::Integer(vals) => Some(Box::new(vals.iter().map(|&v| v as f64))),
240            ValueSeries::String(_) => None,
241        }
242    }
243
244    // Resizes down to the selected size
245    pub fn truncate(&mut self, size: usize) {
246        match self {
247            ValueSeries::String(values) => values.truncate(size),
248            ValueSeries::Double(values) => values.truncate(size),
249            ValueSeries::Integer(values) => values.truncate(size),
250        }
251    }
252}
253
254/// Custom deserializer that accepts usize from either a number or a string with underscores.
255/// For example: `5000` or `"5_000"` both deserialize to `5000`.
256fn usize_with_underscores<'de, D: Deserializer<'de>>(deserializer: D) -> Result<usize, D::Error> {
257    #[derive(Deserialize)]
258    #[serde(untagged)]
259    enum UsizeOrString {
260        Usize(usize),
261        String(String),
262    }
263
264    let value: UsizeOrString = serde::Deserialize::deserialize(deserializer)?;
265    match value {
266        UsizeOrString::Usize(value) => Ok(value),
267        UsizeOrString::String(value) => value
268            .replace('_', "")
269            .parse::<usize>()
270            .map_err(D::Error::custom),
271    }
272}
273
274#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
275#[serde(untagged)]
276pub enum BufferCapacity {
277    Points(#[serde(deserialize_with = "usize_with_underscores")] usize),
278    Duration {
279        unit: TimeUnit,
280        #[serde(deserialize_with = "usize_with_underscores")]
281        value: usize,
282    },
283}
284
285impl Default for BufferCapacity {
286    fn default() -> Self {
287        Self::Points(5000)
288    }
289}
290
291#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
292pub enum TimeUnit {
293    #[serde(alias = "milliseconds")]
294    #[serde(alias = "millis")]
295    #[serde(alias = "ms")]
296    Milliseconds,
297    #[serde(alias = "seconds")]
298    #[serde(alias = "sec")]
299    #[serde(alias = "s")]
300    Seconds,
301    #[serde(alias = "minutes")]
302    #[serde(alias = "min")]
303    #[serde(alias = "m")]
304    Minutes,
305    #[serde(alias = "hours")]
306    #[serde(alias = "hr")]
307    #[serde(alias = "h")]
308    Hours,
309}
310
311impl TimeUnit {
312    /// Converts this time unit and a value to a `core::time::Duration`.
313    pub fn to_duration(&self, value: usize) -> core::time::Duration {
314        match self {
315            TimeUnit::Milliseconds => core::time::Duration::from_millis(value as u64),
316            TimeUnit::Seconds => core::time::Duration::from_secs(value as u64),
317            TimeUnit::Minutes => {
318                core::time::Duration::from_secs(60_u64.saturating_mul(value as u64))
319            }
320            TimeUnit::Hours => {
321                core::time::Duration::from_secs(3600_u64.saturating_mul(value as u64))
322            }
323        }
324    }
325}
326
327impl BufferCapacity {
328    /// The amount of items that the buffer should accommodate.
329    ///
330    /// For the point count, this is the number of data points that can be stored in the buffer.
331    /// For time-based units, this is the number of "units" that can be stored (the actual point
332    /// count varies).
333    pub fn value(&self) -> usize {
334        match self {
335            BufferCapacity::Points(points) => *points,
336            BufferCapacity::Duration { value, unit: _ } => *value,
337        }
338    }
339}