rusmpp_core/pdus/borrowed/
broadcast_sm.rs1use rusmpp_macros::Rusmpp;
2
3use crate::{
4 pdus::borrowed::Pdu,
5 tlvs::borrowed::{BroadcastRequestTlvValue, Tlv},
6 types::borrowed::{COctetString, EmptyOrFullCOctetString},
7 values::{borrowed::*, *},
8};
9
10#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Rusmpp)]
13#[rusmpp(decode = borrowed, test = skip)]
14#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
15#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
16pub struct BroadcastSm<'a, const N: usize> {
17 pub service_type: ServiceType<'a>,
27 pub source_addr_ton: Ton,
31 pub source_addr_npi: Npi,
35 pub source_addr: COctetString<'a, 1, 21>,
39 pub message_id: COctetString<'a, 1, 65>,
54 pub priority_flag: PriorityFlag,
56 pub schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
61 pub validity_period: EmptyOrFullCOctetString<'a, 17>,
68 pub replace_if_present_flag: ReplaceIfPresentFlag,
75 pub data_coding: DataCoding,
78 pub sm_default_msg_id: u8,
83 #[rusmpp(length = "unchecked")]
85 #[cfg_attr(feature = "arbitrary", arbitrary(default))]
86 tlvs: heapless::vec::Vec<Tlv<'a>, N>,
87}
88
89impl<'a, const N: usize> BroadcastSm<'a, N> {
90 #[allow(clippy::too_many_arguments)]
91 pub fn new(
92 service_type: ServiceType<'a>,
93 source_addr_ton: Ton,
94 source_addr_npi: Npi,
95 source_addr: COctetString<'a, 1, 21>,
96 message_id: COctetString<'a, 1, 65>,
97 priority_flag: PriorityFlag,
98 schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
99 validity_period: EmptyOrFullCOctetString<'a, 17>,
100 replace_if_present_flag: ReplaceIfPresentFlag,
101 data_coding: DataCoding,
102 sm_default_msg_id: u8,
103 tlvs: heapless::vec::Vec<impl Into<BroadcastRequestTlvValue<'a>>, N>,
104 ) -> Self {
105 let tlvs = tlvs.into_iter().map(Into::into).map(From::from).collect();
106
107 Self {
108 service_type,
109 source_addr_ton,
110 source_addr_npi,
111 source_addr,
112 message_id,
113 priority_flag,
114 schedule_delivery_time,
115 validity_period,
116 replace_if_present_flag,
117 data_coding,
118 sm_default_msg_id,
119 tlvs,
120 }
121 }
122
123 pub fn tlvs(&'_ self) -> &'_ [Tlv<'_>] {
124 &self.tlvs
125 }
126
127 pub fn set_tlvs(
128 &mut self,
129 tlvs: heapless::vec::Vec<impl Into<BroadcastRequestTlvValue<'a>>, N>,
130 ) {
131 self.tlvs = tlvs.into_iter().map(Into::into).map(From::from).collect();
132 }
133
134 pub fn clear_tlvs(&mut self) {
135 self.tlvs.clear();
136 }
137
138 pub fn push_tlv(
139 &mut self,
140 tlv: impl Into<BroadcastRequestTlvValue<'a>>,
141 ) -> Result<(), Tlv<'a>> {
142 self.tlvs.push(Tlv::from(tlv.into()))?;
143 Ok(())
144 }
145
146 pub fn builder() -> BroadcastSmBuilder<'a, N> {
147 BroadcastSmBuilder::new()
148 }
149}
150
151impl<'a, const N: usize> From<BroadcastSm<'a, N>> for Pdu<'a, N> {
152 fn from(value: BroadcastSm<'a, N>) -> Self {
153 Self::BroadcastSm(value)
154 }
155}
156
157#[derive(Debug, Default)]
158pub struct BroadcastSmBuilder<'a, const N: usize> {
159 inner: BroadcastSm<'a, N>,
160}
161
162impl<'a, const N: usize> BroadcastSmBuilder<'a, N> {
163 pub fn new() -> Self {
164 Self::default()
165 }
166
167 pub fn service_type(mut self, service_type: ServiceType<'a>) -> Self {
168 self.inner.service_type = service_type;
169 self
170 }
171
172 pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
173 self.inner.source_addr_ton = source_addr_ton;
174 self
175 }
176
177 pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
178 self.inner.source_addr_npi = source_addr_npi;
179 self
180 }
181
182 pub fn source_addr(mut self, source_addr: COctetString<'a, 1, 21>) -> Self {
183 self.inner.source_addr = source_addr;
184 self
185 }
186
187 pub fn message_id(mut self, message_id: COctetString<'a, 1, 65>) -> Self {
188 self.inner.message_id = message_id;
189 self
190 }
191
192 pub fn priority_flag(mut self, priority_flag: PriorityFlag) -> Self {
193 self.inner.priority_flag = priority_flag;
194 self
195 }
196
197 pub fn schedule_delivery_time(
198 mut self,
199 schedule_delivery_time: EmptyOrFullCOctetString<'a, 17>,
200 ) -> Self {
201 self.inner.schedule_delivery_time = schedule_delivery_time;
202 self
203 }
204
205 pub fn validity_period(mut self, validity_period: EmptyOrFullCOctetString<'a, 17>) -> Self {
206 self.inner.validity_period = validity_period;
207 self
208 }
209
210 pub fn replace_if_present_flag(
211 mut self,
212 replace_if_present_flag: ReplaceIfPresentFlag,
213 ) -> Self {
214 self.inner.replace_if_present_flag = replace_if_present_flag;
215 self
216 }
217
218 pub fn data_coding(mut self, data_coding: DataCoding) -> Self {
219 self.inner.data_coding = data_coding;
220 self
221 }
222
223 pub fn sm_default_msg_id(mut self, sm_default_msg_id: u8) -> Self {
224 self.inner.sm_default_msg_id = sm_default_msg_id;
225 self
226 }
227
228 pub fn tlvs(
229 mut self,
230 tlvs: heapless::vec::Vec<impl Into<BroadcastRequestTlvValue<'a>>, N>,
231 ) -> Self {
232 self.inner.set_tlvs(tlvs);
233 self
234 }
235
236 pub fn clear_tlvs(mut self) -> Self {
237 self.inner.clear_tlvs();
238 self
239 }
240
241 pub fn push_tlv(
242 mut self,
243 tlv: impl Into<BroadcastRequestTlvValue<'a>>,
244 ) -> Result<Self, Tlv<'a>> {
245 self.inner.push_tlv(tlv)?;
246 Ok(self)
247 }
248
249 pub fn build(self) -> BroadcastSm<'a, N> {
250 self.inner
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use crate::{tests::TestInstance, types::borrowed::OctetString};
257
258 use super::*;
259
260 impl<const N: usize> TestInstance for BroadcastSm<'_, N> {
261 fn instances() -> alloc::vec::Vec<Self> {
262 alloc::vec![
263 Self::default(),
264 Self::builder()
265 .service_type(ServiceType::new(
266 GenericServiceType::CellularMessaging.into(),
267 ))
268 .source_addr_ton(Ton::International)
269 .source_addr_npi(Npi::Isdn)
270 .source_addr(COctetString::new(b"SourceAddr\0").unwrap())
271 .message_id(COctetString::new(b"MessageId\0").unwrap())
272 .priority_flag(PriorityFlag::from(PriorityFlagType::from(GsmSms::from(1))))
273 .schedule_delivery_time(EmptyOrFullCOctetString::empty())
274 .validity_period(EmptyOrFullCOctetString::empty())
275 .replace_if_present_flag(ReplaceIfPresentFlag::Replace)
276 .data_coding(DataCoding::LatinHebrew)
277 .sm_default_msg_id(0)
278 .build(),
279 Self::builder()
280 .service_type(ServiceType::new(
281 GenericServiceType::UnstructuredSupplementaryServicesData.into(),
282 ))
283 .source_addr_ton(Ton::International)
284 .source_addr_npi(Npi::Isdn)
285 .source_addr(COctetString::new(b"SourceAddr\0").unwrap())
286 .message_id(COctetString::new(b"MessageId\0").unwrap())
287 .priority_flag(PriorityFlag::from(PriorityFlagType::from(Ansi136::Bulk)))
288 .schedule_delivery_time(
289 EmptyOrFullCOctetString::new(b"2023-10-01T00:00\0").unwrap(),
290 )
291 .validity_period(EmptyOrFullCOctetString::empty())
292 .replace_if_present_flag(ReplaceIfPresentFlag::DoNotReplace)
293 .data_coding(DataCoding::GsmMessageClassControl)
294 .sm_default_msg_id(255)
295 .tlvs(
296 [
297 BroadcastRequestTlvValue::CallbackNum(
298 OctetString::new(b"1234567890").unwrap(),
299 ),
300 BroadcastRequestTlvValue::LanguageIndicator(LanguageIndicator::German),
301 BroadcastRequestTlvValue::SmsSignal(1024),
302 ]
303 .into()
304 )
305 .build(),
306 ]
307 }
308 }
309
310 #[test]
311 fn encode_decode() {
312 crate::tests::borrowed::encode_decode_with_length_test_instances::<BroadcastSm<'static, 16>>(
313 );
314 }
315}