rusmpp_core/values/
esm_class.rs

1use rusmpp_macros::Rusmpp;
2
3/// Indicates Message Mode and Message Type.
4///
5/// The esm_class parameter is used to indicate special message attributes associated with the
6/// short message.
7///
8/// The esm_class parameter is encoded as follows in the submit_sm, submit_multi and
9/// data_sm (ESME -> MC) PDUs
10#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Rusmpp)]
11#[rusmpp(repr = "u8", test = skip)]
12#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
13#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
14#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
15pub struct EsmClass {
16    /// Messaging Mode (bits 1-0).
17    pub messaging_mode: MessagingMode,
18    /// Message Type (bits 2 and 5).
19    pub message_type: MessageType,
20    /// ANSI-41 Specific (bits 5-2).
21    pub ansi41_specific: Ansi41Specific,
22    /// GSM Specific (bits 7-6).
23    pub gsm_features: GsmFeatures,
24}
25
26impl EsmClass {
27    pub fn new(
28        messaging_mode: MessagingMode,
29        message_type: MessageType,
30        ansi41_specific: Ansi41Specific,
31        gsm_features: GsmFeatures,
32    ) -> Self {
33        Self {
34            messaging_mode,
35            message_type,
36            ansi41_specific,
37            gsm_features,
38        }
39    }
40
41    /// Sets the UDH Indicator bit in the GSM Features field.
42    pub const fn with_udhi_indicator(self) -> Self {
43        Self {
44            messaging_mode: self.messaging_mode,
45            message_type: self.message_type,
46            ansi41_specific: self.ansi41_specific,
47            gsm_features: GsmFeatures::UdhiIndicator,
48        }
49    }
50}
51
52impl From<u8> for EsmClass {
53    fn from(value: u8) -> Self {
54        Self {
55            messaging_mode: MessagingMode::from(value & 0b00_00_00_11),
56            message_type: MessageType::from(value & 0b00_10_01_00),
57            ansi41_specific: Ansi41Specific::from(value & 0b00_01_10_00),
58            gsm_features: GsmFeatures::from(value & 0b11_00_00_00),
59        }
60    }
61}
62
63impl From<EsmClass> for u8 {
64    fn from(value: EsmClass) -> Self {
65        u8::from(value.messaging_mode)
66            | u8::from(value.message_type)
67            | u8::from(value.ansi41_specific)
68            | u8::from(value.gsm_features)
69    }
70}
71
72/// Messaging Mode (bits 1-0).
73#[repr(u8)]
74#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Rusmpp)]
75#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
76#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
77#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
78pub enum MessagingMode {
79    /// Default MC Mode (e.g. Store and Forward).
80    #[default]
81    Default = 0b00_00_00_00,
82    /// Datagram mode.
83    Datagram = 0b00_00_00_01,
84    /// Forward (i.e. Transaction) mode.
85    Forward = 0b00_00_00_10,
86    /// Store and Forward mode
87    ///
88    /// (use to select Store and Forward mode if Default MC
89    /// Mode is non Store and Forward).
90    StoreAndForward = 0b00_00_00_11,
91    Other(u8),
92}
93
94/// Message Type (bits 2 and 5).
95#[repr(u8)]
96#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Rusmpp)]
97#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
98#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
99#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
100pub enum MessageType {
101    /// Default message Type (i.e. normal message).
102    #[default]
103    Default = 0b00_00_00_00,
104    /// Short Message contains MC Delivery Receipt.
105    ShortMessageContainsMCDeliveryReceipt = 0b00_00_01_00,
106    /// Short Message contains Intermediate Delivery Notification.
107    ShortMessageContainsIntermediateDeliveryNotification = 0b00_10_00_00,
108    Other(u8),
109}
110
111/// ANSI-41 Specific (bits 5-2).
112#[repr(u8)]
113#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Rusmpp)]
114#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
115#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
116#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
117pub enum Ansi41Specific {
118    /// Short Message contains Delivery Acknowledgement.
119    #[default]
120    ShortMessageContainsDeliveryAcknowledgement = 0b00_00_10_00,
121    /// Short Message contains Manual/User Acknowledgement.
122    ShortMessageContainsUserAcknowledgment = 0b00_01_00_00,
123    /// Short Message contains Conversation Abort (Korean CDMA).
124    ShortMessageContainsConversationAbort = 0b00_01_10_00,
125    Other(u8),
126}
127
128/// GSM Specific (bits 7-6).
129#[repr(u8)]
130#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Rusmpp)]
131#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
132#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
133#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
134pub enum GsmFeatures {
135    /// No specific features selected.
136    #[default]
137    NotSelected = 0b00_00_00_00,
138    /// UDH Indicator.
139    UdhiIndicator = 0b01_00_00_00,
140    /// Set Reply Path (only relevant for GSM network).
141    SetReplyPath = 0b10_00_00_00,
142    /// Set UDHI and Reply Path (only relevant for GSM network).
143    SetUdhiAndReplyPath = 0b11_00_00_00,
144    Other(u8),
145}
146
147#[cfg(test)]
148mod tests {
149    use crate::tests::TestInstance;
150
151    use super::*;
152
153    impl TestInstance for EsmClass {
154        fn instances() -> alloc::vec::Vec<Self> {
155            alloc::vec![
156                Self::default(),
157                Self::new(
158                    MessagingMode::Forward,
159                    MessageType::ShortMessageContainsIntermediateDeliveryNotification,
160                    Ansi41Specific::ShortMessageContainsConversationAbort,
161                    GsmFeatures::UdhiIndicator,
162                ),
163                Self::new(
164                    MessagingMode::Datagram,
165                    MessageType::ShortMessageContainsMCDeliveryReceipt,
166                    Ansi41Specific::ShortMessageContainsUserAcknowledgment,
167                    GsmFeatures::UdhiIndicator,
168                ),
169            ]
170        }
171    }
172
173    #[test]
174    fn encode_decode() {
175        #[cfg(feature = "alloc")]
176        crate::tests::owned::encode_decode_test_instances::<EsmClass>();
177        crate::tests::borrowed::encode_decode_test_instances::<EsmClass>();
178        #[cfg(feature = "alloc")]
179        crate::tests::owned::encode_decode_test_instances::<MessagingMode>();
180        crate::tests::borrowed::encode_decode_test_instances::<MessagingMode>();
181        #[cfg(feature = "alloc")]
182        crate::tests::owned::encode_decode_test_instances::<MessageType>();
183        crate::tests::borrowed::encode_decode_test_instances::<MessageType>();
184        #[cfg(feature = "alloc")]
185        crate::tests::owned::encode_decode_test_instances::<Ansi41Specific>();
186        crate::tests::borrowed::encode_decode_test_instances::<GsmFeatures>();
187    }
188}