http_request/response/response_binary/
impl.rs

1use crate::*;
2
3/// Implements the `ResponseTrait` trait for `HttpResponseBinary`.
4///
5/// This implementation specifies the associated types for binary and text representations
6/// of HTTP responses, enabling seamless conversion and handling of HTTP response data.
7///
8/// # Associated Types
9/// - `OutputText`: Specifies the text representation of an HTTP response (`HttpResponseText`).
10/// - `OutputBinary`: Specifies the binary representation of an HTTP response (`HttpResponseBinary`).
11impl ResponseTrait for HttpResponseBinary {
12    type OutputText = HttpResponseText;
13    type OutputBinary = HttpResponseBinary;
14    /// Creates a new HttpResponseBinary from raw response bytes.
15    ///
16    /// # Arguments
17    ///
18    /// - `&[u8]` - The raw HTTP response bytes.
19    ///
20    /// # Returns
21    ///
22    /// - `Self` - The parsed HttpResponseBinary.
23    fn from(response: &[u8]) -> Self
24    where
25        Self: Sized,
26    {
27        let split_lines: Vec<&[u8]> = split_multi_byte(response, HTTP_BR_BYTES);
28        let mut lines: IntoIter<&[u8]> = split_lines.into_iter();
29        let status_line: &[u8] = lines.next().unwrap_or(&[]);
30        let status_parts: Vec<&[u8]> = split_whitespace(&status_line);
31        let http_version: HttpVersion = status_parts
32            .get(0)
33            .and_then(|part: &&[u8]| from_utf8(part).ok())
34            .and_then(|version_str: &str| version_str.parse::<HttpVersion>().ok())
35            .unwrap_or_default();
36        let status_code: ResponseStatusCode = status_parts
37            .get(1)
38            .and_then(|part: &&[u8]| from_utf8(part).ok())
39            .and_then(|code_str: &str| code_str.parse().ok())
40            .unwrap_or(HttpStatus::Unknown.code());
41        let status_text: String = status_parts.get(2..).map_or_else(
42            || HttpStatus::Unknown.to_string(),
43            |parts: &[&[u8]]| {
44                if parts.is_empty() {
45                    HttpStatus::Unknown.to_string()
46                } else if parts.len() == 1 {
47                    String::from_utf8_lossy(parts[0]).into_owned()
48                } else {
49                    let total_len: usize =
50                        parts.iter().map(|p: &&[u8]| p.len()).sum::<usize>() + parts.len() - 1;
51                    let mut result: String = String::with_capacity(total_len);
52                    for (i, part) in parts.iter().enumerate() {
53                        if i > 0 {
54                            result.push(' ');
55                        }
56                        result.push_str(&String::from_utf8_lossy(part));
57                    }
58                    result
59                }
60            },
61        );
62        let mut headers: HashMapXxHash3_64<String, VecDeque<String>> = hash_map_xx_hash3_64();
63        for line in lines.by_ref() {
64            if line.is_empty() {
65                break;
66            }
67            let mut colon_pos: Option<usize> = None;
68            for (i, &byte) in line.iter().enumerate() {
69                if byte == b':' {
70                    colon_pos = Some(i);
71                    break;
72                }
73            }
74            if let Some(pos) = colon_pos {
75                if pos > 0 && pos + 1 < line.len() {
76                    let key_bytes: &[u8] = &line[..pos];
77                    let value_start: usize = if line.get(pos + 1) == Some(&b' ') {
78                        pos + 2
79                    } else {
80                        pos + 1
81                    };
82                    let value_bytes: &[u8] = &line[value_start..];
83                    if let (Ok(key_str), Ok(value_str)) =
84                        (from_utf8(key_bytes), from_utf8(value_bytes))
85                    {
86                        let mut value_deque: VecDeque<String> = VecDeque::new();
87                        value_deque.push_front(value_str.trim().to_string());
88                        headers.insert(key_str.trim().to_string(), value_deque);
89                    }
90                }
91            }
92        }
93        let body: Vec<u8> = match lines.len() {
94            0 => Vec::new(),
95            1 => {
96                let line: &[u8] = lines.next().unwrap_or(&[]);
97                let mut body = Vec::with_capacity(line.len());
98                body.extend_from_slice(line);
99                body
100            }
101            _ => {
102                let lines_slice: &[&[u8]] = lines.as_slice();
103                let total_size: usize = lines_slice
104                    .iter()
105                    .map(|line: &&[u8]| line.len())
106                    .sum::<usize>()
107                    + lines_slice.len().saturating_sub(1) * BR_BYTES.len();
108                let mut body: Vec<u8> = Vec::with_capacity(total_size);
109                let mut first: bool = true;
110                for line in lines {
111                    if !first {
112                        body.extend_from_slice(BR_BYTES);
113                    }
114                    body.extend_from_slice(line);
115                    first = false;
116                }
117                body
118            }
119        };
120        HttpResponseBinary {
121            http_version: Arc::new(RwLock::new(http_version)),
122            status_code,
123            status_text: Arc::new(RwLock::new(status_text)),
124            headers: Arc::new(RwLock::new(headers)),
125            body: Arc::new(RwLock::new(body)),
126        }
127    }
128
129    /// Converts the response to binary format.
130    ///
131    /// # Returns
132    ///
133    /// - `Self::OutputBinary` - The binary representation of the response.
134    fn binary(&self) -> Self::OutputBinary {
135        self.clone()
136    }
137
138    /// Converts the response to text format.
139    ///
140    /// # Returns
141    ///
142    /// - `HttpResponseText` - The text representation of the response.
143    fn text(&self) -> HttpResponseText {
144        let body: String = self.body.read().map_or(String::new(), |body_ref| {
145            String::from_utf8_lossy(&body_ref).into_owned()
146        });
147        HttpResponseText {
148            http_version: Arc::clone(&self.http_version),
149            status_code: self.status_code,
150            status_text: Arc::clone(&self.status_text),
151            headers: Arc::clone(&self.headers),
152            body: Arc::new(RwLock::new(body)),
153        }
154    }
155
156    /// Decodes the response body using the specified buffer size.
157    ///
158    /// # Arguments
159    ///
160    /// - `usize` - The buffer size for decoding.
161    ///
162    /// # Returns
163    ///
164    /// - `HttpResponseBinary` - The decoded binary response.
165    fn decode(&self, buffer_size: usize) -> HttpResponseBinary {
166        let decoded_body: Vec<u8> = {
167            let headers_guard = self.headers.read();
168            let body_guard = self.body.read();
169            match (headers_guard, body_guard) {
170                (Ok(headers_ref), Ok(body_ref)) => {
171                    let mut string_headers: HashMapXxHash3_64<String, String> =
172                        hash_map_xx_hash3_64();
173                    for (key, value_deque) in headers_ref.iter() {
174                        if let Some(first_value) = value_deque.front() {
175                            string_headers.insert(key.clone(), first_value.clone());
176                        }
177                    }
178                    Compress::from(&string_headers)
179                        .decode(&*body_ref, buffer_size)
180                        .into_owned()
181                }
182                _ => Vec::new(),
183            }
184        };
185        HttpResponseBinary {
186            http_version: Arc::clone(&self.http_version),
187            status_code: self.status_code,
188            status_text: Arc::clone(&self.status_text),
189            headers: Arc::clone(&self.headers),
190            body: Arc::new(RwLock::new(decoded_body)),
191        }
192    }
193}
194
195impl HttpResponseBinary {
196    /// Retrieves the HTTP version associated with this response.
197    ///
198    /// # Returns
199    /// - `HttpVersion`: The HTTP version used for the response.
200    /// Gets the HTTP version of the response.
201    ///
202    /// # Returns
203    ///
204    /// - `HttpVersion` - The HTTP version.
205    pub fn get_http_version(&self) -> HttpVersion {
206        if let Ok(http_version) = self.http_version.read() {
207            return http_version
208                .to_string()
209                .parse::<HttpVersion>()
210                .unwrap_or_default();
211        }
212        return HttpVersion::default();
213    }
214
215    /// Retrieves the HTTP status code associated with this response.
216    ///
217    /// # Returns
218    /// - `ResponseStatusCode`: The HTTP status code as a usize.
219    /// Gets the HTTP status code of the response.
220    ///
221    /// # Returns
222    ///
223    /// - `ResponseStatusCode` - The status code.
224    pub fn get_status_code(&self) -> ResponseStatusCode {
225        self.status_code
226    }
227
228    /// Retrieves the status text associated with the HTTP status code.
229    ///
230    /// # Returns
231    /// - `String`: The human-readable status text.
232    /// Gets the HTTP status text of the response.
233    ///
234    /// # Returns
235    ///
236    /// - `String` - The status text.
237    pub fn get_status_text(&self) -> String {
238        if let Ok(status_text) = self.status_text.read() {
239            return status_text.to_string();
240        }
241        return HttpStatus::default().to_string();
242    }
243
244    /// Retrieves the headers of the HTTP response.
245    ///
246    /// # Returns
247    /// - `ResponseHeaders`: A map of header names and their corresponding values as key-value pairs.
248    /// Gets the HTTP response headers.
249    ///
250    /// # Returns
251    ///
252    /// - `ResponseHeaders` - The response headers.
253    pub fn get_headers(&self) -> ResponseHeaders {
254        if let Ok(headers) = self.headers.read() {
255            return headers.clone();
256        }
257        return hash_map_xx_hash3_64();
258    }
259
260    /// Retrieves the body content of the HTTP response.
261    ///
262    /// # Returns
263    /// - `RequestBody`: The body of the response in binary form (could be raw bytes, a stream, etc.).
264    /// Gets the HTTP response body.
265    ///
266    /// # Returns
267    ///
268    /// - `RequestBody` - The response body.
269    pub fn get_body(&self) -> RequestBody {
270        if let Ok(body) = self.body.read() {
271            return body.clone();
272        }
273        return RequestBody::new();
274    }
275}
276
277/// Default implementation for HttpResponseBinary.
278///
279/// # Returns
280///
281/// - `HttpResponseBinary` - Default initialized HttpResponseBinary.
282impl Default for HttpResponseBinary {
283    fn default() -> Self {
284        Self {
285            http_version: Arc::new(RwLock::new(HttpVersion::Unknown(String::new()))),
286            status_code: HttpStatus::Unknown.code(),
287            status_text: Arc::new(RwLock::new(HttpStatus::Unknown.to_string())),
288            headers: Arc::new(RwLock::new(hash_map_xx_hash3_64())),
289            body: Arc::new(RwLock::new(Vec::new())),
290        }
291    }
292}