forked from nginx/ngx-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstring.rs
101 lines (88 loc) · 2.8 KB
/
string.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use crate::ffi::*;
use std::borrow::Cow;
use std::slice;
use std::str::{self, Utf8Error};
/// Static string initializer for [`ngx_str_t`].
///
/// The resulting byte string is always nul-terminated (just like a C string).
///
/// [`ngx_str_t`]: https://nginx.org/en/docs/dev/development_guide.html#string_overview
#[macro_export]
macro_rules! ngx_string {
($s:expr) => {{
$crate::ffi::ngx_str_t {
len: $s.len() as _,
data: concat!($s, "\0").as_ptr() as *mut u8,
}
}};
}
/// Static empty string initializer for [`ngx_str_t`].
///
/// [`ngx_str_t`]: https://nginx.org/en/docs/dev/development_guide.html#string_overview
#[macro_export]
macro_rules! ngx_null_string {
() => {
$crate::ffi::ngx_str_t {
len: 0,
data: ::std::ptr::null_mut(),
}
};
}
/// Representation of a borrowed [Nginx string].
///
/// [Nginx string]: https://nginx.org/en/docs/dev/development_guide.html#string_overview
pub struct NgxStr([u_char]);
impl NgxStr {
/// Create an [`NgxStr`] from an [`ngx_str_t`].
///
/// [`ngx_str_t`]: https://nginx.org/en/docs/dev/development_guide.html#string_overview
///
/// # Safety
///
/// The caller has provided a valid `ngx_str_t` with a `data` pointer that points
/// to range of bytes of at least `len` bytes, whose content remains valid and doesn't
/// change for the lifetime of the returned `NgxStr`.
pub unsafe fn from_ngx_str<'a>(str: ngx_str_t) -> &'a NgxStr {
slice::from_raw_parts(str.data, str.len).into()
}
/// Access the [`NgxStr`] as a byte slice.
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
/// Yields a `&str` slice if the [`NgxStr`] contains valid UTF-8.
pub fn to_str(&self) -> Result<&str, Utf8Error> {
str::from_utf8(self.as_bytes())
}
/// Converts an [`NgxStr`] into a [`Cow<str>`], replacing invalid UTF-8 sequences.
///
/// See [`String::from_utf8_lossy`].
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(self.as_bytes())
}
/// Returns `true` if the [`NgxStr`] is empty, otherwise `false`.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl From<&[u8]> for &NgxStr {
fn from(bytes: &[u8]) -> Self {
// SAFETY: An `NgxStr` is identical to a `[u8]` slice, given `u_char` is an alias for `u8`.
unsafe { &*(bytes as *const [u8] as *const NgxStr) }
}
}
impl From<&str> for &NgxStr {
fn from(s: &str) -> Self {
s.as_bytes().into()
}
}
impl AsRef<[u8]> for NgxStr {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl Default for &NgxStr {
fn default() -> Self {
// SAFETY: The null `ngx_str_t` is always a valid Nginx string.
unsafe { NgxStr::from_ngx_str(ngx_null_string!()) }
}
}