rusmpp_core/values/dest_address/
owned.rs

1use rusmpp_macros::Rusmpp;
2
3use crate::{
4    decode::{
5        DecodeError, DecodeResultExt,
6        owned::{Decode, DecodeExt},
7    },
8    encode::{Encode, Length},
9    types::owned::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))]
16#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
17pub enum DestAddress {
18    /// SME Format Destination Address.
19    SmeAddress(SmeAddress),
20    /// Distribution List Format Destination Address.
21    DistributionListName(DistributionListName),
22}
23
24impl Length for DestAddress {
25    fn length(&self) -> usize {
26        match self {
27            Self::SmeAddress(sa) => sa.length(),
28            Self::DistributionListName(dlm) => dlm.length(),
29        }
30    }
31}
32
33impl Encode for DestAddress {
34    fn encode(&self, dst: &mut [u8]) -> usize {
35        match self {
36            Self::SmeAddress(sa) => sa.encode(dst),
37            Self::DistributionListName(dlm) => dlm.encode(dst),
38        }
39    }
40}
41
42impl Decode for DestAddress {
43    fn decode(src: &[u8]) -> Result<(Self, usize), DecodeError> {
44        let size = 0;
45
46        let (flag, size) = DestFlag::decode_move(src, size)?;
47
48        match flag {
49            DestFlag::SmeAddress => {
50                SmeAddress::decode_move(src, size).map_decoded(Self::SmeAddress)
51            }
52            DestFlag::DistributionListName => {
53                DistributionListName::decode_move(src, size).map_decoded(Self::DistributionListName)
54            }
55            DestFlag::Other(flag) => Err(DecodeError::unsupported_key(flag.into())),
56        }
57    }
58}
59
60/// SME Format Destination Address.
61#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
62#[rusmpp(decode = owned, test = skip)]
63#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
64#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
65#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
66pub struct SmeAddress {
67    /// 0x01 (SME Address).
68    ///
69    /// Can't and shouldn't be updated
70    #[rusmpp(skip_decode)]
71    dest_flag: DestFlag,
72    /// Type of Number for destination.
73    pub dest_addr_ton: Ton,
74    /// Numbering Plan Indicator for destination.
75    pub dest_addr_npi: Npi,
76    /// Destination address of this short message. For mobile
77    /// terminated messages, this is the directory number of the
78    /// recipient MS.
79    pub destination_addr: COctetString<1, 21>,
80}
81
82impl SmeAddress {
83    pub const fn new(
84        dest_addr_ton: Ton,
85        dest_addr_npi: Npi,
86        destination_addr: COctetString<1, 21>,
87    ) -> Self {
88        Self {
89            dest_flag: DestFlag::SmeAddress,
90            dest_addr_ton,
91            dest_addr_npi,
92            destination_addr,
93        }
94    }
95
96    pub fn dest_flag(&self) -> DestFlag {
97        self.dest_flag
98    }
99}
100
101/// Distribution List Format Destination Address.
102#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
103#[rusmpp(decode = owned, test = skip)]
104#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
105#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
106#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
107pub struct DistributionListName {
108    /// 0x02 (Distribution List).
109    ///
110    /// Can't and shouldn't be updated.
111    #[rusmpp(skip_decode)]
112    dest_flag: DestFlag,
113    /// Name of Distribution List.
114    pub dl_name: COctetString<1, 21>,
115}
116
117impl DistributionListName {
118    pub fn new(dl_name: COctetString<1, 21>) -> Self {
119        Self {
120            dest_flag: DestFlag::DistributionListName,
121            dl_name,
122        }
123    }
124
125    pub fn dest_flag(&self) -> DestFlag {
126        self.dest_flag
127    }
128}
129
130#[cfg(test)]
131mod tests {
132    //! See tests in [borrowed](super::super::borrowed) for more details.
133
134    use super::*;
135
136    impl crate::tests::TestInstance for DestAddress {
137        fn instances() -> alloc::vec::Vec<Self> {
138            alloc::vec![
139                Self::SmeAddress(SmeAddress::new(
140                    Ton::International,
141                    Npi::Isdn,
142                    COctetString::new(b"1234567890123456789\0").unwrap(),
143                )),
144                Self::DistributionListName(DistributionListName::new(
145                    COctetString::new(b"1234567890123456789\0").unwrap(),
146                )),
147            ]
148        }
149    }
150
151    #[test]
152    fn encode_decode() {
153        crate::tests::owned::encode_decode_test_instances::<DestAddress>();
154    }
155}