nginx_sys/
string.rs

1use core::cmp;
2use core::fmt;
3use core::hash;
4use core::ptr;
5use core::slice;
6use core::str;
7
8use crate::bindings::{ngx_pool_t, ngx_str_t};
9use crate::detail;
10
11impl ngx_str_t {
12    /// Returns the contents of this `ngx_str_t` as a byte slice.
13    ///
14    /// The returned slice will **not** contain the optional nul terminator that `ngx_str_t.data`
15    /// may have.
16    #[inline]
17    pub fn as_bytes(&self) -> &[u8] {
18        if self.is_empty() {
19            &[]
20        } else {
21            // SAFETY: `ngx_str_t` with non-zero len must contain a valid correctly aligned pointer
22            unsafe { slice::from_raw_parts(self.data, self.len) }
23        }
24    }
25
26    /// Returns the contents of this `ngx_str_t` as a mutable byte slice.
27    #[inline]
28    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
29        if self.is_empty() {
30            &mut []
31        } else {
32            // SAFETY: `ngx_str_t` with non-zero len must contain a valid correctly aligned pointer
33            unsafe { slice::from_raw_parts_mut(self.data, self.len) }
34        }
35    }
36
37    /// Returns `true` if the string has a length of 0.
38    #[inline]
39    pub fn is_empty(&self) -> bool {
40        self.len == 0
41    }
42
43    /// Convert the nginx string to a string slice (`&str`).
44    ///
45    /// # Panics
46    /// This function panics if the `ngx_str_t` is not valid UTF-8.
47    ///
48    /// # Returns
49    /// A string slice (`&str`) representing the nginx string.
50    pub fn to_str(&self) -> &str {
51        str::from_utf8(self.as_bytes()).unwrap()
52    }
53
54    /// Creates an empty `ngx_str_t` instance.
55    ///
56    /// This method replaces the `ngx_null_string` C macro.
57    pub const fn empty() -> Self {
58        ngx_str_t {
59            len: 0,
60            data: ptr::null_mut(),
61        }
62    }
63
64    /// Create an `ngx_str_t` instance from a byte slice.
65    ///
66    /// # Safety
67    ///
68    /// The caller must provide a valid pointer to a memory pool.
69    pub unsafe fn from_bytes(pool: *mut ngx_pool_t, src: &[u8]) -> Option<Self> {
70        detail::bytes_to_uchar(pool, src).map(|data| Self {
71            data,
72            len: src.len(),
73        })
74    }
75
76    /// Create an `ngx_str_t` instance from a string slice (`&str`).
77    ///
78    /// # Arguments
79    ///
80    /// * `pool` - A pointer to the nginx memory pool (`ngx_pool_t`).
81    /// * `data` - The string slice from which to create the nginx string.
82    ///
83    /// # Safety
84    /// This function is marked as unsafe because it accepts a raw pointer argument. There is no
85    /// way to know if `pool` is pointing to valid memory. The caller must provide a valid pool to
86    /// avoid indeterminate behavior.
87    ///
88    /// # Returns
89    /// An `ngx_str_t` instance representing the given string slice.
90    pub unsafe fn from_str(pool: *mut ngx_pool_t, data: &str) -> Self {
91        ngx_str_t {
92            data: detail::str_to_uchar(pool, data),
93            len: data.len(),
94        }
95    }
96}
97
98impl AsRef<[u8]> for ngx_str_t {
99    fn as_ref(&self) -> &[u8] {
100        self.as_bytes()
101    }
102}
103
104impl AsMut<[u8]> for ngx_str_t {
105    fn as_mut(&mut self) -> &mut [u8] {
106        self.as_bytes_mut()
107    }
108}
109
110impl Default for ngx_str_t {
111    fn default() -> Self {
112        Self::empty()
113    }
114}
115
116impl fmt::Display for ngx_str_t {
117    #[inline]
118    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119        detail::display_bytes(f, self.as_bytes())
120    }
121}
122
123impl From<ngx_str_t> for &[u8] {
124    fn from(s: ngx_str_t) -> Self {
125        if s.len == 0 || s.data.is_null() {
126            return Default::default();
127        }
128        unsafe { slice::from_raw_parts(s.data, s.len) }
129    }
130}
131
132impl hash::Hash for ngx_str_t {
133    fn hash<H: hash::Hasher>(&self, state: &mut H) {
134        self.as_bytes().hash(state)
135    }
136}
137
138impl PartialEq for ngx_str_t {
139    fn eq(&self, other: &Self) -> bool {
140        PartialEq::eq(self.as_bytes(), other.as_bytes())
141    }
142}
143
144impl Eq for ngx_str_t {}
145
146impl PartialOrd<Self> for ngx_str_t {
147    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
148        Some(self.cmp(other))
149    }
150}
151
152impl Ord for ngx_str_t {
153    fn cmp(&self, other: &Self) -> cmp::Ordering {
154        Ord::cmp(self.as_bytes(), other.as_bytes())
155    }
156}
157
158impl TryFrom<ngx_str_t> for &str {
159    type Error = str::Utf8Error;
160
161    fn try_from(s: ngx_str_t) -> Result<Self, Self::Error> {
162        str::from_utf8(s.into())
163    }
164}