Skip to main content

sim_lib_stream_device/
modeled.rs

1//! Deterministic modeled device sample sources.
2
3use sim_kernel::Symbol;
4
5use crate::{DeviceCaps, DeviceSample};
6
7/// A deterministic sample source driven entirely by an integer index.
8///
9/// Implementations must not read clocks, random sources, hardware, network, or
10/// process state. The same source and index must always produce the same sample.
11pub trait ModeledSource {
12    /// Sample type emitted by the source.
13    type Sample: DeviceSample;
14
15    /// Returns the sample for `index`.
16    fn at(&self, index: u64) -> Self::Sample;
17}
18
19/// Reports whether a modeled source's sequence numbers are monotone.
20pub fn seq_is_monotone<S: ModeledSource>(source: &S, start: u64, count: usize) -> bool {
21    let mut previous = None;
22    for offset in 0..count {
23        let Some(index) = start.checked_add(offset as u64) else {
24            return false;
25        };
26        let seq = source.at(index).seq();
27        if previous.is_some_and(|previous| previous > seq) {
28            return false;
29        }
30        previous = Some(seq);
31    }
32    true
33}
34
35/// Deterministic source for the base [`DeviceCaps`] sample.
36#[derive(Clone, Debug, PartialEq, Eq)]
37pub struct ModeledDeviceCapsSource {
38    device: Symbol,
39    streams: Vec<Symbol>,
40    inputs: Vec<Symbol>,
41    outputs: Vec<Symbol>,
42    seq_base: u64,
43}
44
45impl ModeledDeviceCapsSource {
46    /// Builds a modeled capabilities source.
47    pub fn new(
48        device: Symbol,
49        streams: Vec<Symbol>,
50        inputs: Vec<Symbol>,
51        outputs: Vec<Symbol>,
52    ) -> Self {
53        Self {
54            device,
55            streams,
56            inputs,
57            outputs,
58            seq_base: 0,
59        }
60    }
61
62    /// Sets the sequence number emitted at index zero.
63    pub fn with_seq_base(mut self, seq_base: u64) -> Self {
64        self.seq_base = seq_base;
65        self
66    }
67
68    /// Builds the deterministic demo source used by tests and docs.
69    pub fn demo() -> Self {
70        Self::new(
71            Symbol::qualified("device", "modeled-edge"),
72            vec![
73                Symbol::qualified("device/stream", "battery"),
74                Symbol::qualified("device/stream", "motion"),
75            ],
76            vec![Symbol::qualified("device/input", "button")],
77            vec![
78                Symbol::qualified("device/output", "screen"),
79                Symbol::qualified("device/output", "haptic"),
80            ],
81        )
82    }
83}
84
85impl ModeledSource for ModeledDeviceCapsSource {
86    type Sample = DeviceCaps;
87
88    fn at(&self, index: u64) -> Self::Sample {
89        DeviceCaps::new(
90            self.seq_base.saturating_add(index),
91            self.device.clone(),
92            self.streams.clone(),
93            self.inputs.clone(),
94            self.outputs.clone(),
95        )
96    }
97}