rusmpp_core/pdus/borrowed/
sm_resp.rs

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