use std::boxed::Box;
use bytes::BytesMut;
use crate::{
CommandId,
command::owned::Command,
decode::owned::{Decode, DecodeWithLength},
encode::{Length, owned::Encode},
pdus::owned::*,
tests::TestInstance,
types::owned::AnyOctetString,
};
pub fn encode_decode_test_instances<T>()
where
T: TestInstance + core::fmt::Debug + PartialEq + Encode + Decode,
{
for original in T::instances() {
let mut buf = BytesMut::with_capacity(1024);
if original.length() > buf.capacity() {
panic!("Buffer capacity is too small to hold the encoded data");
}
original.encode(&mut buf);
let mut encoded = buf.split_to(original.length());
let (decoded, _size) = T::decode(&mut encoded).expect("Failed to decode");
assert_eq!(original, decoded);
}
}
pub fn encode_decode_with_length_test_instances<T>()
where
T: TestInstance + core::fmt::Debug + PartialEq + Encode + DecodeWithLength,
{
for original in T::instances() {
let mut buf = BytesMut::with_capacity(1024);
if original.length() > buf.capacity() {
panic!("Buffer capacity is too small to hold the encoded data");
}
original.encode(&mut buf);
let mut encoded = buf.split_to(original.length());
let (decoded, _size) =
T::decode(&mut encoded, original.length()).expect("Failed to decode");
assert_eq!(original, decoded);
}
}
pub trait ChainExt {
fn chain_instances_as_cmds<T: TestInstance + Into<Pdu> + 'static>(
self,
) -> Box<dyn Iterator<Item = Command>>;
fn chain_single_cmd<T: Into<Pdu> + 'static>(self, pdu: T) -> Box<dyn Iterator<Item = Command>>;
}
impl<I: Iterator<Item = Command> + 'static> ChainExt for I {
fn chain_instances_as_cmds<T: TestInstance + Into<Pdu> + 'static>(
self,
) -> Box<dyn Iterator<Item = Command>> {
Box::new(
self.chain(
T::instances()
.into_iter()
.map(|pdu| Command::new(Default::default(), Default::default(), pdu)),
),
)
}
fn chain_single_cmd<T: Into<Pdu> + 'static>(self, pdu: T) -> Box<dyn Iterator<Item = Command>> {
Box::new(self.chain(core::iter::once(Command::new(
Default::default(),
Default::default(),
pdu,
))))
}
}
pub fn test_commands() -> alloc::vec::Vec<Command> {
core::iter::empty()
.chain_instances_as_cmds::<BindTransmitter>()
.chain_instances_as_cmds::<BindTransmitterResp>()
.chain_instances_as_cmds::<BindReceiver>()
.chain_instances_as_cmds::<BindReceiverResp>()
.chain_instances_as_cmds::<BindTransceiver>()
.chain_instances_as_cmds::<BindTransceiverResp>()
.chain_instances_as_cmds::<Outbind>()
.chain_instances_as_cmds::<AlertNotification>()
.chain_instances_as_cmds::<SubmitSm>()
.chain_instances_as_cmds::<SubmitSmResp>()
.chain_instances_as_cmds::<QuerySm>()
.chain_instances_as_cmds::<QuerySmResp>()
.chain_instances_as_cmds::<DeliverSm>()
.chain_instances_as_cmds::<DeliverSmResp>()
.chain_instances_as_cmds::<DataSm>()
.chain_instances_as_cmds::<DataSmResp>()
.chain_instances_as_cmds::<CancelSm>()
.chain_instances_as_cmds::<ReplaceSm>()
.chain_instances_as_cmds::<SubmitMulti>()
.chain_instances_as_cmds::<SubmitMultiResp>()
.chain_instances_as_cmds::<BroadcastSm>()
.chain_instances_as_cmds::<BroadcastSmResp>()
.chain_instances_as_cmds::<CancelBroadcastSm>()
.chain_instances_as_cmds::<QueryBroadcastSm>()
.chain_instances_as_cmds::<QueryBroadcastSmResp>()
.chain_single_cmd(Pdu::Unbind)
.chain_single_cmd(Pdu::UnbindResp)
.chain_single_cmd(Pdu::EnquireLink)
.chain_single_cmd(Pdu::EnquireLinkResp)
.chain_single_cmd(Pdu::GenericNack)
.chain_single_cmd(Pdu::CancelSmResp)
.chain_single_cmd(Pdu::ReplaceSmResp)
.chain_single_cmd(Pdu::CancelBroadcastSmResp)
.chain_single_cmd(Pdu::Other {
command_id: CommandId::Other(100),
body: AnyOctetString::from_static_slice(b"SMPP"),
})
.collect()
}
#[test]
#[ignore = "observation test"]
fn print_decode_errors() {
let mut buf = BytesMut::from(&[0u8; 1024][..]);
for command in test_commands() {
if command.length() > buf.len() {
panic!("Buffer is too small to hold the encoded data");
}
command.encode(&mut buf);
buf[8] = 0xFF;
buf[16] = 0xFF;
buf[32] = 0xFF;
buf[64] = 0xFF;
let result = Command::decode(&mut buf, command.length());
let _ = std::dbg!(result);
}
}