Skip to main content

sim_codec_uds/
status.rs

1//! DTC status-bit helpers shared by the UDS codec and tests.
2
3use sim_kernel::{Expr, Symbol};
4use sim_lib_auto_core::DtcStatus;
5
6/// Decodes a UDS DTC status byte into the automotive status citizen.
7pub fn decode_dtc_status(byte: u8) -> DtcStatus {
8    DtcStatus::from_byte(byte)
9}
10
11/// Decodes a UDS DTC status byte into an expression map.
12pub fn dtc_status_expr(byte: u8) -> Expr {
13    let status = decode_dtc_status(byte);
14    Expr::Map(vec![
15        field("test_failed", status.test_failed),
16        field(
17            "test_failed_this_operation_cycle",
18            status.test_failed_this_operation_cycle,
19        ),
20        field("pending", status.pending),
21        field("confirmed", status.confirmed),
22        field(
23            "test_not_completed_since_clear",
24            status.test_not_completed_since_clear,
25        ),
26        field("test_failed_since_clear", status.test_failed_since_clear),
27        field(
28            "test_not_completed_this_operation_cycle",
29            status.test_not_completed_this_operation_cycle,
30        ),
31        field("warning_indicator", status.warning_indicator),
32    ])
33}
34
35pub(crate) fn status_byte_from_expr(expr: &Expr) -> Option<u8> {
36    let Expr::Map(entries) = expr else {
37        return None;
38    };
39    let status = DtcStatus {
40        test_failed: bool_field(entries, "test_failed")?,
41        test_failed_this_operation_cycle: bool_field(entries, "test_failed_this_operation_cycle")?,
42        pending: bool_field(entries, "pending")?,
43        confirmed: bool_field(entries, "confirmed")?,
44        test_not_completed_since_clear: bool_field(entries, "test_not_completed_since_clear")?,
45        test_failed_since_clear: bool_field(entries, "test_failed_since_clear")?,
46        test_not_completed_this_operation_cycle: bool_field(
47            entries,
48            "test_not_completed_this_operation_cycle",
49        )?,
50        warning_indicator: bool_field(entries, "warning_indicator")?,
51    };
52    Some(status.to_byte())
53}
54
55fn field(name: &str, value: bool) -> (Expr, Expr) {
56    (Expr::Symbol(Symbol::new(name)), Expr::Bool(value))
57}
58
59fn bool_field(entries: &[(Expr, Expr)], name: &str) -> Option<bool> {
60    entries.iter().find_map(|(key, value)| {
61        if key == &Expr::Symbol(Symbol::new(name)) {
62            match value {
63                Expr::Bool(value) => Some(*value),
64                _ => None,
65            }
66        } else {
67            None
68        }
69    })
70}