rusmpp_core/pdus/borrowed/
alert_notification.rs

1use rusmpp_macros::Rusmpp;
2
3use crate::{
4    pdus::borrowed::Pdu,
5    tlvs::borrowed::{Tlv, TlvValue},
6    types::borrowed::COctetString,
7    values::*,
8};
9
10/// The alert_notification PDU is sent by the MC to the ESME across a Receiver or Transceiver
11/// session. It is sent when the MC has detected that a particular mobile subscriber has become
12/// available and a delivery pending flag had been previously set for that subscriber by means of
13/// the set_dpf TLV.
14///
15/// A typical use of this operation is to trigger a data content ‘Push’ to the subscriber from a WAP
16/// Proxy Server.
17///
18/// Note: There is no associated alert_notification_resp PDU.
19#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
20#[rusmpp(decode = borrowed, test = skip)]
21#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
22#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
23pub struct AlertNotification<'a> {
24    /// Type of Number for alert SME.
25    pub source_addr_ton: Ton,
26    /// Numbering Plan Indicator for alert SME.
27    pub source_addr_npi: Npi,
28    /// Address of alert SME.
29    pub source_addr: COctetString<'a, 1, 65>,
30    /// Type of Number for ESME address
31    /// which requested the alert.
32    pub esme_addr_ton: Ton,
33    /// Numbering Plan Indicator for ESME
34    /// address which requested the alert.
35    pub esme_addr_npi: Npi,
36    /// Address for ESME which requested the alert.
37    pub esme_addr: COctetString<'a, 1, 65>,
38    /// The status of the mobile station [`MsAvailabilityStatus`].
39    #[rusmpp(length = "checked")]
40    ms_availability_status: Option<Tlv<'a>>,
41}
42
43impl<'a> AlertNotification<'a> {
44    pub fn new(
45        source_addr_ton: Ton,
46        source_addr_npi: Npi,
47        source_addr: COctetString<'a, 1, 65>,
48        esme_addr_ton: Ton,
49        esme_addr_npi: Npi,
50        esme_addr: COctetString<'a, 1, 65>,
51        ms_availability_status: Option<MsAvailabilityStatus>,
52    ) -> Self {
53        Self {
54            source_addr_ton,
55            source_addr_npi,
56            source_addr,
57            esme_addr_ton,
58            esme_addr_npi,
59            esme_addr,
60            ms_availability_status: ms_availability_status
61                .map(TlvValue::MsAvailabilityStatus)
62                .map(From::from),
63        }
64    }
65
66    pub const fn ms_availability_status_tlv(&'_ self) -> Option<&'_ Tlv<'_>> {
67        self.ms_availability_status.as_ref()
68    }
69
70    pub fn ms_availability_status(&self) -> Option<MsAvailabilityStatus> {
71        self.ms_availability_status_tlv()
72            .and_then(|tlv| match tlv.value() {
73                Some(TlvValue::MsAvailabilityStatus(value)) => Some(value),
74                _ => None,
75            })
76            .copied()
77    }
78
79    pub fn set_ms_availability_status(
80        &mut self,
81        ms_availability_status: Option<MsAvailabilityStatus>,
82    ) {
83        self.ms_availability_status = ms_availability_status
84            .map(TlvValue::MsAvailabilityStatus)
85            .map(From::from);
86    }
87
88    pub fn builder() -> AlertNotificationBuilder<'a> {
89        AlertNotificationBuilder::new()
90    }
91}
92
93impl<'a, const N: usize> From<AlertNotification<'a>> for Pdu<'a, N> {
94    fn from(value: AlertNotification<'a>) -> Self {
95        Self::AlertNotification(value)
96    }
97}
98
99#[derive(Debug, Default)]
100pub struct AlertNotificationBuilder<'a> {
101    inner: AlertNotification<'a>,
102}
103
104impl<'a> AlertNotificationBuilder<'a> {
105    pub fn new() -> Self {
106        Default::default()
107    }
108
109    pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
110        self.inner.source_addr_ton = source_addr_ton;
111        self
112    }
113
114    pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
115        self.inner.source_addr_npi = source_addr_npi;
116        self
117    }
118
119    pub fn source_addr(mut self, source_addr: COctetString<'a, 1, 65>) -> Self {
120        self.inner.source_addr = source_addr;
121        self
122    }
123
124    pub fn esme_addr_ton(mut self, esme_addr_ton: Ton) -> Self {
125        self.inner.esme_addr_ton = esme_addr_ton;
126        self
127    }
128
129    pub fn esme_addr_npi(mut self, esme_addr_npi: Npi) -> Self {
130        self.inner.esme_addr_npi = esme_addr_npi;
131        self
132    }
133
134    pub fn esme_addr(mut self, esme_addr: COctetString<'a, 1, 65>) -> Self {
135        self.inner.esme_addr = esme_addr;
136        self
137    }
138
139    pub fn ms_availability_status(
140        mut self,
141        ms_availability_status: Option<MsAvailabilityStatus>,
142    ) -> Self {
143        self.inner
144            .set_ms_availability_status(ms_availability_status);
145        self
146    }
147
148    pub fn build(self) -> AlertNotification<'a> {
149        self.inner
150    }
151}
152
153#[cfg(test)]
154mod tests {
155    use crate::tests::TestInstance;
156
157    use super::*;
158
159    impl TestInstance for AlertNotification<'_> {
160        fn instances() -> alloc::vec::Vec<Self> {
161            alloc::vec![
162                Self::default(),
163                Self::builder()
164                    .ms_availability_status(Some(MsAvailabilityStatus::Available))
165                    .build(),
166                Self::builder()
167                    .source_addr_ton(Ton::International)
168                    .source_addr_npi(Npi::Isdn)
169                    .source_addr(COctetString::new(b"1234567890\0").unwrap())
170                    .esme_addr_ton(Ton::International)
171                    .esme_addr_npi(Npi::Isdn)
172                    .esme_addr(COctetString::new(b"0987654321\0").unwrap())
173                    .ms_availability_status(Some(MsAvailabilityStatus::Available))
174                    .build(),
175                Self::builder()
176                    .source_addr_ton(Ton::NetworkSpecific)
177                    .source_addr_npi(Npi::LandMobile)
178                    .source_addr(COctetString::new(b"1234567890\0").unwrap())
179                    .esme_addr_ton(Ton::Abbreviated)
180                    .esme_addr_npi(Npi::WapClientId)
181                    .esme_addr(COctetString::new(b"0987654321\0").unwrap())
182                    .ms_availability_status(Some(MsAvailabilityStatus::Other(255)))
183                    .build(),
184            ]
185        }
186    }
187
188    #[test]
189    fn encode_decode() {
190        crate::tests::borrowed::encode_decode_with_length_test_instances::<AlertNotification>();
191    }
192}