rusmpp_core/pdus/borrowed/
data_sm.rs1use rusmpp_macros::Rusmpp;
2
3use crate::{
4 pdus::borrowed::Pdu,
5 tlvs::borrowed::{MessageSubmissionRequestTlvValue, Tlv},
6 types::borrowed::COctetString,
7 values::{borrowed::*, *},
8};
9
10#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
15#[rusmpp(decode = borrowed, test = skip)]
16#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
17#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
18pub struct DataSm<'a, const N: usize> {
19 pub service_type: ServiceType<'a>,
29 pub source_addr_ton: Ton,
35 pub source_addr_npi: Npi,
41 pub source_addr: COctetString<'a, 1, 21>,
47 pub dest_addr_ton: Ton,
49 pub dest_addr_npi: Npi,
51 pub destination_addr: COctetString<'a, 1, 21>,
55 pub esm_class: EsmClass,
57 pub registered_delivery: RegisteredDelivery,
61 pub data_coding: DataCoding,
64 #[rusmpp(length = "unchecked")]
66 #[cfg_attr(feature = "arbitrary", arbitrary(default))]
67 tlvs: heapless::vec::Vec<Tlv<'a>, N>,
68}
69
70impl<'a, const N: usize> DataSm<'a, N> {
71 #[allow(clippy::too_many_arguments)]
72 pub fn new(
73 service_type: ServiceType<'a>,
74 source_addr_ton: Ton,
75 source_addr_npi: Npi,
76 source_addr: COctetString<'a, 1, 21>,
77 dest_addr_ton: Ton,
78 dest_addr_npi: Npi,
79 destination_addr: COctetString<'a, 1, 21>,
80 esm_class: EsmClass,
81 registered_delivery: RegisteredDelivery,
82 data_coding: DataCoding,
83 tlvs: heapless::vec::Vec<MessageSubmissionRequestTlvValue<'a>, N>,
84 ) -> Self {
85 let tlvs = tlvs.into_iter().map(From::from).collect();
86
87 Self {
88 service_type,
89 source_addr_ton,
90 source_addr_npi,
91 source_addr,
92 dest_addr_ton,
93 dest_addr_npi,
94 destination_addr,
95 esm_class,
96 registered_delivery,
97 data_coding,
98 tlvs,
99 }
100 }
101
102 pub fn tlvs(&'_ self) -> &'_ [Tlv<'_>] {
103 &self.tlvs
104 }
105
106 pub fn set_tlvs(&mut self, tlvs: heapless::vec::Vec<MessageSubmissionRequestTlvValue<'a>, N>) {
107 self.tlvs = tlvs.into_iter().map(From::from).collect();
108 }
109
110 pub fn clear_tlvs(&mut self) {
111 self.tlvs.clear();
112 }
113
114 pub fn push_tlv(
115 &mut self,
116 tlv: impl Into<MessageSubmissionRequestTlvValue<'a>>,
117 ) -> Result<(), Tlv<'a>> {
118 self.tlvs.push(Tlv::from(tlv.into()))?;
119 Ok(())
120 }
121
122 pub fn builder() -> DataSmBuilder<'a, N> {
123 DataSmBuilder::new()
124 }
125}
126
127impl<'a, const N: usize> From<DataSm<'a, N>> for Pdu<'a, N> {
128 fn from(value: DataSm<'a, N>) -> Self {
129 Self::DataSm(value)
130 }
131}
132
133#[derive(Debug, Default)]
134pub struct DataSmBuilder<'a, const N: usize> {
135 inner: DataSm<'a, N>,
136}
137
138impl<'a, const N: usize> DataSmBuilder<'a, N> {
139 pub fn new() -> Self {
140 Default::default()
141 }
142
143 pub fn service_type(mut self, service_type: ServiceType<'a>) -> Self {
144 self.inner.service_type = service_type;
145 self
146 }
147
148 pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
149 self.inner.source_addr_ton = source_addr_ton;
150 self
151 }
152
153 pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
154 self.inner.source_addr_npi = source_addr_npi;
155 self
156 }
157
158 pub fn source_addr(mut self, source_addr: COctetString<'a, 1, 21>) -> Self {
159 self.inner.source_addr = source_addr;
160 self
161 }
162
163 pub fn dest_addr_ton(mut self, dest_addr_ton: Ton) -> Self {
164 self.inner.dest_addr_ton = dest_addr_ton;
165 self
166 }
167
168 pub fn dest_addr_npi(mut self, dest_addr_npi: Npi) -> Self {
169 self.inner.dest_addr_npi = dest_addr_npi;
170 self
171 }
172
173 pub fn destination_addr(mut self, destination_addr: COctetString<'a, 1, 21>) -> Self {
174 self.inner.destination_addr = destination_addr;
175 self
176 }
177
178 pub fn esm_class(mut self, esm_class: EsmClass) -> Self {
179 self.inner.esm_class = esm_class;
180 self
181 }
182
183 pub fn registered_delivery(mut self, registered_delivery: RegisteredDelivery) -> Self {
184 self.inner.registered_delivery = registered_delivery;
185 self
186 }
187
188 pub fn data_coding(mut self, data_coding: DataCoding) -> Self {
189 self.inner.data_coding = data_coding;
190 self
191 }
192
193 pub fn tlvs(
194 mut self,
195 tlvs: heapless::vec::Vec<MessageSubmissionRequestTlvValue<'a>, N>,
196 ) -> Self {
197 self.inner.set_tlvs(tlvs);
198 self
199 }
200
201 pub fn clear_tlvs(mut self) -> Self {
202 self.inner.clear_tlvs();
203 self
204 }
205
206 pub fn push_tlv(
207 mut self,
208 tlv: impl Into<MessageSubmissionRequestTlvValue<'a>>,
209 ) -> Result<Self, Tlv<'a>> {
210 self.inner.push_tlv(tlv)?;
211 Ok(self)
212 }
213
214 pub fn build(self) -> DataSm<'a, N> {
215 self.inner
216 }
217}
218
219#[cfg(test)]
220mod tests {
221 use crate::tests::TestInstance;
222
223 use super::*;
224
225 impl<const N: usize> TestInstance for DataSm<'_, N> {
226 fn instances() -> alloc::vec::Vec<Self> {
227 alloc::vec![
228 Self::default(),
229 Self::builder()
230 .service_type(ServiceType::default())
231 .source_addr_ton(Ton::International)
232 .source_addr_npi(Npi::Isdn)
233 .source_addr(COctetString::new(b"source_addr\0").unwrap())
234 .dest_addr_ton(Ton::International)
235 .dest_addr_npi(Npi::Isdn)
236 .destination_addr(COctetString::new(b"destination_addr\0").unwrap())
237 .esm_class(EsmClass::default())
238 .registered_delivery(RegisteredDelivery::request_all())
239 .data_coding(DataCoding::Ucs2)
240 .build(),
241 Self::builder()
242 .service_type(ServiceType::default())
243 .source_addr_ton(Ton::International)
244 .source_addr_npi(Npi::Isdn)
245 .source_addr(COctetString::new(b"source_addr\0").unwrap())
246 .dest_addr_ton(Ton::International)
247 .dest_addr_npi(Npi::Isdn)
248 .destination_addr(COctetString::new(b"destination_addr\0").unwrap())
249 .esm_class(EsmClass::default())
250 .registered_delivery(RegisteredDelivery::new(
251 MCDeliveryReceipt::NoMcDeliveryReceiptRequested,
252 SmeOriginatedAcknowledgement::SmeUserAcknowledgementRequested,
253 IntermediateNotification::IntermediateNotificationRequested,
254 0,
255 ))
256 .data_coding(DataCoding::Ucs2)
257 .push_tlv(MessageSubmissionRequestTlvValue::SourceAddrSubunit(
258 AddrSubunit::MobileEquipment,
259 ))
260 .unwrap()
261 .push_tlv(MessageSubmissionRequestTlvValue::UssdServiceOp(
262 UssdServiceOp::UssnConfirm,
263 ))
264 .unwrap()
265 .build(),
266 ]
267 }
268 }
269
270 #[test]
271 fn encode_decode() {
272 crate::tests::borrowed::encode_decode_with_length_test_instances::<DataSm<'static, 16>>();
273 }
274}