1use rusmpp_macros::Rusmpp;
2
3use crate::{
4 encode::Length,
5 pdus::borrowed::Pdu,
6 tlvs::borrowed::{MessageDeliveryRequestTlvValue, Tlv},
7 types::borrowed::{COctetString, EmptyOrFullCOctetString, OctetString},
8 values::{borrowed::*, *},
9};
10
11#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
14#[rusmpp(decode = borrowed, test = skip)]
15#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
16#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
17pub struct DeliverSm<'a, const N: usize> {
18 pub service_type: ServiceType<'a>,
28 pub source_addr_ton: Ton,
30 pub source_addr_npi: Npi,
32 pub source_addr: COctetString<'a, 1, 21>,
34 pub dest_addr_ton: Ton,
36 pub dest_addr_npi: Npi,
38 pub destination_addr: COctetString<'a, 1, 21>,
44 pub esm_class: EsmClass,
47 pub protocol_id: u8,
50 pub priority_flag: PriorityFlag,
52 pub schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
57 pub validity_period: EmptyOrFullCOctetString<'a, 17>,
64 pub registered_delivery: RegisteredDelivery,
67 pub replace_if_present_flag: ReplaceIfPresentFlag,
69 pub data_coding: DataCoding,
71 pub sm_default_msg_id: u8,
74 sm_length: u8,
76 #[rusmpp(length = sm_length)]
84 short_message: OctetString<'a, 0, 255>,
85 #[rusmpp(length = "unchecked")]
87 #[cfg_attr(feature = "arbitrary", arbitrary(default))]
88 tlvs: heapless::vec::Vec<Tlv<'a>, N>,
89}
90
91impl<'a, const N: usize> DeliverSm<'a, N> {
92 #[allow(clippy::too_many_arguments)]
93 pub fn new(
94 service_type: ServiceType<'a>,
95 source_addr_ton: Ton,
96 source_addr_npi: Npi,
97 source_addr: COctetString<'a, 1, 21>,
98 dest_addr_ton: Ton,
99 dest_addr_npi: Npi,
100 destination_addr: COctetString<'a, 1, 21>,
101 esm_class: EsmClass,
102 protocol_id: u8,
103 priority_flag: PriorityFlag,
104 schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
105 validity_period: EmptyOrFullCOctetString<'a, 17>,
106 registered_delivery: RegisteredDelivery,
107 replace_if_present_flag: ReplaceIfPresentFlag,
108 data_coding: DataCoding,
109 sm_default_msg_id: u8,
110 short_message: OctetString<'a, 0, 255>,
111 tlvs: heapless::vec::Vec<MessageDeliveryRequestTlvValue<'a>, N>,
112 ) -> Self {
113 let tlvs = tlvs.into_iter().map(From::from).collect();
114
115 let sm_length = short_message.length() as u8;
116
117 Self {
118 service_type,
119 source_addr_ton,
120 source_addr_npi,
121 source_addr,
122 dest_addr_ton,
123 dest_addr_npi,
124 destination_addr,
125 esm_class,
126 protocol_id,
127 priority_flag,
128 schedule_delivery_time,
129 validity_period,
130 registered_delivery,
131 replace_if_present_flag,
132 data_coding,
133 sm_default_msg_id,
134 sm_length,
135 short_message,
136 tlvs,
137 }
138 }
139
140 pub const fn sm_length(&self) -> u8 {
141 self.sm_length
142 }
143
144 pub fn short_message(&self) -> &OctetString<'a, 0, 255> {
145 &self.short_message
146 }
147
148 pub fn set_short_message(&mut self, short_message: OctetString<'a, 0, 255>) {
155 self.short_message = short_message;
156 self.sm_length = self.short_message.length() as u8;
157 }
158
159 pub fn tlvs(&'_ self) -> &'_ [Tlv<'_>] {
160 &self.tlvs
161 }
162
163 pub fn set_tlvs(&mut self, tlvs: heapless::vec::Vec<MessageDeliveryRequestTlvValue<'a>, N>) {
164 self.tlvs = tlvs.into_iter().map(From::from).collect();
165 }
166
167 pub fn clear_tlvs(&mut self) {
168 self.tlvs.clear();
169 }
170
171 pub fn push_tlv(
172 &mut self,
173 tlv: impl Into<MessageDeliveryRequestTlvValue<'a>>,
174 ) -> Result<(), Tlv<'a>> {
175 self.tlvs.push(Tlv::from(tlv.into()))?;
176 Ok(())
177 }
178
179 pub fn builder() -> DeliverSmBuilder<'a, N> {
180 DeliverSmBuilder::new()
181 }
182}
183
184impl<'a, const N: usize> From<DeliverSm<'a, N>> for Pdu<'a, N> {
185 fn from(value: DeliverSm<'a, N>) -> Self {
186 Self::DeliverSm(value)
187 }
188}
189
190#[derive(Debug, Default)]
191pub struct DeliverSmBuilder<'a, const N: usize> {
192 inner: DeliverSm<'a, N>,
193}
194
195impl<'a, const N: usize> DeliverSmBuilder<'a, N> {
196 pub fn new() -> Self {
197 Self::default()
198 }
199
200 pub fn service_type(mut self, service_type: ServiceType<'a>) -> Self {
201 self.inner.service_type = service_type;
202 self
203 }
204
205 pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
206 self.inner.source_addr_ton = source_addr_ton;
207 self
208 }
209
210 pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
211 self.inner.source_addr_npi = source_addr_npi;
212 self
213 }
214
215 pub fn source_addr(mut self, source_addr: COctetString<'a, 1, 21>) -> Self {
216 self.inner.source_addr = source_addr;
217 self
218 }
219
220 pub fn dest_addr_ton(mut self, dest_addr_ton: Ton) -> Self {
221 self.inner.dest_addr_ton = dest_addr_ton;
222 self
223 }
224
225 pub fn dest_addr_npi(mut self, dest_addr_npi: Npi) -> Self {
226 self.inner.dest_addr_npi = dest_addr_npi;
227 self
228 }
229
230 pub fn destination_addr(mut self, destination_addr: COctetString<'a, 1, 21>) -> Self {
231 self.inner.destination_addr = destination_addr;
232 self
233 }
234
235 pub fn esm_class(mut self, esm_class: EsmClass) -> Self {
236 self.inner.esm_class = esm_class;
237 self
238 }
239
240 pub fn protocol_id(mut self, protocol_id: u8) -> Self {
241 self.inner.protocol_id = protocol_id;
242 self
243 }
244
245 pub fn priority_flag(mut self, priority_flag: PriorityFlag) -> Self {
246 self.inner.priority_flag = priority_flag;
247 self
248 }
249
250 pub fn schedule_delivery_time(
251 mut self,
252 schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
253 ) -> Self {
254 self.inner.schedule_delivery_time = schedule_delivery_time;
255 self
256 }
257
258 pub fn validity_period(mut self, validity_period: EmptyOrFullCOctetString<'a, 17>) -> Self {
259 self.inner.validity_period = validity_period;
260 self
261 }
262
263 pub fn registered_delivery(mut self, registered_delivery: RegisteredDelivery) -> Self {
264 self.inner.registered_delivery = registered_delivery;
265 self
266 }
267
268 pub fn replace_if_present_flag(
269 mut self,
270 replace_if_present_flag: ReplaceIfPresentFlag,
271 ) -> Self {
272 self.inner.replace_if_present_flag = replace_if_present_flag;
273 self
274 }
275
276 pub fn data_coding(mut self, data_coding: DataCoding) -> Self {
277 self.inner.data_coding = data_coding;
278 self
279 }
280
281 pub fn sm_default_msg_id(mut self, sm_default_msg_id: u8) -> Self {
282 self.inner.sm_default_msg_id = sm_default_msg_id;
283 self
284 }
285
286 pub fn short_message(mut self, short_message: OctetString<'a, 0, 255>) -> Self {
287 self.inner.set_short_message(short_message);
288 self
289 }
290
291 pub fn tlvs(mut self, tlvs: heapless::vec::Vec<MessageDeliveryRequestTlvValue<'a>, N>) -> Self {
292 self.inner.set_tlvs(tlvs);
293 self
294 }
295
296 pub fn clear_tlvs(mut self) -> Self {
297 self.inner.clear_tlvs();
298 self
299 }
300
301 pub fn push_tlv(
302 mut self,
303 tlv: impl Into<MessageDeliveryRequestTlvValue<'a>>,
304 ) -> Result<Self, Tlv<'a>> {
305 self.inner.push_tlv(tlv)?;
306 Ok(self)
307 }
308
309 pub fn build(self) -> DeliverSm<'a, N> {
310 self.inner
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use crate::{tests::TestInstance, types::borrowed::AnyOctetString};
317
318 use super::*;
319
320 impl<const N: usize> TestInstance for DeliverSm<'_, N> {
321 fn instances() -> alloc::vec::Vec<Self> {
322 alloc::vec![
323 Self::default(),
324 Self::builder()
325 .source_addr_ton(Ton::International)
326 .source_addr_npi(Npi::Isdn)
327 .source_addr(COctetString::new(b"Source Address\0").unwrap())
328 .dest_addr_ton(Ton::International)
329 .dest_addr_npi(Npi::Isdn)
330 .destination_addr(COctetString::new(b"Destination Address\0").unwrap())
331 .schedule_delivery_time(EmptyOrFullCOctetString::empty())
332 .validity_period(EmptyOrFullCOctetString::empty())
333 .registered_delivery(RegisteredDelivery::default())
334 .replace_if_present_flag(ReplaceIfPresentFlag::Replace)
335 .short_message(OctetString::new(b"Short Message").unwrap())
336 .build(),
337 Self::builder()
338 .source_addr_ton(Ton::International)
339 .source_addr_npi(Npi::Isdn)
340 .source_addr(COctetString::new(b"Source Address\0").unwrap())
341 .dest_addr_ton(Ton::International)
342 .dest_addr_npi(Npi::Isdn)
343 .destination_addr(COctetString::new(b"Destination Address\0").unwrap())
344 .protocol_id(0)
345 .schedule_delivery_time(EmptyOrFullCOctetString::empty())
346 .validity_period(EmptyOrFullCOctetString::empty())
347 .registered_delivery(RegisteredDelivery::default())
348 .replace_if_present_flag(ReplaceIfPresentFlag::Replace)
349 .data_coding(DataCoding::default())
350 .sm_default_msg_id(0)
351 .short_message(OctetString::new(b"Short Message").unwrap())
352 .tlvs(
353 [
354 MessageDeliveryRequestTlvValue::MessagePayload(MessagePayload::new(
355 AnyOctetString::new(b"Message Payload"),
356 )),
357 MessageDeliveryRequestTlvValue::MessagePayload(MessagePayload::new(
358 AnyOctetString::new(b"Message Payload 2"),
359 )),
360 MessageDeliveryRequestTlvValue::CallbackNumPresInd(
361 CallbackNumPresInd::new(
362 Presentation::NumberNotAvailable,
363 Screening::VerifiedAndPassed,
364 ),
365 ),
366 ]
367 .into()
368 )
369 .build(),
370 ]
371 }
372 }
373
374 #[test]
375 fn encode_decode() {
376 crate::tests::borrowed::encode_decode_with_length_test_instances::<DeliverSm<'static, 16>>(
377 );
378 }
379
380 #[test]
381 fn short_message_length() {
382 let short_message = OctetString::new(b"Short Message").unwrap();
383
384 let submit_sm = DeliverSm::<'static, 16>::builder()
385 .short_message(short_message.clone())
386 .build();
387
388 assert_eq!(submit_sm.short_message(), &short_message);
389 assert_eq!(submit_sm.sm_length(), short_message.length() as u8);
390 }
391}