#![forbid(unsafe_code)]
use crate::noc::FabricRecord;
use crate::state_machine::stage::Stage;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum SessionContext {
Pase,
Case,
}
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Action {
Invoke {
session: SessionContext,
endpoint: u16,
cluster: u32,
command: u32,
payload: Vec<u8>,
expect: Expectation,
},
ReadAttribute {
session: SessionContext,
endpoint: u16,
cluster: u32,
attributes: &'static [u32],
expect: Expectation,
},
EvictCase {
fabric_id: u64,
peer_node_id: u64,
},
EstablishCase {
fabric_id: u64,
peer_node_id: u64,
},
Done(CommissionedFabric),
Abort {
send_disarm_failsafe: bool,
reason: String,
},
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Expectation {
CommissioningInfo,
ArmFailsafeResponse,
SetRegulatoryConfigResponse,
PaiCertChainResponse,
DacCertChainResponse,
AttestationResponse,
CsrResponse,
AddTrustedRootResponse,
NocResponse,
CommissioningCompleteResponse,
NetworkCommissioningInfo,
NetworkConfigResponse,
ConnectNetworkResponse,
CaseFailed,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct CommissionedFabric {
pub fabric: FabricRecord,
pub peer_node_id: u64,
pub peer_root_public_key: [u8; 65],
pub terminated_at: Stage,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn invoke_action_round_trips_through_clone() {
let a = Action::Invoke {
session: SessionContext::Pase,
endpoint: 0,
cluster: 0x0030,
command: 0x00,
payload: vec![0x15, 0x18],
expect: Expectation::ArmFailsafeResponse,
};
let b = a.clone();
match (a, b) {
(
Action::Invoke {
endpoint: e1,
cluster: c1,
command: cmd1,
..
},
Action::Invoke {
endpoint: e2,
cluster: c2,
command: cmd2,
..
},
) => {
assert_eq!(e1, e2);
assert_eq!(c1, c2);
assert_eq!(cmd1, cmd2);
}
_ => panic!("clone produced wrong variant"),
}
}
#[test]
fn expectation_is_copy() {
fn assert_copy<T: Copy>() {}
assert_copy::<Expectation>();
}
#[test]
fn session_context_distinguishes_pase_and_case() {
assert_ne!(SessionContext::Pase, SessionContext::Case);
}
#[test]
fn abort_reason_carries_string() {
let a = Action::Abort {
send_disarm_failsafe: true,
reason: "synthetic failure".to_string(),
};
match a {
Action::Abort {
reason,
send_disarm_failsafe,
} => {
assert!(send_disarm_failsafe);
assert_eq!(reason, "synthetic failure");
}
_ => panic!("expected Abort"),
}
}
}