rusmpp_core/pdus/borrowed/
bind.rs

1use rusmpp_macros::Rusmpp;
2
3use crate::{
4    pdus::borrowed::Pdu,
5    types::borrowed::COctetString,
6    values::{InterfaceVersion, Npi, Ton},
7};
8
9macro_rules! bind {
10    ($name:ident) => {
11        #[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
12        #[rusmpp(decode = borrowed, test = skip)]
13        #[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
14        #[cfg_attr(feature = "serde", derive(::serde::Serialize))]
15
16        pub struct $name<'a> {
17            /// Identifies the ESME system
18            /// requesting to bind with the MC.
19            pub system_id: COctetString<'a, 1, 16>,
20            /// The password may be used by the
21            /// MC to authenticate the ESME
22            /// requesting to bind.
23            pub password: COctetString<'a, 1, 9>,
24            /// Identifies the type of ESME system
25            /// requesting to bind with the MC.
26            pub system_type: COctetString<'a, 1, 13>,
27            /// Identifies the version of the `SMPP`
28            /// protocol supported by the ESME.
29            pub interface_version: InterfaceVersion,
30            /// Type of Number (TON) for ESME
31            /// address(es) served via this `SMPP` session.
32            ///
33            /// Set to NULL (Unknown) if not known.
34            pub addr_ton: Ton,
35            /// Numbering Plan Indicator (NPI) for
36            /// ESME address(es) served via this `SMPP` session.
37            ///
38            /// Set to NULL (Unknown) if not known.
39            pub addr_npi: Npi,
40            /// A single ESME address or a range of
41            /// ESME addresses served via this `SMPP` session.
42            ///
43            /// Set to NULL if not known.
44            pub address_range: COctetString<'a, 1, 41>,
45        }
46
47        impl<'a> $name<'a> {
48            pub const fn new(
49                system_id: COctetString<'a, 1, 16>,
50                password: COctetString<'a, 1, 9>,
51                system_type: COctetString<'a, 1, 13>,
52                interface_version: InterfaceVersion,
53                addr_ton: Ton,
54                addr_npi: Npi,
55                address_range: COctetString<'a, 1, 41>,
56            ) -> Self {
57                Self {
58                    system_id,
59                    password,
60                    system_type,
61                    interface_version,
62                    addr_ton,
63                    addr_npi,
64                    address_range,
65                }
66            }
67
68            ::pastey::paste! {
69                pub fn builder() -> [<$name Builder>]<'a> {
70                    [<$name Builder>]::new()
71                }
72            }
73        }
74
75        ::pastey::paste! {
76            #[derive(Debug, Default)]
77            pub struct [<$name Builder>]<'a> {
78               inner: $name<'a>,
79            }
80
81            impl<'a> [<$name Builder>]<'a> {
82                pub fn new() -> Self {
83                    Self::default()
84                }
85
86                pub fn system_id(mut self, system_id: COctetString<'a, 1, 16>) -> Self {
87                    self.inner.system_id = system_id;
88                    self
89                }
90
91                pub fn password(mut self, password: COctetString<'a, 1, 9>) -> Self {
92                    self.inner.password = password;
93                    self
94                }
95
96                pub fn system_type(mut self, system_type: COctetString<'a, 1, 13>) -> Self {
97                    self.inner.system_type = system_type;
98                    self
99                }
100
101                pub const fn interface_version(mut self, interface_version: InterfaceVersion) -> Self {
102                    self.inner.interface_version = interface_version;
103                    self
104                }
105
106                pub const fn addr_ton(mut self, addr_ton: Ton) -> Self {
107                    self.inner.addr_ton = addr_ton;
108                    self
109                }
110
111                pub const fn addr_npi(mut self, addr_npi: Npi) -> Self {
112                    self.inner.addr_npi = addr_npi;
113                    self
114                }
115
116                pub fn address_range(mut self, address_range: COctetString<'a, 1, 41>) -> Self {
117                    self.inner.address_range = address_range;
118                    self
119                }
120
121                pub fn build(self) -> $name<'a> {
122                    self.inner
123                }
124            }
125        }
126    };
127}
128
129bind!(BindTransmitter);
130bind!(BindReceiver);
131bind!(BindTransceiver);
132
133impl<'a, const N: usize> From<BindTransmitter<'a>> for Pdu<'a, N> {
134    fn from(value: BindTransmitter<'a>) -> Self {
135        Self::BindTransmitter(value)
136    }
137}
138
139impl<'a, const N: usize> From<BindReceiver<'a>> for Pdu<'a, N> {
140    fn from(value: BindReceiver<'a>) -> Self {
141        Self::BindReceiver(value)
142    }
143}
144
145impl<'a, const N: usize> From<BindTransceiver<'a>> for Pdu<'a, N> {
146    fn from(value: BindTransceiver<'a>) -> Self {
147        Self::BindTransceiver(value)
148    }
149}
150
151#[cfg(test)]
152mod tests {
153    use crate::tests::TestInstance;
154
155    use super::*;
156
157    impl TestInstance for BindTransmitter<'static> {
158        fn instances() -> alloc::vec::Vec<Self> {
159            alloc::vec![
160                Self::default(),
161                Self::builder()
162                    .system_id(COctetString::new(b"system_id\0").unwrap())
163                    .password(COctetString::new(b"password\0").unwrap())
164                    .system_type(COctetString::new(b"system_type\0").unwrap())
165                    .interface_version(InterfaceVersion::Smpp5_0)
166                    .addr_ton(Ton::International)
167                    .addr_npi(Npi::Isdn)
168                    .address_range(COctetString::new(b"address_range\0").unwrap())
169                    .build(),
170            ]
171        }
172    }
173
174    impl TestInstance for BindReceiver<'static> {
175        fn instances() -> alloc::vec::Vec<Self> {
176            alloc::vec![
177                Self::default(),
178                Self::builder()
179                    .system_id(COctetString::new(b"system_id\0").unwrap())
180                    .password(COctetString::new(b"password\0").unwrap())
181                    .system_type(COctetString::new(b"system_type\0").unwrap())
182                    .interface_version(InterfaceVersion::Smpp3_4)
183                    .addr_ton(Ton::Alphanumeric)
184                    .addr_npi(Npi::Ermes)
185                    .address_range(COctetString::new(b"address_range\0").unwrap())
186                    .build(),
187            ]
188        }
189    }
190
191    impl TestInstance for BindTransceiver<'static> {
192        fn instances() -> alloc::vec::Vec<Self> {
193            alloc::vec![
194                Self::default(),
195                Self::builder()
196                    .system_id(COctetString::new(b"system_id\0").unwrap())
197                    .password(COctetString::new(b"password\0").unwrap())
198                    .system_type(COctetString::new(b"system_type\0").unwrap())
199                    .interface_version(InterfaceVersion::Smpp3_3OrEarlier(2))
200                    .addr_ton(Ton::International)
201                    .addr_npi(Npi::Ermes)
202                    .address_range(COctetString::new(b"address_range\0").unwrap())
203                    .build(),
204            ]
205        }
206    }
207
208    #[test]
209    fn encode_decode() {
210        crate::tests::borrowed::encode_decode_test_instances::<BindTransmitter<'static>>();
211        crate::tests::borrowed::encode_decode_test_instances::<BindReceiver>();
212        crate::tests::borrowed::encode_decode_test_instances::<BindTransceiver>();
213    }
214}