rusmpp_core/values/dest_address/
borrowed.rs

1use rusmpp_macros::Rusmpp;
2
3use crate::{
4    decode::{
5        DecodeError, DecodeResultExt,
6        borrowed::{Decode, DecodeExt},
7    },
8    encode::Length,
9    types::borrowed::COctetString,
10    values::{dest_address::DestFlag, npi::Npi, ton::Ton},
11};
12
13#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
14#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
15#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
16pub enum DestAddress<'a> {
17    /// SME Format Destination Address.
18    SmeAddress(SmeAddress<'a>),
19    /// Distribution List Format Destination Address.
20    DistributionListName(DistributionListName<'a>),
21}
22
23impl Length for DestAddress<'_> {
24    fn length(&self) -> usize {
25        match self {
26            Self::SmeAddress(sa) => sa.length(),
27            Self::DistributionListName(dlm) => dlm.length(),
28        }
29    }
30}
31
32impl crate::encode::Encode for DestAddress<'_> {
33    fn encode(&self, dst: &mut [u8]) -> usize {
34        match self {
35            Self::SmeAddress(sa) => sa.encode(dst),
36            Self::DistributionListName(dlm) => dlm.encode(dst),
37        }
38    }
39}
40
41#[cfg(feature = "alloc")]
42impl crate::encode::owned::Encode for DestAddress<'_> {
43    fn encode(&self, dst: &mut bytes::BytesMut) {
44        match self {
45            Self::SmeAddress(sa) => sa.encode(dst),
46            Self::DistributionListName(dlm) => dlm.encode(dst),
47        }
48    }
49}
50
51impl<'a> Decode<'a> for DestAddress<'a> {
52    fn decode(src: &'a [u8]) -> Result<(Self, usize), DecodeError> {
53        let size = 0;
54
55        let (flag, size) = DestFlag::decode_move(src, size)?;
56
57        match flag {
58            DestFlag::SmeAddress => {
59                SmeAddress::decode_move(src, size).map_decoded(Self::SmeAddress)
60            }
61            DestFlag::DistributionListName => {
62                DistributionListName::decode_move(src, size).map_decoded(Self::DistributionListName)
63            }
64            DestFlag::Other(flag) => Err(DecodeError::unsupported_key(flag.into())),
65        }
66    }
67}
68
69/// SME Format Destination Address.
70#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
71#[rusmpp(decode = borrowed, test = skip)]
72#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
73#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
74pub struct SmeAddress<'a> {
75    /// 0x01 (SME Address).
76    ///
77    /// Can't and shouldn't be updated
78    #[rusmpp(skip_decode)]
79    dest_flag: DestFlag,
80    /// Type of Number for destination.
81    pub dest_addr_ton: Ton,
82    /// Numbering Plan Indicator for destination.
83    pub dest_addr_npi: Npi,
84    /// Destination address of this short message. For mobile
85    /// terminated messages, this is the directory number of the
86    /// recipient MS.
87    pub destination_addr: COctetString<'a, 1, 21>,
88}
89
90impl<'a> SmeAddress<'a> {
91    pub const fn new(
92        dest_addr_ton: Ton,
93        dest_addr_npi: Npi,
94        destination_addr: COctetString<'a, 1, 21>,
95    ) -> Self {
96        Self {
97            dest_flag: DestFlag::SmeAddress,
98            dest_addr_ton,
99            dest_addr_npi,
100            destination_addr,
101        }
102    }
103
104    pub fn dest_flag(&self) -> DestFlag {
105        self.dest_flag
106    }
107}
108
109/// Distribution List Format Destination Address.
110#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
111#[rusmpp(decode = borrowed, test = skip)]
112#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
113#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
114pub struct DistributionListName<'a> {
115    /// 0x02 (Distribution List).
116    ///
117    /// Can't and shouldn't be updated.
118    #[rusmpp(skip_decode)]
119    dest_flag: DestFlag,
120    /// Name of Distribution List.
121    pub dl_name: COctetString<'a, 1, 21>,
122}
123
124impl<'a> DistributionListName<'a> {
125    pub fn new(dl_name: COctetString<'a, 1, 21>) -> Self {
126        Self {
127            dest_flag: DestFlag::DistributionListName,
128            dl_name,
129        }
130    }
131
132    pub fn dest_flag(&self) -> DestFlag {
133        self.dest_flag
134    }
135}
136
137#[cfg(test)]
138mod tests {
139    //! # Note
140    //!
141    //! [`encode_decode_test_instances`](crate::tests::borrowed::encode_decode_test_instances) will fail for [`SmeAddress`] and [`DistributionListName`]
142    //! because they encode the `dest_flag` field but skip decoding it, since it will be extracted while decoding [`DestAddress`].
143    //!
144    //! Another implementation for [`DestAddress`] that looks like `Pdu` or `Tlv` requires using the [`DestFlag`] as a key for decoding the `DestAddressVariant`,
145    //! and making [`DestAddress`] a struct with a `dest_flag` field and a `variant` field.
146    //! This means we should implement `DecodeWithKey` for `DestAddressVariant` with the [`DestFlag`] as a key.
147    //! But `DecodeWithKey` needs a `length` parameter, and our macro supports only `key` and `length` attributes.
148    //! So we have to create new trait that uses a key but does not require a length, and we have to update our macro to support only a key without a length.
149
150    use super::*;
151
152    impl crate::tests::TestInstance for DestAddress<'static> {
153        fn instances() -> alloc::vec::Vec<Self> {
154            alloc::vec![
155                Self::SmeAddress(SmeAddress::new(
156                    Ton::International,
157                    Npi::Isdn,
158                    COctetString::new(b"1234567890123456789\0").unwrap(),
159                )),
160                Self::DistributionListName(DistributionListName::new(
161                    COctetString::new(b"1234567890123456789\0").unwrap(),
162                )),
163            ]
164        }
165    }
166
167    #[test]
168    fn encode_decode() {
169        crate::tests::borrowed::encode_decode_test_instances::<DestAddress>();
170    }
171}