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<impl Into<MessageSubmissionRequestTlvValue<'a>>, N>,
84 ) -> Self {
85 let tlvs = tlvs.into_iter().map(Into::into).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(
107 &mut self,
108 tlvs: heapless::vec::Vec<impl Into<MessageSubmissionRequestTlvValue<'a>>, N>,
109 ) {
110 self.tlvs = tlvs.into_iter().map(Into::into).map(From::from).collect();
111 }
112
113 pub fn clear_tlvs(&mut self) {
114 self.tlvs.clear();
115 }
116
117 pub fn push_tlv(
118 &mut self,
119 tlv: impl Into<MessageSubmissionRequestTlvValue<'a>>,
120 ) -> Result<(), Tlv<'a>> {
121 self.tlvs.push(Tlv::from(tlv.into()))?;
122 Ok(())
123 }
124
125 pub fn builder() -> DataSmBuilder<'a, N> {
126 DataSmBuilder::new()
127 }
128}
129
130impl<'a, const N: usize> From<DataSm<'a, N>> for Pdu<'a, N> {
131 fn from(value: DataSm<'a, N>) -> Self {
132 Self::DataSm(value)
133 }
134}
135
136#[derive(Debug, Default)]
137pub struct DataSmBuilder<'a, const N: usize> {
138 inner: DataSm<'a, N>,
139}
140
141impl<'a, const N: usize> DataSmBuilder<'a, N> {
142 pub fn new() -> Self {
143 Default::default()
144 }
145
146 pub fn service_type(mut self, service_type: ServiceType<'a>) -> Self {
147 self.inner.service_type = service_type;
148 self
149 }
150
151 pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
152 self.inner.source_addr_ton = source_addr_ton;
153 self
154 }
155
156 pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
157 self.inner.source_addr_npi = source_addr_npi;
158 self
159 }
160
161 pub fn source_addr(mut self, source_addr: COctetString<'a, 1, 21>) -> Self {
162 self.inner.source_addr = source_addr;
163 self
164 }
165
166 pub fn dest_addr_ton(mut self, dest_addr_ton: Ton) -> Self {
167 self.inner.dest_addr_ton = dest_addr_ton;
168 self
169 }
170
171 pub fn dest_addr_npi(mut self, dest_addr_npi: Npi) -> Self {
172 self.inner.dest_addr_npi = dest_addr_npi;
173 self
174 }
175
176 pub fn destination_addr(mut self, destination_addr: COctetString<'a, 1, 21>) -> Self {
177 self.inner.destination_addr = destination_addr;
178 self
179 }
180
181 pub fn esm_class(mut self, esm_class: EsmClass) -> Self {
182 self.inner.esm_class = esm_class;
183 self
184 }
185
186 pub fn registered_delivery(mut self, registered_delivery: RegisteredDelivery) -> Self {
187 self.inner.registered_delivery = registered_delivery;
188 self
189 }
190
191 pub fn data_coding(mut self, data_coding: DataCoding) -> Self {
192 self.inner.data_coding = data_coding;
193 self
194 }
195
196 pub fn tlvs(
197 mut self,
198 tlvs: heapless::vec::Vec<impl Into<MessageSubmissionRequestTlvValue<'a>>, N>,
199 ) -> Self {
200 self.inner.set_tlvs(tlvs);
201 self
202 }
203
204 pub fn clear_tlvs(mut self) -> Self {
205 self.inner.clear_tlvs();
206 self
207 }
208
209 pub fn push_tlv(
210 mut self,
211 tlv: impl Into<MessageSubmissionRequestTlvValue<'a>>,
212 ) -> Result<Self, Tlv<'a>> {
213 self.inner.push_tlv(tlv)?;
214 Ok(self)
215 }
216
217 pub fn build(self) -> DataSm<'a, N> {
218 self.inner
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use crate::tests::TestInstance;
225
226 use super::*;
227
228 impl<const N: usize> TestInstance for DataSm<'_, N> {
229 fn instances() -> alloc::vec::Vec<Self> {
230 alloc::vec![
231 Self::default(),
232 Self::builder()
233 .service_type(ServiceType::default())
234 .source_addr_ton(Ton::International)
235 .source_addr_npi(Npi::Isdn)
236 .source_addr(COctetString::new(b"source_addr\0").unwrap())
237 .dest_addr_ton(Ton::International)
238 .dest_addr_npi(Npi::Isdn)
239 .destination_addr(COctetString::new(b"destination_addr\0").unwrap())
240 .esm_class(EsmClass::default())
241 .registered_delivery(RegisteredDelivery::request_all())
242 .data_coding(DataCoding::Ucs2)
243 .build(),
244 Self::builder()
245 .service_type(ServiceType::default())
246 .source_addr_ton(Ton::International)
247 .source_addr_npi(Npi::Isdn)
248 .source_addr(COctetString::new(b"source_addr\0").unwrap())
249 .dest_addr_ton(Ton::International)
250 .dest_addr_npi(Npi::Isdn)
251 .destination_addr(COctetString::new(b"destination_addr\0").unwrap())
252 .esm_class(EsmClass::default())
253 .registered_delivery(RegisteredDelivery::new(
254 MCDeliveryReceipt::NoMcDeliveryReceiptRequested,
255 SmeOriginatedAcknowledgement::SmeUserAcknowledgementRequested,
256 IntermediateNotification::IntermediateNotificationRequested,
257 0,
258 ))
259 .data_coding(DataCoding::Ucs2)
260 .push_tlv(MessageSubmissionRequestTlvValue::SourceAddrSubunit(
261 AddrSubunit::MobileEquipment,
262 ))
263 .unwrap()
264 .push_tlv(MessageSubmissionRequestTlvValue::UssdServiceOp(
265 UssdServiceOp::UssnConfirm,
266 ))
267 .unwrap()
268 .build(),
269 ]
270 }
271 }
272
273 #[test]
274 fn encode_decode() {
275 crate::tests::borrowed::encode_decode_with_length_test_instances::<DataSm<'static, 16>>();
276 }
277}