rusmpp_core/pdus/borrowed/
replace_sm.rs1use rusmpp_macros::Rusmpp;
2
3use crate::{
4 encode::Length,
5 pdus::borrowed::Pdu,
6 tlvs::borrowed::{Tlv, TlvValue},
7 types::borrowed::{COctetString, EmptyOrFullCOctetString, OctetString},
8 values::{borrowed::*, *},
9};
10
11#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
18#[rusmpp(decode = borrowed, test = skip)]
19#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
20#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
21pub struct ReplaceSm<'a> {
22 pub message_id: COctetString<'a, 1, 65>,
29 pub source_addr_ton: Ton,
35 pub source_addr_npi: Npi,
40 pub source_addr: COctetString<'a, 1, 21>,
43 pub schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
47 pub validity_period: EmptyOrFullCOctetString<'a, 17>,
53 pub registered_delivery: RegisteredDelivery,
57 pub sm_default_msg_id: u8,
63 sm_length: u8,
65 #[rusmpp(length = sm_length)]
75 short_message: OctetString<'a, 0, 255>,
76 #[rusmpp(length = "checked")]
78 message_payload: Option<Tlv<'a>>,
79}
80
81impl<'a> ReplaceSm<'a> {
82 #[allow(clippy::too_many_arguments)]
83 pub fn new(
84 message_id: COctetString<'a, 1, 65>,
85 source_addr_ton: Ton,
86 source_addr_npi: Npi,
87 source_addr: COctetString<'a, 1, 21>,
88 schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
89 validity_period: EmptyOrFullCOctetString<'a, 17>,
90 registered_delivery: RegisteredDelivery,
91 sm_default_msg_id: u8,
92 short_message: OctetString<'a, 0, 255>,
93 message_payload: Option<MessagePayload<'a>>,
94 ) -> Self {
95 let message_payload = message_payload
96 .map(TlvValue::MessagePayload)
97 .map(From::from);
98
99 let sm_length = short_message.length() as u8;
100
101 let mut replace_sm = Self {
102 message_id,
103 source_addr_ton,
104 source_addr_npi,
105 source_addr,
106 schedule_delivery_time,
107 validity_period,
108 registered_delivery,
109 sm_default_msg_id,
110 sm_length,
111 short_message,
112 message_payload,
113 };
114
115 replace_sm.clear_short_message_if_message_payload_exists();
116
117 replace_sm
118 }
119
120 pub const fn sm_length(&self) -> u8 {
121 self.sm_length
122 }
123
124 pub fn short_message(&'_ self) -> &'_ OctetString<'_, 0, 255> {
125 &self.short_message
126 }
127
128 pub fn set_short_message(&mut self, short_message: OctetString<'a, 0, 255>) -> bool {
133 self.sm_length = short_message.length() as u8;
134 self.short_message = short_message;
135
136 !self.clear_short_message_if_message_payload_exists()
137 }
138
139 pub const fn message_payload_tlv(&'_ self) -> Option<&'_ Tlv<'_>> {
140 self.message_payload.as_ref()
141 }
142
143 pub fn message_payload(&'_ self) -> Option<&'_ MessagePayload<'_>> {
144 self.message_payload_tlv()
145 .and_then(|tlv| match tlv.value() {
146 Some(TlvValue::MessagePayload(value)) => Some(value),
147 _ => None,
148 })
149 }
150
151 pub fn set_message_payload(&mut self, message_payload: Option<MessagePayload<'a>>) {
154 self.message_payload = message_payload
155 .map(TlvValue::MessagePayload)
156 .map(From::from);
157
158 self.clear_short_message_if_message_payload_exists();
159 }
160
161 fn clear_short_message_if_message_payload_exists(&mut self) -> bool {
164 if self.message_payload.is_some() {
165 self.short_message = OctetString::empty();
166 self.sm_length = 0;
167
168 return true;
169 };
170
171 false
172 }
173
174 pub fn builder() -> ReplaceSmBuilder<'a> {
175 ReplaceSmBuilder::new()
176 }
177}
178
179impl<'a, const N: usize> From<ReplaceSm<'a>> for Pdu<'a, N> {
180 fn from(value: ReplaceSm<'a>) -> Self {
181 Self::ReplaceSm(value)
182 }
183}
184
185#[derive(Debug, Default)]
186pub struct ReplaceSmBuilder<'a> {
187 inner: ReplaceSm<'a>,
188}
189
190impl<'a> ReplaceSmBuilder<'a> {
191 pub fn new() -> Self {
192 Self::default()
193 }
194
195 pub fn message_id(mut self, message_id: COctetString<'a, 1, 65>) -> Self {
196 self.inner.message_id = message_id;
197 self
198 }
199
200 pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
201 self.inner.source_addr_ton = source_addr_ton;
202 self
203 }
204
205 pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
206 self.inner.source_addr_npi = source_addr_npi;
207 self
208 }
209
210 pub fn source_addr(mut self, source_addr: COctetString<'a, 1, 21>) -> Self {
211 self.inner.source_addr = source_addr;
212 self
213 }
214
215 pub fn schedule_delivery_time(
216 mut self,
217 schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
218 ) -> Self {
219 self.inner.schedule_delivery_time = schedule_delivery_time;
220 self
221 }
222
223 pub fn validity_period(mut self, validity_period: EmptyOrFullCOctetString<'a, 17>) -> Self {
224 self.inner.validity_period = validity_period;
225 self
226 }
227
228 pub fn registered_delivery(mut self, registered_delivery: RegisteredDelivery) -> Self {
229 self.inner.registered_delivery = registered_delivery;
230 self
231 }
232
233 pub fn sm_default_msg_id(mut self, sm_default_msg_id: u8) -> Self {
234 self.inner.sm_default_msg_id = sm_default_msg_id;
235 self
236 }
237
238 pub fn short_message(mut self, short_message: OctetString<'a, 0, 255>) -> Self {
239 self.inner.set_short_message(short_message);
240 self
241 }
242
243 pub fn message_payload(mut self, message_payload: Option<MessagePayload<'a>>) -> Self {
244 self.inner.set_message_payload(message_payload);
245 self
246 }
247
248 pub fn build(self) -> ReplaceSm<'a> {
249 self.inner
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use crate::{tests::TestInstance, types::borrowed::AnyOctetString};
256
257 use super::*;
258
259 impl TestInstance for ReplaceSm<'_> {
260 fn instances() -> alloc::vec::Vec<Self> {
261 alloc::vec![
262 Self::default(),
263 Self::builder()
264 .message_id(COctetString::new(b"123456789012345678901234\0").unwrap())
265 .source_addr_ton(Ton::International)
266 .source_addr_npi(Npi::Isdn)
267 .source_addr(COctetString::new(b"Source Addr\0").unwrap())
268 .schedule_delivery_time(
269 EmptyOrFullCOctetString::new(b"2023-10-01T12:00\0").unwrap(),
270 )
271 .validity_period(EmptyOrFullCOctetString::new(b"2023-10-01T12:00\0").unwrap())
272 .registered_delivery(RegisteredDelivery::default())
273 .sm_default_msg_id(0)
274 .short_message(OctetString::new(b"Short Message").unwrap())
275 .build(),
276 Self::builder()
277 .message_id(COctetString::new(b"123456789012345678901234\0").unwrap())
278 .source_addr_ton(Ton::International)
279 .source_addr_npi(Npi::Isdn)
280 .source_addr(COctetString::new(b"Source Addr\0").unwrap())
281 .schedule_delivery_time(
282 EmptyOrFullCOctetString::new(b"2023-10-01T12:00\0").unwrap(),
283 )
284 .validity_period(EmptyOrFullCOctetString::new(b"2023-10-01T12:00\0").unwrap())
285 .registered_delivery(RegisteredDelivery::default())
286 .sm_default_msg_id(0)
287 .message_payload(Some(MessagePayload::new(AnyOctetString::new(
288 b"Message Payload",
289 ))))
290 .build(),
291 Self::builder()
292 .validity_period(EmptyOrFullCOctetString::new(b"2023-10-01T12:00\0").unwrap())
293 .short_message(OctetString::new(b"Short Message").unwrap())
294 .message_payload(Some(MessagePayload::new(AnyOctetString::new(
295 b"Message Payload",
296 ))))
297 .build(),
298 ]
299 }
300 }
301
302 #[test]
303 fn encode_decode() {
304 crate::tests::borrowed::encode_decode_with_length_test_instances::<ReplaceSm>();
305 }
306
307 #[test]
308 fn short_message_length() {
309 let short_message = OctetString::new(b"Short Message").unwrap();
310
311 let submit_sm = ReplaceSm::builder()
312 .short_message(short_message.clone())
313 .build();
314
315 assert_eq!(submit_sm.short_message(), &short_message);
316 assert_eq!(submit_sm.sm_length(), short_message.length() as u8);
317 }
318
319 #[test]
320 fn short_message_override() {
321 let short_message_1 = OctetString::new(b"Short Message 101").unwrap();
322 let short_message_2 = OctetString::new(b"Short Message 2").unwrap();
323
324 let submit_sm = ReplaceSm::builder()
325 .short_message(short_message_1)
326 .short_message(short_message_2.clone())
327 .build();
328
329 assert_eq!(submit_sm.short_message(), &short_message_2);
330 assert_eq!(submit_sm.sm_length(), short_message_2.length() as u8);
331 }
332
333 #[test]
334 fn message_payload_suppresses_short_message() {
335 let short_message = OctetString::new(b"Short Message").unwrap();
336 let message_payload = MessagePayload::new(AnyOctetString::new(b"Message Payload"));
337
338 let replace_sm = ReplaceSm::builder()
340 .short_message(short_message.clone())
341 .message_payload(Some(message_payload.clone()))
342 .build();
343
344 assert_eq!(replace_sm.short_message(), &OctetString::empty());
345 assert_eq!(replace_sm.sm_length(), 0);
346
347 let submit_sm = ReplaceSm::builder()
349 .short_message(short_message.clone())
350 .message_payload(Some(message_payload.clone()))
351 .short_message(short_message.clone())
352 .build();
353
354 assert_eq!(submit_sm.short_message(), &OctetString::empty());
355 assert_eq!(submit_sm.sm_length(), 0);
356
357 let submit_sm = ReplaceSm::builder()
359 .message_payload(Some(message_payload.clone()))
360 .message_payload(None)
361 .short_message(short_message.clone())
362 .build();
363
364 assert_eq!(submit_sm.short_message(), &short_message);
365 assert_eq!(submit_sm.sm_length(), short_message.length() as u8);
366 }
367}