simbld_http/helpers/
http_code_helper.rs

1//! # HTTP Status Code Representation
2//!
3//! This module provides a standardized way to represent and work with HTTP status codes.
4//! It defines the `HttpCode` struct which encapsulates both standard HTTP status codes
5//! and custom internal codes used for application-specific error tracking.
6//!
7//! The module supports conversion between different representations of HTTP codes and
8//! provides utilities for serializing them in a consistent format.
9
10use crate::traits::into_http_code_trait::IntoHttpCode;
11use serde::Serialize;
12
13/// Represents an HTTP status code with standard and internal identifiers.
14///
15/// This structure combines standard HTTP status codes (like 200, 404) with optional
16/// internal application-specific codes for more detailed error tracking and reporting.
17///
18#[derive(Debug, Clone, Copy, Serialize, PartialEq)]
19pub struct HttpCode {
20    /// Standard HTTP status code.
21    pub standard_code: u16,
22    /// Standard HTTP status message.
23    pub standard_name: &'static str,
24    /// Unified description of the HTTP response.
25    pub unified_description: &'static str,
26    /// Optional internal HTTP status code.
27    pub internal_code: Option<u16>,
28    /// Optional internal HTTP status name.
29    pub internal_name: Option<&'static str>,
30}
31
32/// Implement IntoHttpCode for u16, converting it to an HttpCode with default values.
33impl IntoHttpCode for (u16, &'static str, &'static str) {
34    /// Converts a tuple of (code, name, description) into an HttpCode.
35    fn into_http_code(self) -> HttpCode {
36        let (standard_code, standard_name, unified_description) = self;
37        HttpCode {
38            standard_code,
39            standard_name,
40            unified_description,
41            internal_code: None,
42            internal_name: None,
43        }
44    }
45}
46
47impl HttpCode {
48    /// Creates a new HttpCode with both standard and internal identifiers.
49    ///
50    /// # Arguments
51    /// * `standard_code` - The standard HTTP status code
52    /// * `standard_name` - The standard HTTP status name
53    /// * `unified_description` - Human-readable description
54    /// * `internal_code` - Application-specific status code
55    /// * `internal_name` - Application-specific status name
56    pub fn new(
57        standard_code: u16,
58        standard_name: &'static str,
59        unified_description: &'static str,
60        internal_code: u16,
61        internal_name: &'static str,
62    ) -> Self {
63        let (int_code, int_name) = if standard_code == internal_code {
64            (None, None)
65        } else {
66            (Some(internal_code), Some(internal_name))
67        };
68        HttpCode {
69            standard_code,
70            standard_name,
71            unified_description,
72            internal_code: int_code,
73            internal_name: int_name,
74        }
75    }
76
77    /// Returns the standard HTTP status code.
78    pub fn get_code(&self) -> u16 {
79        self.standard_code
80    }
81
82    /// Converts the HttpCode to a UnifiedTuple representation for consistent formatting.
83    pub fn as_unified_tuple(&self) -> crate::helpers::unified_tuple_helper::UnifiedTuple {
84        crate::helpers::unified_tuple_helper::UnifiedTuple {
85            standard_code: self.standard_code,
86            standard_name: self.standard_name,
87            unified_description: self.unified_description,
88            internal_code: self.internal_code,
89            internal_name: self.internal_name,
90        }
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97    use crate::helpers::unified_tuple_helper::UnifiedTuple;
98    use serde_json::json;
99
100    /// Tests the creation of an HttpCode with the new() constructor.
101    #[test]
102    fn test_http_code_new() {
103        let http_code = HttpCode::new(200, "ContentDeleted", "File deleted", 215, "Accepted");
104        assert_eq!(http_code.standard_code, 200);
105        assert_eq!(http_code.standard_name, "ContentDeleted");
106        assert_eq!(http_code.unified_description, "File deleted");
107        assert_eq!(http_code.internal_code, Some(215));
108        assert_eq!(http_code.internal_name, Some("Accepted"));
109    }
110
111    /// Tests conversion to UnifiedTuple with only standard fields.
112    #[test]
113    fn test_http_code_as_unified_tuple() {
114        let http_code = HttpCode::new(202, "Accepted", "Request processed", 202, "Accepted");
115        let unified_tuple = http_code.as_unified_tuple();
116        let expected_tuple = UnifiedTuple {
117            standard_code: 202,
118            standard_name: "Accepted",
119            unified_description: "Request processed",
120            internal_code: None,
121            internal_name: None,
122        };
123        assert_eq!(unified_tuple, expected_tuple);
124    }
125
126    /// Tests conversion to UnifiedTuple with both standard and internal fields.
127    #[test]
128    fn test_http_code_as_unified_tuple_with_internal() {
129        let http_code = HttpCode::new(
130            202,
131            "Accepted",
132            "Request processed",
133            203,
134            "Non-Authoritative Information",
135        );
136        let unified_tuple = http_code.as_unified_tuple();
137        let expected_tuple = UnifiedTuple {
138            standard_code: 202,
139            standard_name: "Accepted",
140            unified_description: "Request processed",
141            internal_code: Some(203),
142            internal_name: Some("Non-Authoritative Information"),
143        };
144        assert_eq!(unified_tuple, expected_tuple);
145    }
146
147    /// Tests the get_code method returns the correct standard code.
148    #[test]
149    fn test_http_code_get_code() {
150        let http_code = HttpCode::new(202, "Accepted", "Request processed", 202, "Accepted");
151        assert_eq!(http_code.get_code(), 202);
152    }
153
154    /// Tests JSON serialization of HttpCode instances.
155    #[test]
156    fn test_http_code_as_json() {
157        let http_code = HttpCode::new(202, "Accepted", "Request processed", 202, "Accepted");
158        let unified_tuple = http_code.as_unified_tuple();
159        let json_result = serde_json::to_value(&unified_tuple).unwrap();
160        let expected_json = json!({
161            "standard_code": 202,
162            "standard_name": "Accepted",
163            "unified_description": "Request processed",
164            "internal_code": null,
165            "internal_name": null
166        });
167        assert_eq!(json_result, expected_json);
168    }
169}