use crate::{prelude::*, Ack, Cancellation, Control, ControlAckMode, QueryAck};
use deku::prelude::*;
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, DekuRead, DekuWrite)]
#[deku(
endian = "endian",
ctx = "endian: deku::ctx::Endian, cam: &ControlAckMode, packet_header: &PacketHeader",
id = "CommandPayload::derive_type(cam, packet_header)"
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CommandPayload {
#[deku(id = "CommandPayload::Control(_)")]
Control(Control),
#[deku(id = "CommandPayload::Cancellation(_)")]
Cancellation(Cancellation),
#[deku(id = "CommandPayload::ValidationAck(_)")]
ValidationAck(#[deku(ctx = "cam")] Ack),
#[deku(id = "CommandPayload::ExecAck(_)")]
ExecAck(#[deku(ctx = "cam")] Ack),
#[deku(id = "CommandPayload::QueryAck(_)")]
QueryAck(QueryAck),
}
impl CommandPayload {
fn derive_type(cam: &ControlAckMode, packet_header: &PacketHeader) -> CommandPayload {
if packet_header.is_ack_packet().unwrap() {
if [cam.validation(), cam.execution(), cam.state()]
.iter()
.filter(|&x| *x)
.count()
!= 1
{
panic!("CAM field in ACK packet does not exclusively select one of Validation, Exec, or Query");
}
if cam.validation() {
CommandPayload::ValidationAck(Ack::default())
} else if cam.execution() {
CommandPayload::ExecAck(Ack::default())
} else if cam.state() {
CommandPayload::QueryAck(QueryAck::default())
} else {
unreachable!()
}
} else if packet_header.is_cancellation_packet().unwrap() {
CommandPayload::Cancellation(Cancellation::default())
} else {
CommandPayload::Control(Control::default())
}
}
pub fn size_words(&self) -> u16 {
match self {
CommandPayload::Control(p) => p.size_words(),
CommandPayload::Cancellation(p) => p.size_words(),
CommandPayload::ValidationAck(p) => p.size_words(),
CommandPayload::ExecAck(p) => p.size_words(),
CommandPayload::QueryAck(p) => p.size_words(),
}
}
pub fn control(&self) -> Result<&Control, VitaError> {
match self {
CommandPayload::Control(p) => Ok(p),
_ => Err(VitaError::ControlOnly),
}
}
pub fn control_mut(&mut self) -> Result<&mut Control, VitaError> {
match self {
CommandPayload::Control(p) => Ok(p),
_ => Err(VitaError::ControlOnly),
}
}
pub fn cancellation(&self) -> Result<&Cancellation, VitaError> {
match self {
CommandPayload::Cancellation(p) => Ok(p),
_ => Err(VitaError::CancellationOnly),
}
}
pub fn cancellation_mut(&mut self) -> Result<&mut Cancellation, VitaError> {
match self {
CommandPayload::Cancellation(p) => Ok(p),
_ => Err(VitaError::CancellationOnly),
}
}
pub fn validation_ack(&self) -> Result<&Ack, VitaError> {
match self {
CommandPayload::ValidationAck(p) => Ok(p),
_ => Err(VitaError::ValidationAckOnly),
}
}
pub fn validation_ack_mut(&mut self) -> Result<&mut Ack, VitaError> {
match self {
CommandPayload::ValidationAck(p) => Ok(p),
_ => Err(VitaError::ValidationAckOnly),
}
}
pub fn exec_ack(&self) -> Result<&Ack, VitaError> {
match self {
CommandPayload::ExecAck(p) => Ok(p),
_ => Err(VitaError::ExecAckOnly),
}
}
pub fn exec_ack_mut(&mut self) -> Result<&mut Ack, VitaError> {
match self {
CommandPayload::ExecAck(p) => Ok(p),
_ => Err(VitaError::ExecAckOnly),
}
}
pub fn query_ack(&self) -> Result<&QueryAck, VitaError> {
match self {
CommandPayload::QueryAck(p) => Ok(p),
_ => Err(VitaError::QueryAckOnly),
}
}
pub fn query_ack_mut(&mut self) -> Result<&mut QueryAck, VitaError> {
match self {
CommandPayload::QueryAck(p) => Ok(p),
_ => Err(VitaError::QueryAckOnly),
}
}
}