rusmpp_core/pdus/owned/
data_sm.rs

1use rusmpp_macros::Rusmpp;
2
3use crate::{
4    pdus::owned::Pdu,
5    tlvs::owned::{MessageSubmissionRequestTlvValue, Tlv},
6    types::owned::COctetString,
7    values::{owned::*, *},
8};
9/// The data_sm operation is similar to the submit_sm in that it provides a means to submit a
10/// mobile-terminated message. However, data_sm is intended for packet-based applications
11/// such as WAP in that it features a reduced PDU body containing fields relevant to WAP or
12/// packet-based applications.
13#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
14#[rusmpp(decode = owned, test = skip)]
15#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
16#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
17#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
18pub struct DataSm {
19    /// The service_type parameter can be used to indicate the
20    /// SMS Application service associated with the message.
21    /// Specifying the service_type allows the ESME to avail of
22    /// enhanced messaging services such as “replace by
23    /// service_type” or control the teleservice used on the air
24    /// interface.
25    ///
26    /// Set to NULL for default MC
27    /// settings.
28    pub service_type: ServiceType,
29    /// Type of Number for source
30    /// address.
31    ///
32    /// If not known, set to NULL
33    /// (Unknown).
34    pub source_addr_ton: Ton,
35    /// Numbering Plan Indicator for
36    /// source address.
37    ///
38    /// If not known, set to NULL
39    /// (Unknown).
40    pub source_addr_npi: Npi,
41    /// Address of SME which
42    /// originated this message.
43    ///
44    /// If not known, set to NULL
45    /// (Unknown).
46    pub source_addr: COctetString<1, 21>,
47    /// Type of Number for destination.
48    pub dest_addr_ton: Ton,
49    /// Numbering Plan Indicator for destination.
50    pub dest_addr_npi: Npi,
51    /// Destination address of this short message For mobile
52    /// terminated messages, this is the directory number of the
53    /// recipient MS.
54    pub destination_addr: COctetString<1, 21>,
55    /// Indicates Message Mode and Message Type.
56    pub esm_class: EsmClass,
57    /// Indicator to signify if a MC
58    /// delivery receipt or an SME
59    /// acknowledgement is required.
60    pub registered_delivery: RegisteredDelivery,
61    /// Defines the encoding scheme
62    /// of the short message user data.
63    pub data_coding: DataCoding,
64    /// Message submission request TLVs ([`MessageSubmissionRequestTlvValue`])
65    #[rusmpp(length = "unchecked")]
66    tlvs: alloc::vec::Vec<Tlv>,
67}
68
69impl DataSm {
70    #[allow(clippy::too_many_arguments)]
71    pub fn new(
72        service_type: ServiceType,
73        source_addr_ton: Ton,
74        source_addr_npi: Npi,
75        source_addr: COctetString<1, 21>,
76        dest_addr_ton: Ton,
77        dest_addr_npi: Npi,
78        destination_addr: COctetString<1, 21>,
79        esm_class: EsmClass,
80        registered_delivery: RegisteredDelivery,
81        data_coding: DataCoding,
82        tlvs: alloc::vec::Vec<MessageSubmissionRequestTlvValue>,
83    ) -> Self {
84        let tlvs = tlvs.into_iter().map(From::from).collect();
85
86        Self {
87            service_type,
88            source_addr_ton,
89            source_addr_npi,
90            source_addr,
91            dest_addr_ton,
92            dest_addr_npi,
93            destination_addr,
94            esm_class,
95            registered_delivery,
96            data_coding,
97            tlvs,
98        }
99    }
100
101    pub fn tlvs(&self) -> &[Tlv] {
102        &self.tlvs
103    }
104
105    pub fn set_tlvs(&mut self, tlvs: alloc::vec::Vec<MessageSubmissionRequestTlvValue>) {
106        self.tlvs = tlvs.into_iter().map(From::from).collect();
107    }
108
109    pub fn clear_tlvs(&mut self) {
110        self.tlvs.clear();
111    }
112
113    pub fn push_tlv(&mut self, tlv: impl Into<MessageSubmissionRequestTlvValue>) {
114        self.tlvs.push(Tlv::from(tlv.into()));
115    }
116
117    pub fn builder() -> DataSmBuilder {
118        DataSmBuilder::new()
119    }
120}
121
122impl From<DataSm> for Pdu {
123    fn from(value: DataSm) -> Self {
124        Self::DataSm(value)
125    }
126}
127
128#[derive(Debug, Default)]
129pub struct DataSmBuilder {
130    inner: DataSm,
131}
132
133impl DataSmBuilder {
134    pub fn new() -> Self {
135        Default::default()
136    }
137
138    pub fn service_type(mut self, service_type: ServiceType) -> Self {
139        self.inner.service_type = service_type;
140        self
141    }
142
143    pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
144        self.inner.source_addr_ton = source_addr_ton;
145        self
146    }
147
148    pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
149        self.inner.source_addr_npi = source_addr_npi;
150        self
151    }
152
153    pub fn source_addr(mut self, source_addr: COctetString<1, 21>) -> Self {
154        self.inner.source_addr = source_addr;
155        self
156    }
157
158    pub fn dest_addr_ton(mut self, dest_addr_ton: Ton) -> Self {
159        self.inner.dest_addr_ton = dest_addr_ton;
160        self
161    }
162
163    pub fn dest_addr_npi(mut self, dest_addr_npi: Npi) -> Self {
164        self.inner.dest_addr_npi = dest_addr_npi;
165        self
166    }
167
168    pub fn destination_addr(mut self, destination_addr: COctetString<1, 21>) -> Self {
169        self.inner.destination_addr = destination_addr;
170        self
171    }
172
173    pub fn esm_class(mut self, esm_class: EsmClass) -> Self {
174        self.inner.esm_class = esm_class;
175        self
176    }
177
178    pub fn registered_delivery(mut self, registered_delivery: RegisteredDelivery) -> Self {
179        self.inner.registered_delivery = registered_delivery;
180        self
181    }
182
183    pub fn data_coding(mut self, data_coding: DataCoding) -> Self {
184        self.inner.data_coding = data_coding;
185        self
186    }
187
188    pub fn tlvs(mut self, tlvs: alloc::vec::Vec<MessageSubmissionRequestTlvValue>) -> Self {
189        self.inner.set_tlvs(tlvs);
190        self
191    }
192
193    pub fn clear_tlvs(mut self) -> Self {
194        self.inner.clear_tlvs();
195        self
196    }
197
198    pub fn push_tlv(mut self, tlv: impl Into<MessageSubmissionRequestTlvValue>) -> Self {
199        self.inner.push_tlv(tlv);
200        self
201    }
202
203    pub fn build(self) -> DataSm {
204        self.inner
205    }
206}
207
208#[cfg(test)]
209mod tests {
210    use std::str::FromStr;
211
212    use crate::tests::TestInstance;
213
214    use super::*;
215
216    impl TestInstance for DataSm {
217        fn instances() -> alloc::vec::Vec<Self> {
218            alloc::vec![
219                Self::default(),
220                Self::builder()
221                    .service_type(ServiceType::default())
222                    .source_addr_ton(Ton::International)
223                    .source_addr_npi(Npi::Isdn)
224                    .source_addr(COctetString::from_str("source_addr").unwrap())
225                    .dest_addr_ton(Ton::International)
226                    .dest_addr_npi(Npi::Isdn)
227                    .destination_addr(COctetString::from_str("destination_addr").unwrap())
228                    .esm_class(EsmClass::default())
229                    .registered_delivery(RegisteredDelivery::request_all())
230                    .data_coding(DataCoding::Ucs2)
231                    .build(),
232                Self::builder()
233                    .service_type(ServiceType::default())
234                    .source_addr_ton(Ton::International)
235                    .source_addr_npi(Npi::Isdn)
236                    .source_addr(COctetString::from_str("source_addr").unwrap())
237                    .dest_addr_ton(Ton::International)
238                    .dest_addr_npi(Npi::Isdn)
239                    .destination_addr(COctetString::from_str("destination_addr").unwrap())
240                    .esm_class(EsmClass::default())
241                    .registered_delivery(RegisteredDelivery::new(
242                        MCDeliveryReceipt::NoMcDeliveryReceiptRequested,
243                        SmeOriginatedAcknowledgement::SmeUserAcknowledgementRequested,
244                        IntermediateNotification::IntermediateNotificationRequested,
245                        0,
246                    ))
247                    .data_coding(DataCoding::Ucs2)
248                    .push_tlv(MessageSubmissionRequestTlvValue::SourceAddrSubunit(
249                        AddrSubunit::MobileEquipment,
250                    ))
251                    .push_tlv(MessageSubmissionRequestTlvValue::UssdServiceOp(
252                        UssdServiceOp::UssnConfirm,
253                    ))
254                    .build(),
255            ]
256        }
257    }
258
259    #[test]
260    fn encode_decode() {
261        crate::tests::owned::encode_decode_with_length_test_instances::<DataSm>();
262    }
263}