use rusmpp_macros::Rusmpp;
use crate::{CommandId, CommandStatus, pdus::borrowed::Pdu};
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
#[rusmpp(decode = borrowed)]
#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
pub struct Command<'a, const N: usize> {
id: CommandId,
pub status: CommandStatus,
pub sequence_number: u32,
#[rusmpp(key = id, length = "unchecked")]
pdu: Option<Pdu<'a, N>>,
}
impl<'a, const N: usize> Default for Command<'a, N> {
fn default() -> Self {
Self {
id: CommandId::EnquireLink,
status: CommandStatus::EsmeRok,
sequence_number: 0,
pdu: Some(Pdu::EnquireLink),
}
}
}
impl<'a, const N: usize> Command<'a, N> {
pub fn new(status: CommandStatus, sequence_number: u32, pdu: impl Into<Pdu<'a, N>>) -> Self {
Self::new_const(status, sequence_number, pdu.into())
}
pub const fn new_const(status: CommandStatus, sequence_number: u32, pdu: Pdu<'a, N>) -> Self {
let id = pdu.command_id();
Self {
id,
status,
sequence_number,
pdu: Some(pdu),
}
}
#[inline]
pub const fn id(&self) -> CommandId {
self.id
}
#[inline]
pub const fn status(&self) -> CommandStatus {
self.status
}
#[inline]
pub const fn sequence_number(&self) -> u32 {
self.sequence_number
}
#[inline]
pub const fn pdu(&self) -> Option<&Pdu<'a, N>> {
self.pdu.as_ref()
}
#[inline]
pub fn set_pdu(&mut self, pdu: impl Into<Pdu<'a, N>>) {
let pdu = pdu.into();
self.id = pdu.command_id();
self.pdu = Some(pdu);
}
#[inline]
pub fn builder() -> CommandStatusBuilder<'a, N> {
Default::default()
}
}
#[derive(Debug, Default)]
pub struct CommandStatusBuilder<'a, const N: usize> {
inner: Command<'a, N>,
}
impl<'a, const N: usize> CommandStatusBuilder<'a, N> {
#[inline]
pub fn status(mut self, status: CommandStatus) -> SequenceNumberBuilder<'a, N> {
self.inner.status = status;
SequenceNumberBuilder { inner: self.inner }
}
}
#[derive(Debug)]
pub struct SequenceNumberBuilder<'a, const N: usize> {
inner: Command<'a, N>,
}
impl<'a, const N: usize> SequenceNumberBuilder<'a, N> {
#[inline]
pub fn sequence_number(mut self, sequence_number: u32) -> PduBuilder<'a, N> {
self.inner.sequence_number = sequence_number;
PduBuilder { inner: self.inner }
}
}
#[derive(Debug)]
pub struct PduBuilder<'a, const N: usize> {
inner: Command<'a, N>,
}
impl<'a, const N: usize> PduBuilder<'a, N> {
#[inline]
pub fn pdu(mut self, pdu: impl Into<Pdu<'a, N>>) -> Command<'a, N> {
self.inner.set_pdu(pdu);
self.inner
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn encode_decode() {
crate::tests::borrowed::encode_decode_with_length_test_instances::<Command<'static, 16>>();
}
}