1use rusmpp_macros::Rusmpp;
2
3use crate::{
4 encode::Length,
5 pdus::borrowed::Pdu,
6 tlvs::{
7 TlvTag,
8 borrowed::{MessageDeliveryRequestTlvValue, Tlv},
9 },
10 types::borrowed::{COctetString, EmptyOrFullCOctetString, OctetString},
11 values::{borrowed::*, *},
12};
13
14#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
17#[rusmpp(decode = borrowed, test = skip)]
18#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
19#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
20pub struct DeliverSm<'a, const N: usize> {
21 pub service_type: ServiceType<'a>,
31 pub source_addr_ton: Ton,
33 pub source_addr_npi: Npi,
35 pub source_addr: COctetString<'a, 1, 21>,
37 pub dest_addr_ton: Ton,
39 pub dest_addr_npi: Npi,
41 pub destination_addr: COctetString<'a, 1, 21>,
47 pub esm_class: EsmClass,
50 pub protocol_id: u8,
53 pub priority_flag: PriorityFlag,
55 pub schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
60 pub validity_period: EmptyOrFullCOctetString<'a, 17>,
67 pub registered_delivery: RegisteredDelivery,
70 pub replace_if_present_flag: ReplaceIfPresentFlag,
72 pub data_coding: DataCoding,
74 pub sm_default_msg_id: u8,
77 sm_length: u8,
79 #[rusmpp(length = sm_length)]
87 short_message: OctetString<'a, 0, 255>,
88 #[rusmpp(length = "unchecked")]
90 #[cfg_attr(feature = "arbitrary", arbitrary(default))]
91 tlvs: heapless::vec::Vec<Tlv<'a>, N>,
92}
93
94impl<'a, const N: usize> DeliverSm<'a, N> {
95 #[allow(clippy::too_many_arguments)]
96 pub fn new(
97 service_type: ServiceType<'a>,
98 source_addr_ton: Ton,
99 source_addr_npi: Npi,
100 source_addr: COctetString<'a, 1, 21>,
101 dest_addr_ton: Ton,
102 dest_addr_npi: Npi,
103 destination_addr: COctetString<'a, 1, 21>,
104 esm_class: EsmClass,
105 protocol_id: u8,
106 priority_flag: PriorityFlag,
107 schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
108 validity_period: EmptyOrFullCOctetString<'a, 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<'a, 0, 255>,
114 tlvs: heapless::vec::Vec<impl Into<MessageDeliveryRequestTlvValue<'a>>, N>,
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<'a, 0, 255> {
152 &self.short_message
153 }
154
155 pub fn set_short_message(&mut self, short_message: OctetString<'a, 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(
171 &mut self,
172 tlvs: heapless::vec::Vec<impl Into<MessageDeliveryRequestTlvValue<'a>>, N>,
173 ) {
174 self.tlvs = tlvs.into_iter().map(Into::into).map(From::from).collect();
175
176 self.clear_short_message_if_message_payload_exists();
177 }
178
179 pub fn clear_tlvs(&mut self) {
180 self.tlvs.clear();
181 }
182
183 pub fn push_tlv(
184 &mut self,
185 tlv: impl Into<MessageDeliveryRequestTlvValue<'a>>,
186 ) -> Result<(), Tlv<'a>> {
187 self.tlvs.push(Tlv::from(tlv.into()))?;
188
189 self.clear_short_message_if_message_payload_exists();
190
191 Ok(())
192 }
193
194 fn clear_short_message_if_message_payload_exists(&mut self) -> bool {
197 let message_payload_exists = self
198 .tlvs
199 .iter()
200 .any(|value| matches!(value.tag(), TlvTag::MessagePayload));
201
202 if message_payload_exists {
203 self.short_message = OctetString::empty();
204 self.sm_length = 0;
205
206 return true;
207 };
208
209 false
210 }
211
212 pub fn builder() -> DeliverSmBuilder<'a, N> {
213 DeliverSmBuilder::new()
214 }
215}
216
217impl<'a, const N: usize> From<DeliverSm<'a, N>> for Pdu<'a, N> {
218 fn from(value: DeliverSm<'a, N>) -> Self {
219 Self::DeliverSm(value)
220 }
221}
222
223#[derive(Debug, Default)]
224pub struct DeliverSmBuilder<'a, const N: usize> {
225 inner: DeliverSm<'a, N>,
226}
227
228impl<'a, const N: usize> DeliverSmBuilder<'a, N> {
229 pub fn new() -> Self {
230 Self::default()
231 }
232
233 pub fn service_type(mut self, service_type: ServiceType<'a>) -> Self {
234 self.inner.service_type = service_type;
235 self
236 }
237
238 pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
239 self.inner.source_addr_ton = source_addr_ton;
240 self
241 }
242
243 pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
244 self.inner.source_addr_npi = source_addr_npi;
245 self
246 }
247
248 pub fn source_addr(mut self, source_addr: COctetString<'a, 1, 21>) -> Self {
249 self.inner.source_addr = source_addr;
250 self
251 }
252
253 pub fn dest_addr_ton(mut self, dest_addr_ton: Ton) -> Self {
254 self.inner.dest_addr_ton = dest_addr_ton;
255 self
256 }
257
258 pub fn dest_addr_npi(mut self, dest_addr_npi: Npi) -> Self {
259 self.inner.dest_addr_npi = dest_addr_npi;
260 self
261 }
262
263 pub fn destination_addr(mut self, destination_addr: COctetString<'a, 1, 21>) -> Self {
264 self.inner.destination_addr = destination_addr;
265 self
266 }
267
268 pub fn esm_class(mut self, esm_class: EsmClass) -> Self {
269 self.inner.esm_class = esm_class;
270 self
271 }
272
273 pub fn protocol_id(mut self, protocol_id: u8) -> Self {
274 self.inner.protocol_id = protocol_id;
275 self
276 }
277
278 pub fn priority_flag(mut self, priority_flag: PriorityFlag) -> Self {
279 self.inner.priority_flag = priority_flag;
280 self
281 }
282
283 pub fn schedule_delivery_time(
284 mut self,
285 schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
286 ) -> Self {
287 self.inner.schedule_delivery_time = schedule_delivery_time;
288 self
289 }
290
291 pub fn validity_period(mut self, validity_period: EmptyOrFullCOctetString<'a, 17>) -> Self {
292 self.inner.validity_period = validity_period;
293 self
294 }
295
296 pub fn registered_delivery(mut self, registered_delivery: RegisteredDelivery) -> Self {
297 self.inner.registered_delivery = registered_delivery;
298 self
299 }
300
301 pub fn replace_if_present_flag(
302 mut self,
303 replace_if_present_flag: ReplaceIfPresentFlag,
304 ) -> Self {
305 self.inner.replace_if_present_flag = replace_if_present_flag;
306 self
307 }
308
309 pub fn data_coding(mut self, data_coding: DataCoding) -> Self {
310 self.inner.data_coding = data_coding;
311 self
312 }
313
314 pub fn sm_default_msg_id(mut self, sm_default_msg_id: u8) -> Self {
315 self.inner.sm_default_msg_id = sm_default_msg_id;
316 self
317 }
318
319 pub fn short_message(mut self, short_message: OctetString<'a, 0, 255>) -> Self {
320 self.inner.set_short_message(short_message);
321 self
322 }
323
324 pub fn tlvs(
325 mut self,
326 tlvs: heapless::vec::Vec<impl Into<MessageDeliveryRequestTlvValue<'a>>, N>,
327 ) -> Self {
328 self.inner.set_tlvs(tlvs);
329 self
330 }
331
332 pub fn clear_tlvs(mut self) -> Self {
333 self.inner.clear_tlvs();
334 self
335 }
336
337 pub fn push_tlv(
338 mut self,
339 tlv: impl Into<MessageDeliveryRequestTlvValue<'a>>,
340 ) -> Result<Self, Tlv<'a>> {
341 self.inner.push_tlv(tlv)?;
342 Ok(self)
343 }
344
345 pub fn build(self) -> DeliverSm<'a, N> {
346 self.inner
347 }
348}
349
350#[cfg(test)]
351mod tests {
352 use crate::{tests::TestInstance, types::borrowed::AnyOctetString};
353
354 use super::*;
355
356 impl<const N: usize> TestInstance for DeliverSm<'_, N> {
357 fn instances() -> alloc::vec::Vec<Self> {
358 alloc::vec![
359 Self::default(),
360 Self::builder()
361 .source_addr_ton(Ton::International)
362 .source_addr_npi(Npi::Isdn)
363 .source_addr(COctetString::new(b"Source Address\0").unwrap())
364 .dest_addr_ton(Ton::International)
365 .dest_addr_npi(Npi::Isdn)
366 .destination_addr(COctetString::new(b"Destination Address\0").unwrap())
367 .schedule_delivery_time(EmptyOrFullCOctetString::empty())
368 .validity_period(EmptyOrFullCOctetString::empty())
369 .registered_delivery(RegisteredDelivery::default())
370 .replace_if_present_flag(ReplaceIfPresentFlag::Replace)
371 .short_message(OctetString::new(b"Short Message").unwrap())
372 .build(),
373 Self::builder()
374 .source_addr_ton(Ton::International)
375 .source_addr_npi(Npi::Isdn)
376 .source_addr(COctetString::new(b"Source Address\0").unwrap())
377 .dest_addr_ton(Ton::International)
378 .dest_addr_npi(Npi::Isdn)
379 .destination_addr(COctetString::new(b"Destination Address\0").unwrap())
380 .protocol_id(0)
381 .schedule_delivery_time(EmptyOrFullCOctetString::empty())
382 .validity_period(EmptyOrFullCOctetString::empty())
383 .registered_delivery(RegisteredDelivery::default())
384 .replace_if_present_flag(ReplaceIfPresentFlag::Replace)
385 .data_coding(DataCoding::default())
386 .sm_default_msg_id(0)
387 .short_message(OctetString::new(b"Short Message").unwrap())
388 .tlvs(
389 [
390 MessageDeliveryRequestTlvValue::MessagePayload(MessagePayload::new(
391 AnyOctetString::new(b"Message Payload"),
392 )),
393 MessageDeliveryRequestTlvValue::MessagePayload(MessagePayload::new(
394 AnyOctetString::new(b"Message Payload 2"),
395 )),
396 MessageDeliveryRequestTlvValue::CallbackNumPresInd(
397 CallbackNumPresInd::new(
398 Presentation::NumberNotAvailable,
399 Screening::VerifiedAndPassed,
400 ),
401 ),
402 ]
403 .into()
404 )
405 .build(),
406 ]
407 }
408 }
409
410 #[test]
411 fn encode_decode() {
412 crate::tests::borrowed::encode_decode_with_length_test_instances::<DeliverSm<'static, 16>>(
413 );
414 }
415
416 #[test]
417 fn short_message_length() {
418 let short_message = OctetString::new(b"Short Message").unwrap();
419
420 let submit_sm = DeliverSm::<'static, 16>::builder()
421 .short_message(short_message.clone())
422 .build();
423
424 assert_eq!(submit_sm.short_message(), &short_message);
425 assert_eq!(submit_sm.sm_length(), short_message.length() as u8);
426 }
427
428 #[test]
429 fn short_message_override() {
430 let short_message_1 = OctetString::new(b"Short Message 101").unwrap();
431 let short_message_2 = OctetString::new(b"Short Message 2").unwrap();
432
433 let submit_sm = DeliverSm::<'static, 16>::builder()
434 .short_message(short_message_1)
435 .short_message(short_message_2.clone())
436 .build();
437
438 assert_eq!(submit_sm.short_message(), &short_message_2);
439 assert_eq!(submit_sm.sm_length(), short_message_2.length() as u8);
440 }
441
442 #[test]
443 fn message_payload_suppresses_short_message() {
444 let short_message = OctetString::new(b"Short Message").unwrap();
445 let message_payload = MessagePayload::new(AnyOctetString::new(b"Message Payload"));
446
447 let deliver_sm = DeliverSm::<'static, 16>::builder()
449 .short_message(short_message.clone())
450 .push_tlv(MessageDeliveryRequestTlvValue::MessagePayload(
451 message_payload.clone(),
452 ))
453 .unwrap()
454 .build();
455
456 assert_eq!(deliver_sm.short_message(), &OctetString::empty());
457 assert_eq!(deliver_sm.sm_length(), 0);
458
459 let submit_sm = DeliverSm::<'static, 16>::builder()
461 .short_message(short_message.clone())
462 .tlvs(
463 [MessageDeliveryRequestTlvValue::MessagePayload(
464 message_payload.clone(),
465 )]
466 .into(),
467 )
468 .build();
469
470 assert_eq!(submit_sm.short_message(), &OctetString::empty());
471 assert_eq!(submit_sm.sm_length(), 0);
472
473 let submit_sm = DeliverSm::<'static, 16>::builder()
476 .short_message(short_message.clone())
477 .push_tlv(MessageDeliveryRequestTlvValue::MessagePayload(
478 message_payload.clone(),
479 ))
480 .unwrap()
481 .short_message(short_message.clone())
482 .build();
483
484 assert_eq!(submit_sm.short_message(), &OctetString::empty());
485 assert_eq!(submit_sm.sm_length(), 0);
486
487 let submit_sm = DeliverSm::<'static, 16>::builder()
489 .short_message(short_message.clone())
490 .tlvs(
491 [MessageDeliveryRequestTlvValue::MessagePayload(
492 message_payload.clone(),
493 )]
494 .into(),
495 )
496 .short_message(short_message.clone())
497 .build();
498
499 assert_eq!(submit_sm.short_message(), &OctetString::empty());
500 assert_eq!(submit_sm.sm_length(), 0);
501
502 let submit_sm = DeliverSm::<'static, 16>::builder()
504 .push_tlv(MessageDeliveryRequestTlvValue::MessagePayload(
505 message_payload.clone(),
506 ))
507 .unwrap()
508 .clear_tlvs()
509 .short_message(short_message.clone())
510 .build();
511
512 assert_eq!(submit_sm.short_message(), &short_message);
513 assert_eq!(submit_sm.sm_length(), short_message.length() as u8);
514 }
515}