1use rusmpp_macros::Rusmpp;
2
3use crate::{
4 encode::Length,
5 pdus::owned::Pdu,
6 tlvs::{
7 TlvTag,
8 owned::{MessageDeliveryRequestTlvValue, Tlv},
9 },
10 types::owned::{COctetString, EmptyOrFullCOctetString, OctetString},
11 values::{owned::*, *},
12};
13
14#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
17#[rusmpp(decode = owned, test = skip)]
18#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
19#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
20#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
21pub struct DeliverSm {
22 pub service_type: ServiceType,
32 pub source_addr_ton: Ton,
34 pub source_addr_npi: Npi,
36 pub source_addr: COctetString<1, 21>,
38 pub dest_addr_ton: Ton,
40 pub dest_addr_npi: Npi,
42 pub destination_addr: COctetString<1, 21>,
48 pub esm_class: EsmClass,
51 pub protocol_id: u8,
54 pub priority_flag: PriorityFlag,
56 pub schedule_delivery_time: EmptyOrFullCOctetString<17>,
61 pub validity_period: EmptyOrFullCOctetString<17>,
68 pub registered_delivery: RegisteredDelivery,
71 pub replace_if_present_flag: ReplaceIfPresentFlag,
73 pub data_coding: DataCoding,
75 pub sm_default_msg_id: u8,
78 sm_length: u8,
80 #[rusmpp(length = sm_length)]
88 short_message: OctetString<0, 255>,
89 #[rusmpp(length = "unchecked")]
91 tlvs: alloc::vec::Vec<Tlv>,
92}
93
94impl DeliverSm {
95 #[allow(clippy::too_many_arguments)]
96 pub fn new(
97 service_type: ServiceType,
98 source_addr_ton: Ton,
99 source_addr_npi: Npi,
100 source_addr: COctetString<1, 21>,
101 dest_addr_ton: Ton,
102 dest_addr_npi: Npi,
103 destination_addr: COctetString<1, 21>,
104 esm_class: EsmClass,
105 protocol_id: u8,
106 priority_flag: PriorityFlag,
107 schedule_delivery_time: EmptyOrFullCOctetString<17>,
108 validity_period: EmptyOrFullCOctetString<17>,
109 registered_delivery: RegisteredDelivery,
110 replace_if_present_flag: ReplaceIfPresentFlag,
111 data_coding: DataCoding,
112 sm_default_msg_id: u8,
113 short_message: OctetString<0, 255>,
114 tlvs: alloc::vec::Vec<impl Into<MessageDeliveryRequestTlvValue>>,
115 ) -> Self {
116 let tlvs = tlvs.into_iter().map(Into::into).map(From::from).collect();
117
118 let sm_length = short_message.length() as u8;
119
120 let mut submit_sm = Self {
121 service_type,
122 source_addr_ton,
123 source_addr_npi,
124 source_addr,
125 dest_addr_ton,
126 dest_addr_npi,
127 destination_addr,
128 esm_class,
129 protocol_id,
130 priority_flag,
131 schedule_delivery_time,
132 validity_period,
133 registered_delivery,
134 replace_if_present_flag,
135 data_coding,
136 sm_default_msg_id,
137 sm_length,
138 short_message,
139 tlvs,
140 };
141
142 submit_sm.clear_short_message_if_message_payload_exists();
143
144 submit_sm
145 }
146
147 pub const fn sm_length(&self) -> u8 {
148 self.sm_length
149 }
150
151 pub fn short_message(&self) -> &OctetString<0, 255> {
152 &self.short_message
153 }
154
155 pub fn set_short_message(&mut self, short_message: OctetString<0, 255>) -> bool {
160 self.short_message = short_message;
161 self.sm_length = self.short_message.length() as u8;
162
163 !self.clear_short_message_if_message_payload_exists()
164 }
165
166 pub fn tlvs(&self) -> &[Tlv] {
167 &self.tlvs
168 }
169
170 pub fn set_tlvs(&mut self, tlvs: alloc::vec::Vec<impl Into<MessageDeliveryRequestTlvValue>>) {
171 self.tlvs = tlvs.into_iter().map(Into::into).map(From::from).collect();
172
173 self.clear_short_message_if_message_payload_exists();
174 }
175
176 pub fn clear_tlvs(&mut self) {
177 self.tlvs.clear();
178 }
179
180 pub fn push_tlv(&mut self, tlv: impl Into<MessageDeliveryRequestTlvValue>) {
181 self.tlvs.push(Tlv::from(tlv.into()));
182
183 self.clear_short_message_if_message_payload_exists();
184 }
185
186 fn clear_short_message_if_message_payload_exists(&mut self) -> bool {
189 let message_payload_exists = self
190 .tlvs
191 .iter()
192 .any(|value| matches!(value.tag(), TlvTag::MessagePayload));
193
194 if message_payload_exists {
195 self.short_message = OctetString::empty();
196 self.sm_length = 0;
197
198 return true;
199 };
200
201 false
202 }
203
204 pub fn builder() -> DeliverSmBuilder {
205 DeliverSmBuilder::new()
206 }
207}
208
209impl From<DeliverSm> for Pdu {
210 fn from(value: DeliverSm) -> Self {
211 Self::DeliverSm(value)
212 }
213}
214
215#[derive(Debug, Default)]
216pub struct DeliverSmBuilder {
217 inner: DeliverSm,
218}
219
220impl DeliverSmBuilder {
221 pub fn new() -> Self {
222 Self::default()
223 }
224
225 pub fn service_type(mut self, service_type: ServiceType) -> Self {
226 self.inner.service_type = service_type;
227 self
228 }
229
230 pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
231 self.inner.source_addr_ton = source_addr_ton;
232 self
233 }
234
235 pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
236 self.inner.source_addr_npi = source_addr_npi;
237 self
238 }
239
240 pub fn source_addr(mut self, source_addr: COctetString<1, 21>) -> Self {
241 self.inner.source_addr = source_addr;
242 self
243 }
244
245 pub fn dest_addr_ton(mut self, dest_addr_ton: Ton) -> Self {
246 self.inner.dest_addr_ton = dest_addr_ton;
247 self
248 }
249
250 pub fn dest_addr_npi(mut self, dest_addr_npi: Npi) -> Self {
251 self.inner.dest_addr_npi = dest_addr_npi;
252 self
253 }
254
255 pub fn destination_addr(mut self, destination_addr: COctetString<1, 21>) -> Self {
256 self.inner.destination_addr = destination_addr;
257 self
258 }
259
260 pub fn esm_class(mut self, esm_class: EsmClass) -> Self {
261 self.inner.esm_class = esm_class;
262 self
263 }
264
265 pub fn protocol_id(mut self, protocol_id: u8) -> Self {
266 self.inner.protocol_id = protocol_id;
267 self
268 }
269
270 pub fn priority_flag(mut self, priority_flag: PriorityFlag) -> Self {
271 self.inner.priority_flag = priority_flag;
272 self
273 }
274
275 pub fn schedule_delivery_time(
276 mut self,
277 schedule_delivery_time: EmptyOrFullCOctetString<17>,
278 ) -> Self {
279 self.inner.schedule_delivery_time = schedule_delivery_time;
280 self
281 }
282
283 pub fn validity_period(mut self, validity_period: EmptyOrFullCOctetString<17>) -> Self {
284 self.inner.validity_period = validity_period;
285 self
286 }
287
288 pub fn registered_delivery(mut self, registered_delivery: RegisteredDelivery) -> Self {
289 self.inner.registered_delivery = registered_delivery;
290 self
291 }
292
293 pub fn replace_if_present_flag(
294 mut self,
295 replace_if_present_flag: ReplaceIfPresentFlag,
296 ) -> Self {
297 self.inner.replace_if_present_flag = replace_if_present_flag;
298 self
299 }
300
301 pub fn data_coding(mut self, data_coding: DataCoding) -> Self {
302 self.inner.data_coding = data_coding;
303 self
304 }
305
306 pub fn sm_default_msg_id(mut self, sm_default_msg_id: u8) -> Self {
307 self.inner.sm_default_msg_id = sm_default_msg_id;
308 self
309 }
310
311 pub fn short_message(mut self, short_message: OctetString<0, 255>) -> Self {
312 self.inner.set_short_message(short_message);
313 self
314 }
315
316 pub fn tlvs(
317 mut self,
318 tlvs: alloc::vec::Vec<impl Into<MessageDeliveryRequestTlvValue>>,
319 ) -> Self {
320 self.inner.set_tlvs(tlvs);
321 self
322 }
323
324 pub fn clear_tlvs(mut self) -> Self {
325 self.inner.clear_tlvs();
326 self
327 }
328
329 pub fn push_tlv(mut self, tlv: impl Into<MessageDeliveryRequestTlvValue>) -> Self {
330 self.inner.push_tlv(tlv);
331 self
332 }
333
334 pub fn build(self) -> DeliverSm {
335 self.inner
336 }
337}
338
339#[cfg(test)]
340mod tests {
341 use std::str::FromStr;
342
343 use crate::{tests::TestInstance, types::owned::AnyOctetString};
344
345 use super::*;
346
347 impl TestInstance for DeliverSm {
348 fn instances() -> alloc::vec::Vec<Self> {
349 alloc::vec![
350 Self::default(),
351 Self::builder()
352 .source_addr_ton(Ton::International)
353 .source_addr_npi(Npi::Isdn)
354 .source_addr(COctetString::from_str("Source Address").unwrap())
355 .dest_addr_ton(Ton::International)
356 .dest_addr_npi(Npi::Isdn)
357 .destination_addr(COctetString::from_str("Destination Address").unwrap())
358 .schedule_delivery_time(EmptyOrFullCOctetString::empty())
359 .validity_period(EmptyOrFullCOctetString::empty())
360 .registered_delivery(RegisteredDelivery::default())
361 .replace_if_present_flag(ReplaceIfPresentFlag::Replace)
362 .short_message(OctetString::new(b"Short Message").unwrap())
363 .build(),
364 Self::builder()
365 .source_addr_ton(Ton::International)
366 .source_addr_npi(Npi::Isdn)
367 .source_addr(COctetString::from_str("Source Address").unwrap())
368 .dest_addr_ton(Ton::International)
369 .dest_addr_npi(Npi::Isdn)
370 .destination_addr(COctetString::from_str("Destination Address").unwrap())
371 .protocol_id(0)
372 .schedule_delivery_time(EmptyOrFullCOctetString::empty())
373 .validity_period(EmptyOrFullCOctetString::empty())
374 .registered_delivery(RegisteredDelivery::default())
375 .replace_if_present_flag(ReplaceIfPresentFlag::Replace)
376 .data_coding(DataCoding::default())
377 .sm_default_msg_id(0)
378 .short_message(OctetString::new(b"Short Message").unwrap())
379 .tlvs(alloc::vec![
380 MessageDeliveryRequestTlvValue::MessagePayload(MessagePayload::new(
381 AnyOctetString::new(b"Message Payload"),
382 )),
383 MessageDeliveryRequestTlvValue::MessagePayload(MessagePayload::new(
384 AnyOctetString::new(b"Message Payload 2"),
385 )),
386 MessageDeliveryRequestTlvValue::CallbackNumPresInd(
387 CallbackNumPresInd::new(
388 Presentation::NumberNotAvailable,
389 Screening::VerifiedAndPassed,
390 ),
391 ),
392 ])
393 .build(),
394 ]
395 }
396 }
397
398 #[test]
399 fn encode_decode() {
400 crate::tests::owned::encode_decode_with_length_test_instances::<DeliverSm>();
401 }
402
403 #[test]
404 fn short_message_length() {
405 let short_message = OctetString::new(b"Short Message").unwrap();
406
407 let submit_sm = DeliverSm::builder()
408 .short_message(short_message.clone())
409 .build();
410
411 assert_eq!(submit_sm.short_message(), &short_message);
412 assert_eq!(submit_sm.sm_length(), short_message.length() as u8);
413 }
414
415 #[test]
416 fn short_message_override() {
417 let short_message_1 = OctetString::new(b"Short Message 101").unwrap();
418 let short_message_2 = OctetString::new(b"Short Message 2").unwrap();
419
420 let submit_sm = DeliverSm::builder()
421 .short_message(short_message_1)
422 .short_message(short_message_2.clone())
423 .build();
424
425 assert_eq!(submit_sm.short_message(), &short_message_2);
426 assert_eq!(submit_sm.sm_length(), short_message_2.length() as u8);
427 }
428
429 #[test]
430 fn message_payload_suppresses_short_message() {
431 let short_message = OctetString::new(b"Short Message").unwrap();
432 let message_payload = MessagePayload::new(AnyOctetString::new(b"Message Payload"));
433
434 let deliver_sm = DeliverSm::builder()
436 .short_message(short_message.clone())
437 .push_tlv(MessageDeliveryRequestTlvValue::MessagePayload(
438 message_payload.clone(),
439 ))
440 .build();
441
442 assert_eq!(deliver_sm.short_message(), &OctetString::empty());
443 assert_eq!(deliver_sm.sm_length(), 0);
444
445 let submit_sm = DeliverSm::builder()
447 .short_message(short_message.clone())
448 .tlvs(alloc::vec![MessageDeliveryRequestTlvValue::MessagePayload(
449 message_payload.clone(),
450 )])
451 .build();
452
453 assert_eq!(submit_sm.short_message(), &OctetString::empty());
454 assert_eq!(submit_sm.sm_length(), 0);
455
456 let submit_sm = DeliverSm::builder()
459 .short_message(short_message.clone())
460 .push_tlv(MessageDeliveryRequestTlvValue::MessagePayload(
461 message_payload.clone(),
462 ))
463 .short_message(short_message.clone())
464 .build();
465
466 assert_eq!(submit_sm.short_message(), &OctetString::empty());
467 assert_eq!(submit_sm.sm_length(), 0);
468
469 let submit_sm = DeliverSm::builder()
471 .short_message(short_message.clone())
472 .tlvs(alloc::vec![MessageDeliveryRequestTlvValue::MessagePayload(
473 message_payload.clone(),
474 )])
475 .short_message(short_message.clone())
476 .build();
477
478 assert_eq!(submit_sm.short_message(), &OctetString::empty());
479 assert_eq!(submit_sm.sm_length(), 0);
480
481 let submit_sm = DeliverSm::builder()
483 .push_tlv(MessageDeliveryRequestTlvValue::MessagePayload(
484 message_payload.clone(),
485 ))
486 .clear_tlvs()
487 .short_message(short_message.clone())
488 .build();
489
490 assert_eq!(submit_sm.short_message(), &short_message);
491 assert_eq!(submit_sm.sm_length(), short_message.length() as u8);
492 }
493}