use rusmpp_macros::Rusmpp;
use crate::{
pdus::borrowed::Pdu,
tlvs::borrowed::{MessageDeliveryResponseTlvValue, Tlv},
types::borrowed::COctetString,
};
macro_rules! sm_resp {
($name:ident) => {
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
#[rusmpp(decode = borrowed, test = skip)]
#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
pub struct $name<'a, const N: usize> {
message_id: COctetString<'a, 1, 65>,
#[rusmpp(length = "unchecked")]
#[cfg_attr(feature = "arbitrary", arbitrary(default))]
tlvs: heapless::vec::Vec<Tlv<'a>, N>,
}
impl<'a, const N: usize> $name<'a, N> {
pub fn new(
message_id: COctetString<'a, 1, 65>,
tlvs: heapless::vec::Vec<MessageDeliveryResponseTlvValue<'a>, N>,
) -> Self {
let tlvs = tlvs.into_iter().map(From::from).collect();
Self { message_id, tlvs }
}
pub fn message_id(&'_ self) -> &'_ COctetString<'a, 1, 65> {
&self.message_id
}
pub fn tlvs(&'_ self) -> &'_ [Tlv<'_>] {
&self.tlvs
}
pub fn set_tlvs(
&mut self,
tlvs: heapless::vec::Vec<MessageDeliveryResponseTlvValue<'a>, N>,
) {
self.tlvs = tlvs.into_iter().map(From::from).collect();
}
pub fn push_tlv(&mut self, tlv: impl Into<MessageDeliveryResponseTlvValue<'a>>) -> Result<(), Tlv<'a>> {
self.tlvs.push(Tlv::from(tlv.into()))?;
Ok(())
}
::pastey::paste! {
pub fn builder() -> [<$name Builder>]<'a, N> {
[<$name Builder>]::new()
}
}
}
::pastey::paste! {
#[derive(Debug, Default)]
pub struct [<$name Builder>]<'a, const N: usize> {
inner: $name<'a, N>,
}
impl<'a, const N: usize> [<$name Builder>]<'a, N> {
pub fn new() -> Self {
Self::default()
}
pub fn message_id(mut self, message_id: COctetString<'a, 1, 65>) -> Self {
self.inner.message_id = message_id;
self
}
pub fn tlvs(
mut self,
tlvs: heapless::vec::Vec<MessageDeliveryResponseTlvValue<'a>, N>,
) -> Self {
self.inner.set_tlvs(tlvs);
self
}
pub fn push_tlv(mut self, tlv: impl Into<MessageDeliveryResponseTlvValue<'a>>) -> Result<Self, Tlv<'a>> {
self.inner.push_tlv(tlv)?;
Ok(self)
}
pub fn build(self) -> $name<'a, N> {
self.inner
}
}
}
};
}
sm_resp!(DeliverSmResp);
sm_resp!(DataSmResp);
impl<'a, const N: usize> From<DeliverSmResp<'a, N>> for Pdu<'a, N> {
fn from(value: DeliverSmResp<'a, N>) -> Self {
Self::DeliverSmResp(value)
}
}
impl<'a, const N: usize> From<DataSmResp<'a, N>> for Pdu<'a, N> {
fn from(value: DataSmResp<'a, N>) -> Self {
Self::DataSmResp(value)
}
}
#[cfg(test)]
mod tests {
use crate::{tests::TestInstance, values::*};
use super::*;
impl<const N: usize> TestInstance for DeliverSmResp<'static, N> {
fn instances() -> alloc::vec::Vec<Self> {
alloc::vec![
Self::default(),
Self::builder()
.message_id(COctetString::new(b"123456789012345678\0").unwrap())
.build(),
Self::builder()
.message_id(COctetString::new(b"123456789012345678\0").unwrap())
.tlvs(
[
MessageDeliveryResponseTlvValue::AdditionalStatusInfoText(
COctetString::new(b"Octets\0").unwrap(),
),
MessageDeliveryResponseTlvValue::DeliveryFailureReason(
DeliveryFailureReason::TemporaryNetworkError,
),
]
.into()
)
.build(),
]
}
}
impl<const N: usize> TestInstance for DataSmResp<'static, N> {
fn instances() -> alloc::vec::Vec<Self> {
alloc::vec![
Self::default(),
Self::builder()
.message_id(COctetString::new(b"123456789012345678\0").unwrap())
.build(),
Self::builder()
.message_id(COctetString::new(b"123456789012345678\0").unwrap())
.tlvs(
[
MessageDeliveryResponseTlvValue::AdditionalStatusInfoText(
COctetString::new(b"Octets on steroids\0").unwrap(),
),
MessageDeliveryResponseTlvValue::NetworkErrorCode(
NetworkErrorCode::new(ErrorCodeNetworkType::SmppError, 1,)
),
]
.into()
)
.build(),
]
}
}
#[test]
fn encode_decode() {
crate::tests::borrowed::encode_decode_with_length_test_instances::<
DeliverSmResp<'static, 16>,
>();
crate::tests::borrowed::encode_decode_with_length_test_instances::<DataSmResp<'static, 16>>(
);
}
}