rusmpp_core/pdus/owned/
sm_resp.rs

1use rusmpp_macros::Rusmpp;
2
3use crate::{
4    pdus::owned::Pdu,
5    tlvs::owned::{MessageDeliveryResponseTlvValue, Tlv},
6    types::owned::COctetString,
7};
8
9macro_rules! sm_resp {
10    ($name:ident) => {
11        #[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
12        #[rusmpp(decode = owned, test = skip)]
13        #[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
14        #[cfg_attr(feature = "serde", derive(::serde::Serialize))]
15        #[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
16        pub struct $name {
17            /// This field contains the MC message ID of the submitted message.
18            /// It may be used at a later stage to query the status of a message,
19            /// cancel or replace the message.
20            message_id: COctetString<1, 65>,
21            /// Message delivery response TLVs ([`MessageDeliveryResponseTlvValue`])
22            #[rusmpp(length = "unchecked")]
23            tlvs: alloc::vec::Vec<Tlv>,
24        }
25
26        impl $name {
27            pub fn new(
28                message_id: COctetString<1, 65>,
29                tlvs: alloc::vec::Vec<impl Into<MessageDeliveryResponseTlvValue>>,
30            ) -> Self {
31                let tlvs = tlvs.into_iter().map(Into::into).map(From::from).collect();
32
33                Self { message_id, tlvs }
34            }
35
36            pub fn message_id(&self) -> &COctetString<1, 65> {
37                &self.message_id
38            }
39
40            pub fn tlvs(&self) -> &[Tlv] {
41                &self.tlvs
42            }
43
44            pub fn set_tlvs(
45                &mut self,
46                tlvs: alloc::vec::Vec<impl Into<MessageDeliveryResponseTlvValue>>,
47            ) {
48                self.tlvs = tlvs.into_iter().map(Into::into).map(From::from).collect();
49            }
50
51            pub fn push_tlv(&mut self, tlv: impl Into<MessageDeliveryResponseTlvValue>) {
52                self.tlvs.push(Tlv::from(tlv.into()));
53            }
54
55            ::pastey::paste! {
56                pub fn builder() -> [<$name Builder>] {
57                    [<$name Builder>]::new()
58                }
59            }
60        }
61
62        ::pastey::paste! {
63            #[derive(Debug, Default)]
64            pub struct [<$name Builder>] {
65               inner: $name,
66            }
67
68            impl [<$name Builder>] {
69                pub fn new() -> Self {
70                    Self::default()
71                }
72
73                pub fn message_id(mut self, message_id: COctetString<1, 65>) -> Self {
74                    self.inner.message_id = message_id;
75                    self
76                }
77
78                pub fn tlvs(
79                    mut self,
80                    tlvs: alloc::vec::Vec<impl Into<MessageDeliveryResponseTlvValue>>,
81                ) -> Self {
82                    self.inner.set_tlvs(tlvs);
83                    self
84                }
85
86                pub fn push_tlv(mut self, tlv: impl Into<MessageDeliveryResponseTlvValue>) -> Self {
87                    self.inner.push_tlv(tlv);
88                    self
89                }
90
91                pub fn build(self) -> $name {
92                    self.inner
93                }
94            }
95        }
96    };
97}
98
99sm_resp!(DeliverSmResp);
100sm_resp!(DataSmResp);
101
102impl From<DeliverSmResp> for Pdu {
103    fn from(value: DeliverSmResp) -> Self {
104        Self::DeliverSmResp(value)
105    }
106}
107
108impl From<DataSmResp> for Pdu {
109    fn from(value: DataSmResp) -> Self {
110        Self::DataSmResp(value)
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use std::str::FromStr;
117
118    use crate::{tests::TestInstance, values::*};
119
120    use super::*;
121
122    impl TestInstance for DeliverSmResp {
123        fn instances() -> alloc::vec::Vec<Self> {
124            alloc::vec![
125                Self::default(),
126                Self::builder()
127                    .message_id(COctetString::from_str("123456789012345678").unwrap())
128                    .build(),
129                Self::builder()
130                    .message_id(COctetString::from_str("123456789012345678").unwrap())
131                    .tlvs(alloc::vec![
132                        MessageDeliveryResponseTlvValue::AdditionalStatusInfoText(
133                            COctetString::from_str("Octets").unwrap(),
134                        ),
135                        MessageDeliveryResponseTlvValue::DeliveryFailureReason(
136                            DeliveryFailureReason::TemporaryNetworkError,
137                        ),
138                    ])
139                    .build(),
140            ]
141        }
142    }
143
144    impl TestInstance for DataSmResp {
145        fn instances() -> alloc::vec::Vec<Self> {
146            alloc::vec![
147                Self::default(),
148                Self::builder()
149                    .message_id(COctetString::from_str("123456789012345678").unwrap())
150                    .build(),
151                Self::builder()
152                    .message_id(COctetString::from_str("123456789012345678").unwrap())
153                    .tlvs(alloc::vec![
154                        MessageDeliveryResponseTlvValue::AdditionalStatusInfoText(
155                            COctetString::from_str("Octets on steroids").unwrap(),
156                        ),
157                        MessageDeliveryResponseTlvValue::NetworkErrorCode(NetworkErrorCode::new(
158                            ErrorCodeNetworkType::SmppError,
159                            1,
160                        )),
161                    ])
162                    .build(),
163            ]
164        }
165    }
166
167    #[test]
168    fn encode_decode() {
169        crate::tests::owned::encode_decode_with_length_test_instances::<DeliverSmResp>();
170        crate::tests::owned::encode_decode_with_length_test_instances::<DataSmResp>();
171    }
172}