1use rusmpp_macros::Rusmpp;
2
3use crate::{
4 encode::Length,
5 pdus::owned::Pdu,
6 tlvs::owned::{Tlv, TlvValue},
7 types::owned::{COctetString, EmptyOrFullCOctetString, OctetString},
8 values::{owned::*, *},
9};
10
11#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
18#[rusmpp(decode = owned, test = skip)]
19#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
20#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
21#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
22pub struct ReplaceSm {
23 pub message_id: COctetString<1, 65>,
30 pub source_addr_ton: Ton,
36 pub source_addr_npi: Npi,
41 pub source_addr: COctetString<1, 21>,
44 pub schedule_delivery_time: EmptyOrFullCOctetString<17>,
48 pub validity_period: EmptyOrFullCOctetString<17>,
54 pub registered_delivery: RegisteredDelivery,
58 pub sm_default_msg_id: u8,
64 sm_length: u8,
66 #[rusmpp(length = sm_length)]
76 short_message: OctetString<0, 255>,
77 #[rusmpp(length = "checked")]
79 message_payload: Option<Tlv>,
80}
81
82impl ReplaceSm {
83 #[allow(clippy::too_many_arguments)]
84 pub fn new(
85 message_id: COctetString<1, 65>,
86 source_addr_ton: Ton,
87 source_addr_npi: Npi,
88 source_addr: COctetString<1, 21>,
89 schedule_delivery_time: EmptyOrFullCOctetString<17>,
90 validity_period: EmptyOrFullCOctetString<17>,
91 registered_delivery: RegisteredDelivery,
92 sm_default_msg_id: u8,
93 short_message: OctetString<0, 255>,
94 message_payload: Option<MessagePayload>,
95 ) -> Self {
96 let message_payload = message_payload
97 .map(TlvValue::MessagePayload)
98 .map(From::from);
99
100 let sm_length = short_message.length() as u8;
101
102 Self {
103 message_id,
104 source_addr_ton,
105 source_addr_npi,
106 source_addr,
107 schedule_delivery_time,
108 validity_period,
109 registered_delivery,
110 sm_default_msg_id,
111 sm_length,
112 short_message,
113 message_payload,
114 }
115 }
116
117 pub const fn sm_length(&self) -> u8 {
118 self.sm_length
119 }
120
121 pub fn short_message(&self) -> &OctetString<0, 255> {
122 &self.short_message
123 }
124
125 pub fn set_short_message(&mut self, short_message: OctetString<0, 255>) {
132 self.short_message = short_message;
133 self.sm_length = self.short_message.length() as u8;
134 }
135
136 pub const fn message_payload_tlv(&self) -> Option<&Tlv> {
137 self.message_payload.as_ref()
138 }
139
140 pub fn message_payload(&self) -> Option<&MessagePayload> {
141 self.message_payload_tlv()
142 .and_then(|tlv| match tlv.value() {
143 Some(TlvValue::MessagePayload(value)) => Some(value),
144 _ => None,
145 })
146 }
147
148 pub fn set_message_payload(&mut self, message_payload: Option<MessagePayload>) {
155 self.message_payload = message_payload
156 .map(TlvValue::MessagePayload)
157 .map(From::from);
158 }
159
160 pub fn builder() -> ReplaceSmBuilder {
161 ReplaceSmBuilder::new()
162 }
163}
164
165impl From<ReplaceSm> for Pdu {
166 fn from(value: ReplaceSm) -> Self {
167 Self::ReplaceSm(value)
168 }
169}
170
171#[derive(Debug, Default)]
172pub struct ReplaceSmBuilder {
173 inner: ReplaceSm,
174}
175
176impl ReplaceSmBuilder {
177 pub fn new() -> Self {
178 Self::default()
179 }
180
181 pub fn message_id(mut self, message_id: COctetString<1, 65>) -> Self {
182 self.inner.message_id = message_id;
183 self
184 }
185
186 pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
187 self.inner.source_addr_ton = source_addr_ton;
188 self
189 }
190
191 pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
192 self.inner.source_addr_npi = source_addr_npi;
193 self
194 }
195
196 pub fn source_addr(mut self, source_addr: COctetString<1, 21>) -> Self {
197 self.inner.source_addr = source_addr;
198 self
199 }
200
201 pub fn schedule_delivery_time(
202 mut self,
203 schedule_delivery_time: EmptyOrFullCOctetString<17>,
204 ) -> Self {
205 self.inner.schedule_delivery_time = schedule_delivery_time;
206 self
207 }
208
209 pub fn validity_period(mut self, validity_period: EmptyOrFullCOctetString<17>) -> Self {
210 self.inner.validity_period = validity_period;
211 self
212 }
213
214 pub fn registered_delivery(mut self, registered_delivery: RegisteredDelivery) -> Self {
215 self.inner.registered_delivery = registered_delivery;
216 self
217 }
218
219 pub fn sm_default_msg_id(mut self, sm_default_msg_id: u8) -> Self {
220 self.inner.sm_default_msg_id = sm_default_msg_id;
221 self
222 }
223
224 pub fn short_message(mut self, short_message: OctetString<0, 255>) -> Self {
225 self.inner.set_short_message(short_message);
226 self
227 }
228
229 pub fn message_payload(mut self, message_payload: Option<MessagePayload>) -> Self {
230 self.inner.set_message_payload(message_payload);
231 self
232 }
233
234 pub fn build(self) -> ReplaceSm {
235 self.inner
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use std::str::FromStr;
242
243 use crate::{tests::TestInstance, types::owned::AnyOctetString};
244
245 use super::*;
246
247 impl TestInstance for ReplaceSm {
248 fn instances() -> alloc::vec::Vec<Self> {
249 alloc::vec![
250 Self::default(),
251 Self::builder()
252 .message_id(COctetString::from_str("123456789012345678901234").unwrap())
253 .source_addr_ton(Ton::International)
254 .source_addr_npi(Npi::Isdn)
255 .source_addr(COctetString::from_str("Source Addr").unwrap())
256 .schedule_delivery_time(
257 EmptyOrFullCOctetString::from_static_slice(b"2023-10-01T12:00\0").unwrap(),
258 )
259 .validity_period(
260 EmptyOrFullCOctetString::from_static_slice(b"2023-10-01T12:00\0").unwrap()
261 )
262 .registered_delivery(RegisteredDelivery::default())
263 .sm_default_msg_id(0)
264 .short_message(OctetString::from_static_slice(b"Short Message").unwrap())
265 .build(),
266 Self::builder()
267 .message_id(COctetString::from_str("123456789012345678901234").unwrap())
268 .source_addr_ton(Ton::International)
269 .source_addr_npi(Npi::Isdn)
270 .source_addr(COctetString::from_str("Source Addr").unwrap())
271 .schedule_delivery_time(
272 EmptyOrFullCOctetString::from_static_slice(b"2023-10-01T12:00\0").unwrap(),
273 )
274 .validity_period(
275 EmptyOrFullCOctetString::from_static_slice(b"2023-10-01T12:00\0").unwrap()
276 )
277 .registered_delivery(RegisteredDelivery::default())
278 .sm_default_msg_id(0)
279 .message_payload(Some(MessagePayload::new(
280 AnyOctetString::from_static_slice(b"Message Payload",)
281 )))
282 .build(),
283 Self::builder()
284 .validity_period(
285 EmptyOrFullCOctetString::from_static_slice(b"2023-10-01T12:00\0").unwrap()
286 )
287 .short_message(OctetString::from_static_slice(b"Short Message").unwrap())
288 .message_payload(Some(MessagePayload::new(
289 AnyOctetString::from_static_slice(b"Message Payload",)
290 )))
291 .build(),
292 ]
293 }
294 }
295
296 #[test]
297 fn encode_decode() {
298 crate::tests::owned::encode_decode_with_length_test_instances::<ReplaceSm>();
299 }
300
301 #[test]
302 fn short_message_length() {
303 let short_message = OctetString::from_static_slice(b"Short Message").unwrap();
304
305 let submit_sm = ReplaceSm::builder()
306 .short_message(short_message.clone())
307 .build();
308
309 assert_eq!(submit_sm.short_message(), &short_message);
310 assert_eq!(submit_sm.sm_length(), short_message.length() as u8);
311 }
312}