@@ -24,6 +24,7 @@ macro_rules! ngx_string {
24
24
/// Representation of a borrowed [Nginx string].
25
25
///
26
26
/// [Nginx string]: https://nginx.org/en/docs/dev/development_guide.html#string_overview
27
+ #[ repr( transparent) ]
27
28
pub struct NgxStr ( [ u_char ] ) ;
28
29
29
30
impl NgxStr {
@@ -37,7 +38,15 @@ impl NgxStr {
37
38
/// to range of bytes of at least `len` bytes, whose content remains valid and doesn't
38
39
/// change for the lifetime of the returned `NgxStr`.
39
40
pub unsafe fn from_ngx_str < ' a > ( str : ngx_str_t ) -> & ' a NgxStr {
40
- str. as_bytes ( ) . into ( )
41
+ let bytes: & [ u8 ] = str. as_bytes ( ) ;
42
+ & * ( bytes as * const [ u8 ] as * const NgxStr )
43
+ }
44
+
45
+ /// Create an [NgxStr] from a borrowed byte slice.
46
+ #[ inline]
47
+ pub fn from_bytes ( bytes : & [ u8 ] ) -> & Self {
48
+ // SAFETY: An `NgxStr` is identical to a `[u8]` slice, given `u_char` is an alias for `u8`
49
+ unsafe { & * ( bytes as * const [ u8 ] as * const NgxStr ) }
41
50
}
42
51
43
52
/// Access the [`NgxStr`] as a byte slice.
@@ -64,16 +73,15 @@ impl NgxStr {
64
73
}
65
74
}
66
75
67
- impl From < & [ u8 ] > for & NgxStr {
68
- fn from ( bytes : & [ u8 ] ) -> Self {
69
- // SAFETY: An `NgxStr` is identical to a `[u8]` slice, given `u_char` is an alias for `u8`.
70
- unsafe { & * ( bytes as * const [ u8 ] as * const NgxStr ) }
76
+ impl < ' a > From < & ' a [ u8 ] > for & ' a NgxStr {
77
+ fn from ( bytes : & ' a [ u8 ] ) -> Self {
78
+ NgxStr :: from_bytes ( bytes)
71
79
}
72
80
}
73
81
74
- impl From < & str > for & NgxStr {
75
- fn from ( s : & str ) -> Self {
76
- s. as_bytes ( ) . into ( )
82
+ impl < ' a > From < & ' a str > for & ' a NgxStr {
83
+ fn from ( s : & ' a str ) -> Self {
84
+ NgxStr :: from_bytes ( s. as_bytes ( ) )
77
85
}
78
86
}
79
87
@@ -85,7 +93,28 @@ impl AsRef<[u8]> for NgxStr {
85
93
86
94
impl Default for & NgxStr {
87
95
fn default ( ) -> Self {
88
- // SAFETY: The empty `ngx_str_t` is always a valid Nginx string.
89
- unsafe { NgxStr :: from_ngx_str ( ngx_str_t:: default ( ) ) }
96
+ NgxStr :: from_bytes ( & [ ] )
97
+ }
98
+ }
99
+
100
+ #[ cfg( test) ]
101
+ mod tests {
102
+ extern crate alloc;
103
+
104
+ use alloc:: string:: ToString ;
105
+
106
+ use super :: * ;
107
+
108
+ #[ test]
109
+ fn test_lifetimes ( ) {
110
+ let a: & NgxStr = "Hello World!" . into ( ) ;
111
+
112
+ let s = "Hello World!" . to_string ( ) ;
113
+ let b: & NgxStr = s. as_bytes ( ) . into ( ) ;
114
+
115
+ // The compiler should detect that s is borrowed and fail.
116
+ // drop(s); // ☢️
117
+
118
+ assert_eq ! ( a. 0 , b. 0 ) ;
90
119
}
91
120
}
0 commit comments