ariel_os_sensors/sensor/
samples.rs

1use super::{ChannelsSamplesZip, Reading, ReadingChannel, Sample, Sensor};
2
3/// Provides access to the sensor driver instance.
4/// For driver implementors only.
5pub trait SensorAccess: private::Sealed {
6    /// Returns the sensor driver instance that produced these samples.
7    /// For driver implementors only.
8    fn sensor(&self) -> &'static dyn Sensor;
9}
10
11/// Avoid external implementations of [`SensorAccess`].
12mod private {
13    use super::Samples;
14    pub trait Sealed {}
15
16    impl Sealed for Samples {}
17}
18
19/// Samples returned by a sensor driver.
20///
21/// This type implements [`Reading`] to iterate over the samples.
22///
23/// # For implementors
24///
25/// Sensor driver crates must enable the appropriate `max-sample-min-count-*` Cargo feature
26/// on this crate.
27/// For instance, a 3-axis accelerometer driver crate must enable `max-sample-min-count-3`
28/// to be able to return 3 [`Sample`]s using [`Samples::from_3()`].
29#[derive(Copy, Clone)]
30pub struct Samples {
31    samples: InnerSamples,
32    sensor: &'static dyn Sensor,
33}
34
35impl core::fmt::Debug for Samples {
36    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37        f.debug_struct("Samples")
38            .field("samples", &self.samples)
39            .field("sensor", &"&dyn Sensor")
40            .finish()
41    }
42}
43
44impl SensorAccess for Samples {
45    fn sensor(&self) -> &'static dyn Sensor {
46        self.sensor
47    }
48}
49
50impl Samples {
51    /// Creates a new [`Samples`] containing 1 sample.
52    pub fn from_1(sensor: &'static dyn Sensor, samples: [Sample; 1]) -> Self {
53        Self {
54            samples: InnerSamples::V1(samples),
55            sensor,
56        }
57    }
58
59    /// Creates a new [`Samples`] containing 2 samples.
60    #[cfg(feature = "max-sample-min-count-2")]
61    pub fn from_2(sensor: &'static dyn Sensor, samples: [Sample; 2]) -> Self {
62        Self {
63            samples: InnerSamples::V2(samples),
64            sensor,
65        }
66    }
67
68    /// Creates a new [`Samples`] containing 3 samples.
69    #[cfg(feature = "max-sample-min-count-3")]
70    pub fn from_3(sensor: &'static dyn Sensor, samples: [Sample; 3]) -> Self {
71        Self {
72            samples: InnerSamples::V3(samples),
73            sensor,
74        }
75    }
76
77    /// Creates a new [`Samples`] containing 4 samples.
78    #[cfg(feature = "max-sample-min-count-4")]
79    pub fn from_4(sensor: &'static dyn Sensor, samples: [Sample; 4]) -> Self {
80        Self {
81            samples: InnerSamples::V4(samples),
82            sensor,
83        }
84    }
85
86    /// Creates a new [`Samples`] containing 5 samples.
87    #[cfg(feature = "max-sample-min-count-5")]
88    pub fn from_5(sensor: &'static dyn Sensor, samples: [Sample; 5]) -> Self {
89        Self {
90            samples: InnerSamples::V5(samples),
91            sensor,
92        }
93    }
94
95    /// Creates a new [`Samples`] containing 6 samples.
96    #[cfg(feature = "max-sample-min-count-6")]
97    pub fn from_6(sensor: &'static dyn Sensor, samples: [Sample; 6]) -> Self {
98        Self {
99            samples: InnerSamples::V6(samples),
100            sensor,
101        }
102    }
103
104    /// Creates a new [`Samples`] containing 7 samples.
105    #[cfg(feature = "max-sample-min-count-7")]
106    pub fn from_7(sensor: &'static dyn Sensor, samples: [Sample; 7]) -> Self {
107        Self {
108            samples: InnerSamples::V7(samples),
109            sensor,
110        }
111    }
112
113    /// Creates a new [`Samples`] containing 8 samples.
114    #[cfg(feature = "max-sample-min-count-8")]
115    pub fn from_8(sensor: &'static dyn Sensor, samples: [Sample; 8]) -> Self {
116        Self {
117            samples: InnerSamples::V8(samples),
118            sensor,
119        }
120    }
121
122    /// Creates a new [`Samples`] containing 9 samples.
123    #[cfg(feature = "max-sample-min-count-9")]
124    pub fn from_9(sensor: &'static dyn Sensor, samples: [Sample; 9]) -> Self {
125        Self {
126            samples: InnerSamples::V9(samples),
127            sensor,
128        }
129    }
130
131    /// Creates a new [`Samples`] containing 10 samples.
132    #[cfg(feature = "max-sample-min-count-10")]
133    pub fn from_10(sensor: &'static dyn Sensor, samples: [Sample; 10]) -> Self {
134        Self {
135            samples: InnerSamples::V10(samples),
136            sensor,
137        }
138    }
139
140    /// Creates a new [`Samples`] containing 11 samples.
141    #[cfg(feature = "max-sample-min-count-11")]
142    pub fn from_11(sensor: &'static dyn Sensor, samples: [Sample; 11]) -> Self {
143        Self {
144            samples: InnerSamples::V11(samples),
145            sensor,
146        }
147    }
148
149    /// Creates a new [`Samples`] containing 12 samples.
150    #[cfg(feature = "max-sample-min-count-12")]
151    pub fn from_12(sensor: &'static dyn Sensor, samples: [Sample; 12]) -> Self {
152        Self {
153            samples: InnerSamples::V12(samples),
154            sensor,
155        }
156    }
157}
158
159impl Reading for Samples {
160    fn sample(&self) -> (ReadingChannel, Sample) {
161        match self.samples {
162            InnerSamples::V1(samples) => {
163                if let Some(sample) = samples.first() {
164                    let reading_channel = self.sensor.reading_channels().first();
165                    (reading_channel, *sample)
166                } else {
167                    // NOTE(no-panic): there is always at least one sample
168                    unreachable!();
169                }
170            }
171            #[cfg(feature = "max-sample-min-count-2")]
172            InnerSamples::V2(samples) => {
173                if let Some(sample) = samples.first() {
174                    let reading_channel = self.sensor.reading_channels().first();
175                    (reading_channel, *sample)
176                } else {
177                    // NOTE(no-panic): there is always at least one sample
178                    unreachable!();
179                }
180            }
181            #[cfg(feature = "max-sample-min-count-3")]
182            InnerSamples::V3(samples) => {
183                if let Some(sample) = samples.first() {
184                    let reading_channel = self.sensor.reading_channels().first();
185                    (reading_channel, *sample)
186                } else {
187                    // NOTE(no-panic): there is always at least one sample
188                    unreachable!();
189                }
190            }
191            #[cfg(feature = "max-sample-min-count-4")]
192            InnerSamples::V4(samples) => {
193                if let Some(sample) = samples.first() {
194                    let reading_channel = self.sensor.reading_channels().first();
195                    (reading_channel, *sample)
196                } else {
197                    // NOTE(no-panic): there is always at least one sample
198                    unreachable!();
199                }
200            }
201            #[cfg(feature = "max-sample-min-count-5")]
202            InnerSamples::V5(samples) => {
203                if let Some(sample) = samples.first() {
204                    let reading_channel = self.sensor.reading_channels().first();
205                    (reading_channel, *sample)
206                } else {
207                    // NOTE(no-panic): there is always at least one sample
208                    unreachable!();
209                }
210            }
211            #[cfg(feature = "max-sample-min-count-6")]
212            InnerSamples::V6(samples) => {
213                if let Some(sample) = samples.first() {
214                    let reading_channel = self.sensor.reading_channels().first();
215                    (reading_channel, *sample)
216                } else {
217                    // NOTE(no-panic): there is always at least one sample
218                    unreachable!();
219                }
220            }
221            #[cfg(feature = "max-sample-min-count-7")]
222            InnerSamples::V7(samples) => {
223                if let Some(sample) = samples.first() {
224                    let reading_channel = self.sensor.reading_channels().first();
225                    (reading_channel, *sample)
226                } else {
227                    // NOTE(no-panic): there is always at least one sample
228                    unreachable!();
229                }
230            }
231            #[cfg(feature = "max-sample-min-count-8")]
232            InnerSamples::V8(samples) => {
233                if let Some(sample) = samples.first() {
234                    let reading_channel = self.sensor.reading_channels().first();
235                    (reading_channel, *sample)
236                } else {
237                    // NOTE(no-panic): there is always at least one sample
238                    unreachable!();
239                }
240            }
241            #[cfg(feature = "max-sample-min-count-9")]
242            InnerSamples::V9(samples) => {
243                if let Some(sample) = samples.first() {
244                    let reading_channel = self.sensor.reading_channels().first();
245                    (reading_channel, *sample)
246                } else {
247                    // NOTE(no-panic): there is always at least one sample
248                    unreachable!();
249                }
250            }
251            #[cfg(feature = "max-sample-min-count-10")]
252            InnerSamples::V10(samples) => {
253                if let Some(sample) = samples.first() {
254                    let reading_channel = self.sensor.reading_channels().first();
255                    (reading_channel, *sample)
256                } else {
257                    // NOTE(no-panic): there is always at least one sample
258                    unreachable!();
259                }
260            }
261            #[cfg(feature = "max-sample-min-count-11")]
262            InnerSamples::V11(samples) => {
263                if let Some(sample) = samples.first() {
264                    let reading_channel = self.sensor.reading_channels().first();
265                    (reading_channel, *sample)
266                } else {
267                    // NOTE(no-panic): there is always at least one sample
268                    unreachable!();
269                }
270            }
271            #[cfg(feature = "max-sample-min-count-12")]
272            InnerSamples::V12(samples) => {
273                if let Some(sample) = samples.first() {
274                    let reading_channel = self.sensor.reading_channels().first();
275                    (reading_channel, *sample)
276                } else {
277                    // NOTE(no-panic): there is always at least one sample
278                    unreachable!();
279                }
280            }
281        }
282    }
283
284    fn samples(
285        &self,
286    ) -> impl ExactSizeIterator<Item = (ReadingChannel, Sample)> + core::iter::FusedIterator {
287        let reading_channels = self.sensor.reading_channels();
288        ChannelsSamplesZip::new(reading_channels, self.samples)
289    }
290}
291
292#[derive(Debug, Copy, Clone)]
293pub enum InnerSamples {
294    V1([Sample; 1]),
295    #[cfg(feature = "max-sample-min-count-2")]
296    V2([Sample; 2]),
297    #[cfg(feature = "max-sample-min-count-3")]
298    V3([Sample; 3]),
299    #[cfg(feature = "max-sample-min-count-4")]
300    V4([Sample; 4]),
301    #[cfg(feature = "max-sample-min-count-5")]
302    V5([Sample; 5]),
303    #[cfg(feature = "max-sample-min-count-6")]
304    V6([Sample; 6]),
305    #[cfg(feature = "max-sample-min-count-7")]
306    V7([Sample; 7]),
307    #[cfg(feature = "max-sample-min-count-8")]
308    V8([Sample; 8]),
309    #[cfg(feature = "max-sample-min-count-9")]
310    V9([Sample; 9]),
311    #[cfg(feature = "max-sample-min-count-10")]
312    V10([Sample; 10]),
313    #[cfg(feature = "max-sample-min-count-11")]
314    V11([Sample; 11]),
315    #[cfg(feature = "max-sample-min-count-12")]
316    V12([Sample; 12]),
317}
318
319impl InnerSamples {
320    pub fn iter(&self) -> impl ExactSizeIterator<Item = Sample> + core::iter::FusedIterator + '_ {
321        match self {
322            InnerSamples::V1(samples) => samples.iter().copied(),
323            #[cfg(feature = "max-sample-min-count-2")]
324            InnerSamples::V2(samples) => samples.iter().copied(),
325            #[cfg(feature = "max-sample-min-count-3")]
326            InnerSamples::V3(samples) => samples.iter().copied(),
327            #[cfg(feature = "max-sample-min-count-4")]
328            InnerSamples::V4(samples) => samples.iter().copied(),
329            #[cfg(feature = "max-sample-min-count-5")]
330            InnerSamples::V5(samples) => samples.iter().copied(),
331            #[cfg(feature = "max-sample-min-count-6")]
332            InnerSamples::V6(samples) => samples.iter().copied(),
333            #[cfg(feature = "max-sample-min-count-7")]
334            InnerSamples::V7(samples) => samples.iter().copied(),
335            #[cfg(feature = "max-sample-min-count-8")]
336            InnerSamples::V8(samples) => samples.iter().copied(),
337            #[cfg(feature = "max-sample-min-count-9")]
338            InnerSamples::V9(samples) => samples.iter().copied(),
339            #[cfg(feature = "max-sample-min-count-10")]
340            InnerSamples::V10(samples) => samples.iter().copied(),
341            #[cfg(feature = "max-sample-min-count-11")]
342            InnerSamples::V11(samples) => samples.iter().copied(),
343            #[cfg(feature = "max-sample-min-count-12")]
344            InnerSamples::V12(samples) => samples.iter().copied(),
345        }
346    }
347}