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