rusmpp_core/pdus/borrowed/
bind_resp.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
10macro_rules! bind_resp {
11    ($name:ident) => {
12        #[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
13        #[rusmpp(decode = borrowed, test = skip)]
14        #[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
15        #[cfg_attr(feature = "serde", derive(::serde::Serialize))]
16
17        pub struct $name<'a> {
18            /// MC identifier.
19            ///
20            /// Identifies the MC to the ESME.
21            pub system_id: COctetString<'a, 1, 16>,
22            /// `SMPP` version supported by MC. [`ScInterfaceVersion`].
23            #[rusmpp(length = "checked")]
24            sc_interface_version: Option<Tlv<'a>>,
25        }
26
27        impl<'a> $name<'a> {
28            pub fn new(
29                system_id: COctetString<'a, 1, 16>,
30                sc_interface_version: Option<InterfaceVersion>,
31            ) -> Self {
32                Self {
33                    system_id,
34                    sc_interface_version: sc_interface_version
35                        .map(TlvValue::ScInterfaceVersion)
36                        .map(From::from),
37                }
38            }
39
40            pub const fn sc_interface_version_tlv(&'_ self) -> Option<&'_ Tlv<'_>> {
41                self.sc_interface_version.as_ref()
42            }
43
44            pub fn sc_interface_version(&self) -> Option<InterfaceVersion> {
45                self.sc_interface_version_tlv()
46                    .and_then(|tlv| match tlv.value() {
47                        Some(TlvValue::ScInterfaceVersion(value)) => Some(value),
48                        _ => None,
49                    })
50                    .copied()
51            }
52
53            pub fn set_sc_interface_version(
54                &mut self,
55                sc_interface_version: Option<InterfaceVersion>,
56            ) {
57                self.sc_interface_version = sc_interface_version
58                    .map(TlvValue::ScInterfaceVersion)
59                    .map(From::from);
60            }
61
62            ::pastey::paste! {
63                pub fn builder() -> [<$name Builder>]<'a> {
64                    [<$name Builder>]::new()
65                }
66            }
67        }
68
69        ::pastey::paste! {
70            #[derive(Debug, Default)]
71            pub struct [<$name Builder>]<'a> {
72               inner: $name<'a>,
73            }
74
75            impl<'a> [<$name Builder>]<'a> {
76                pub fn new() -> Self {
77                    Self::default()
78                }
79
80                pub fn system_id(mut self, system_id: COctetString<'a, 1, 16>) -> Self {
81                    self.inner.system_id = system_id;
82                    self
83                }
84
85                pub fn sc_interface_version(
86                    mut self,
87                    sc_interface_version: Option<InterfaceVersion>,
88                ) -> Self {
89                    self.inner.set_sc_interface_version(sc_interface_version);
90                    self
91                }
92
93                pub fn build(self) -> $name<'a> {
94                    self.inner
95                }
96            }
97        }
98    };
99}
100
101bind_resp!(BindTransmitterResp);
102bind_resp!(BindReceiverResp);
103bind_resp!(BindTransceiverResp);
104
105impl<'a, const N: usize> From<BindTransmitterResp<'a>> for Pdu<'a, N> {
106    fn from(value: BindTransmitterResp<'a>) -> Self {
107        Self::BindTransmitterResp(value)
108    }
109}
110
111impl<'a, const N: usize> From<BindReceiverResp<'a>> for Pdu<'a, N> {
112    fn from(value: BindReceiverResp<'a>) -> Self {
113        Self::BindReceiverResp(value)
114    }
115}
116
117impl<'a, const N: usize> From<BindTransceiverResp<'a>> for Pdu<'a, N> {
118    fn from(value: BindTransceiverResp<'a>) -> Self {
119        Self::BindTransceiverResp(value)
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    use crate::tests::TestInstance;
126
127    use super::*;
128
129    impl TestInstance for BindTransmitterResp<'_> {
130        fn instances() -> alloc::vec::Vec<Self> {
131            alloc::vec![
132                Self::default(),
133                Self::builder()
134                    .system_id(COctetString::new(b"system_id\0").unwrap())
135                    .sc_interface_version(Some(InterfaceVersion::Smpp5_0))
136                    .build(),
137            ]
138        }
139    }
140
141    impl TestInstance for BindReceiverResp<'_> {
142        fn instances() -> alloc::vec::Vec<Self> {
143            alloc::vec![
144                Self::default(),
145                Self::builder()
146                    .system_id(COctetString::new(b"system_id\0").unwrap())
147                    .sc_interface_version(Some(InterfaceVersion::Smpp3_4))
148                    .build(),
149            ]
150        }
151    }
152
153    impl TestInstance for BindTransceiverResp<'_> {
154        fn instances() -> alloc::vec::Vec<Self> {
155            alloc::vec![
156                Self::default(),
157                Self::builder()
158                    .system_id(COctetString::new(b"system_id\0").unwrap())
159                    .sc_interface_version(Some(InterfaceVersion::Smpp3_3OrEarlier(1)))
160                    .build(),
161            ]
162        }
163    }
164
165    #[test]
166    fn encode_decode() {
167        crate::tests::borrowed::encode_decode_with_length_test_instances::<BindTransmitterResp>();
168        crate::tests::borrowed::encode_decode_with_length_test_instances::<BindReceiverResp>();
169        crate::tests::borrowed::encode_decode_with_length_test_instances::<BindTransceiverResp>();
170    }
171}