sim_lib_stream_core/cassette/
timing.rs1use sim_kernel::{Expr, Result, Symbol};
2
3use crate::{
4 StreamEnvelope, StreamMetadata, StreamPacket,
5 buffer::{expr_kind, field, symbol_field},
6};
7
8use super::{
9 StreamCassetteTiming, bool_field, ensure_fields, optional_u64, optional_u64_expr, parse_usize,
10};
11
12impl StreamCassetteTiming {
13 pub fn to_expr(&self) -> Expr {
15 Expr::Map(vec![
16 (
17 Expr::Symbol(Symbol::new("clock")),
18 Expr::Symbol(self.clock.clone()),
19 ),
20 (
21 Expr::Symbol(Symbol::new("packet-count")),
22 Expr::String(self.packet_count.to_string()),
23 ),
24 (
25 Expr::Symbol(Symbol::new("first-sequence")),
26 optional_u64_expr(self.first_sequence),
27 ),
28 (
29 Expr::Symbol(Symbol::new("last-sequence")),
30 optional_u64_expr(self.last_sequence),
31 ),
32 (Expr::Symbol(Symbol::new("finite")), Expr::Bool(self.finite)),
33 ])
34 }
35
36 pub fn from_expr(expr: &Expr) -> Result<Self> {
42 let Expr::Map(entries) = expr else {
43 return Err(sim_kernel::Error::TypeMismatch {
44 expected: "stream cassette timing map",
45 found: expr_kind(expr),
46 });
47 };
48 ensure_fields(
49 entries,
50 &[
51 "clock",
52 "packet-count",
53 "first-sequence",
54 "last-sequence",
55 "finite",
56 ],
57 )?;
58 Ok(Self {
59 clock: symbol_field(entries, "clock")?.clone(),
60 packet_count: parse_usize(entries, "packet-count")?,
61 first_sequence: optional_u64(field(entries, "first-sequence")?)?,
62 last_sequence: optional_u64(field(entries, "last-sequence")?)?,
63 finite: bool_field(entries, "finite")?,
64 })
65 }
66}
67
68pub(super) fn timing_from_envelopes(
69 metadata: &StreamMetadata,
70 envelopes: &[StreamEnvelope],
71) -> StreamCassetteTiming {
72 StreamCassetteTiming {
73 clock: metadata.clock().clone(),
74 packet_count: envelopes.len(),
75 first_sequence: envelopes.first().map(StreamEnvelope::sequence),
76 last_sequence: envelopes.last().map(StreamEnvelope::sequence),
77 finite: true,
78 }
79}
80
81pub(super) fn diagnostics_from_envelopes(envelopes: &[StreamEnvelope]) -> Vec<Symbol> {
82 let mut diagnostics = Vec::new();
83 for envelope in envelopes {
84 for diagnostic in envelope.diagnostics() {
85 push_unique(&mut diagnostics, diagnostic.clone());
86 }
87 if let StreamPacket::Diagnostic(packet) = envelope.packet() {
88 push_unique(&mut diagnostics, packet.kind().clone());
89 }
90 }
91 diagnostics
92}
93
94fn push_unique(symbols: &mut Vec<Symbol>, symbol: Symbol) {
95 if !symbols.contains(&symbol) {
96 symbols.push(symbol);
97 }
98}