smpp_codec/pdus/session_pdus/unbind.rs
1use crate::common::{
2 get_status_code, get_status_description, PduError, CMD_UNBIND, CMD_UNBIND_RESP, HEADER_LEN,
3};
4use std::io::{Cursor, Read, Write};
5
6// --- Unbind Request ---
7#[derive(Debug, Clone)]
8pub struct UnbindRequest {
9 pub sequence_number: u32,
10}
11
12impl UnbindRequest {
13 /// Create a new Unbind Request.
14 ///
15 /// # Examples
16 ///
17 /// ```
18 /// use smpp_codec::pdus::UnbindRequest;
19 ///
20 /// let sequence_number: u32 = 1;
21 /// let unbind_req = UnbindRequest::new(sequence_number);
22 /// ```
23 pub fn new(sequence_number: u32) -> Self {
24 Self { sequence_number }
25 }
26
27 /// Encode the struct into raw bytes for the network.
28 ///
29 /// # Errors
30 ///
31 /// Returns a [`PduError`] if an I/O error occurs while writing.
32 ///
33 /// # Examples
34 ///
35 /// ```
36 /// # use smpp_codec::pdus::UnbindRequest;
37 /// # let sequence_number: u32 = 1;
38 /// # let unbind_req = UnbindRequest::new(sequence_number);
39 /// let mut buffer = Vec::new();
40 /// unbind_req.encode(&mut buffer).expect("Encoding failed");
41 /// ```
42 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
43 let command_len = HEADER_LEN as u32;
44 writer.write_all(&command_len.to_be_bytes())?;
45 writer.write_all(&CMD_UNBIND.to_be_bytes())?;
46 writer.write_all(&0u32.to_be_bytes())?; // Status always 0 for requests
47 writer.write_all(&self.sequence_number.to_be_bytes())?;
48 Ok(())
49 }
50
51 /// Decode raw bytes from the network into the struct.
52 ///
53 /// # Errors
54 ///
55 /// Returns a [`PduError`] if the buffer is too short.
56 ///
57 /// # Examples
58 ///
59 /// ```
60 /// # use smpp_codec::pdus::UnbindRequest;
61 /// # let sequence_number: u32 = 1;
62 /// # let unbind_req = UnbindRequest::new(sequence_number);
63 /// # let mut buffer = Vec::new();
64 /// # unbind_req.encode(&mut buffer).unwrap();
65 /// let decoded = UnbindRequest::decode(&buffer).expect("Decoding failed");
66 /// assert_eq!(decoded.sequence_number, 1);
67 /// ```
68 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
69 if buffer.len() < HEADER_LEN {
70 return Err(PduError::BufferTooShort);
71 }
72 let mut cursor = Cursor::new(buffer);
73 cursor.set_position(12); // Skip len, id, status
74
75 let mut bytes = [0u8; 4];
76 cursor.read_exact(&mut bytes)?;
77 let sequence_number = u32::from_be_bytes(bytes);
78
79 Ok(Self { sequence_number })
80 }
81}
82
83// --- Unbind Response ---
84#[derive(Debug, Clone)]
85pub struct UnbindResponse {
86 pub sequence_number: u32,
87 pub command_status: u32,
88 pub status_description: String,
89}
90
91impl UnbindResponse {
92 /// Create a new Unbind Response.
93 ///
94 /// # Examples
95 ///
96 /// ```
97 /// use smpp_codec::pdus::UnbindResponse;
98 ///
99 /// let sequence_number: u32 = 1;
100 /// let unbind_resp = UnbindResponse::new(sequence_number, "ESME_ROK");
101 /// ```
102 pub fn new(sequence_number: u32, status_name: &str) -> Self {
103 let command_status = get_status_code(status_name);
104 Self {
105 sequence_number,
106 command_status,
107 status_description: status_name.to_string(),
108 }
109 }
110
111 /// Encode the struct into raw bytes for the network.
112 ///
113 /// # Errors
114 ///
115 /// Returns a [`PduError`] if an I/O error occurs while writing.
116 ///
117 /// # Examples
118 ///
119 /// ```
120 /// # use smpp_codec::pdus::UnbindResponse;
121 /// # let sequence_number: u32 = 1;
122 /// # let unbind_resp = UnbindResponse::new(sequence_number, "ESME_ROK");
123 /// let mut buffer = Vec::new();
124 /// unbind_resp.encode(&mut buffer).expect("Encoding failed");
125 /// ```
126 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
127 let command_len = HEADER_LEN as u32;
128 writer.write_all(&command_len.to_be_bytes())?;
129 writer.write_all(&CMD_UNBIND_RESP.to_be_bytes())?;
130 writer.write_all(&self.command_status.to_be_bytes())?;
131 writer.write_all(&self.sequence_number.to_be_bytes())?;
132 Ok(())
133 }
134
135 /// Decode raw bytes from the network into the struct.
136 ///
137 /// # Errors
138 ///
139 /// Returns a [`PduError`] if the buffer is too short.
140 ///
141 /// # Examples
142 ///
143 /// ```
144 /// # use smpp_codec::pdus::UnbindResponse;
145 /// # let sequence_number: u32 = 1;
146 /// # let unbind_resp = UnbindResponse::new(sequence_number, "ESME_ROK");
147 /// # let mut buffer = Vec::new();
148 /// # unbind_resp.encode(&mut buffer).unwrap();
149 /// let decoded = UnbindResponse::decode(&buffer).expect("Decoding failed");
150 /// assert_eq!(decoded.sequence_number, 1);
151 /// ```
152 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
153 if buffer.len() < HEADER_LEN {
154 return Err(PduError::BufferTooShort);
155 }
156 let mut cursor = Cursor::new(buffer);
157
158 // Skip Length (4) + ID (4)
159 cursor.set_position(8);
160
161 let mut bytes = [0u8; 4];
162
163 // Read Status
164 cursor.read_exact(&mut bytes)?;
165 let command_status = u32::from_be_bytes(bytes);
166
167 // Read Sequence
168 cursor.read_exact(&mut bytes)?;
169 let sequence_number = u32::from_be_bytes(bytes);
170
171 Ok(Self {
172 sequence_number,
173 command_status,
174 status_description: get_status_description(command_status),
175 })
176 }
177}