Skip to content

Commit b7451a4

Browse files
committed
feat: add std feature for opt-out
1 parent 445cb31 commit b7451a4

File tree

9 files changed

+408
-108
lines changed

9 files changed

+408
-108
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ repository.workspace = true
2525
rust-version.workspace = true
2626

2727
[dependencies]
28-
nginx-sys = { path = "nginx-sys", version = "0.5.0"}
28+
nginx-sys = { path = "nginx-sys", default-features = false, version = "0.5.0" }
2929

3030
[features]
3131
default = ["vendored","std"]
3232
# use std memory allocation
33-
std = []
33+
std = ["nginx-sys/std"]
3434
# Build our own copy of the NGINX by default.
3535
# This could be disabled with `--no-default-features` to minimize the dependency tree
3636
# when building against an existing copy of the NGINX with the NGX_OBJS variable.

nginx-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ ureq = { version = "2.9.6", features = ["tls"], optional = true }
2727
which = { version = "6.0.0", optional = true }
2828

2929
[features]
30-
default = ["std"]
30+
default = ["std","vendored"]
3131
std = []
3232
vendored = ["dep:which", "dep:duct", "dep:ureq", "dep:flate2", "dep:tar"]

nginx-sys/build/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ fn generate_binding(nginx_build_dir: PathBuf) {
9797
.header("build/wrapper.h")
9898
.clang_args(clang_args)
9999
.layout_tests(false)
100+
.use_core()
100101
.generate()
101102
.expect("Unable to generate bindings");
102103

nginx-sys/src/lib.rs

Lines changed: 108 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#![doc = include_str!("../README.md")]
22
#![warn(missing_docs)]
3+
#![cfg_attr(not(feature = "std"), no_std)]
4+
#[cfg(not(feature = "std"))]
5+
extern crate alloc;
36

47
use core::fmt;
58
use core::ptr::copy_nonoverlapping;
@@ -17,6 +20,11 @@ mod bindings {
1720
#![allow(rustdoc::broken_intra_doc_links)]
1821
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
1922
}
23+
#[cfg(not(feature = "std"))]
24+
use alloc::string;
25+
#[cfg(feature = "std")]
26+
use std::string;
27+
2028
#[doc(no_inline)]
2129
pub use bindings::*;
2230

@@ -92,7 +100,7 @@ impl ngx_str_t {
92100
self.len == 0
93101
}
94102

95-
/// Convert the nginx string to a string slice (`&str`).
103+
/// Returns the contents of this `ngx_str_t` as a string slice (`&str`).
96104
///
97105
/// # Safety
98106
/// This function is marked as unsafe because it involves raw pointer manipulation.
@@ -107,6 +115,99 @@ impl ngx_str_t {
107115
core::str::from_utf8(self.as_bytes()).unwrap()
108116
}
109117

118+
// /// Returns the contents of this `ngx_str_t` as a mutable string slice (`&str`).
119+
// ///
120+
// /// # Safety
121+
// /// This function is marked as unsafe because it involves raw pointer manipulation.
122+
// /// It assumes that the underlying `data` pointer is valid and points to a valid UTF-8 encoded string.
123+
// ///
124+
// /// # Panics
125+
// /// This function panics if the `ngx_str_t` is not valid UTF-8.
126+
// ///
127+
// /// # Returns
128+
// /// A mutable string slice (`&mut str`) representing the nginx string.
129+
// pub fn to_str_mut(&mut self) -> &str {
130+
// core::str::from_utf8(self.as_bytes()).unwrap()
131+
// }
132+
133+
// /// Convert `ngx_str_t` to a byte slice.
134+
// ///
135+
// /// The returned slice will **not** contain the optional nul terminator that `ngx_str_t.data`
136+
// /// may have.
137+
// ///
138+
// /// # Safety
139+
// /// This function is marked as unsafe because it involves lifetime generation.
140+
// /// Caller must specify the proper lifetime which original `ngx_str_t` belongs to.
141+
// #[inline]
142+
// pub fn into_bytes<'a>(self) -> &'a [u8] {
143+
// if self.is_empty() {
144+
// &[]
145+
// } else {
146+
// // SAFETY: `ngx_str_t` with non-zero len must contain a valid correctly aligned pointer
147+
// unsafe { slice::from_raw_parts(self.data, self.len) }
148+
// }
149+
// }
150+
151+
// /// Convert `ngx_str_t` to a mutable byte slice.
152+
// ///
153+
// /// The returned slice will **not** contain the optional nul terminator that `ngx_str_t.data`
154+
// /// may have.
155+
// ///
156+
// /// # Safety
157+
// /// This function is marked as unsafe because it involves raw pointer manipulation.
158+
// /// It assumes that the underlying `data` pointer is valid and points to a valid UTF-8 encoded string.
159+
// ///
160+
// /// This function is marked as unsafe because it involves lifetime generation.
161+
// /// Caller must specify the proper lifetime which original `ngx_str_t` belongs to.
162+
// ///
163+
// /// # Panics
164+
// /// This function panics if the `ngx_str_t` is not valid UTF-8.
165+
// ///
166+
// /// # Returns
167+
// /// A mutable string slice (`&mut str`) representing the nginx string.
168+
// #[inline]
169+
// pub fn into_bytes_mut<'a>(self) -> &'a mut [u8] {
170+
// if self.is_empty() {
171+
// &mut []
172+
// } else {
173+
// // SAFETY: `ngx_str_t` with non-zero len must contain a valid correctly aligned pointer
174+
// unsafe { slice::from_raw_parts_mut(self.data, self.len) }
175+
// }
176+
// }
177+
178+
// /// Convert `ngx_str_t` to a string slice (`&str`).
179+
// ///
180+
// /// The returned slice will **not** contain the optional nul terminator that `ngx_str_t.data`
181+
// /// may have.
182+
// ///
183+
// /// # Safety
184+
// /// This function is marked as unsafe because it involves lifetime generation.
185+
// /// Caller must specify the proper lifetime which original `ngx_str_t` belongs to.
186+
// pub fn into_str<'a>(self) -> &'a str {
187+
// core::str::from_utf8(self.into_bytes()).unwrap()
188+
// }
189+
190+
// /// Convert `ngx_str_t` to a mutable byte string slice (`&str`).
191+
// ///
192+
// /// The returned slice will **not** contain the optional nul terminator that `ngx_str_t.data`
193+
// /// may have.
194+
// ///
195+
// /// # Safety
196+
// /// This function is marked as unsafe because it involves raw pointer manipulation.
197+
// /// It assumes that the underlying `data` pointer is valid and points to a valid UTF-8 encoded string.
198+
// ///
199+
// /// This function is marked as unsafe because it involves lifetime generation.
200+
// /// Caller must specify the proper lifetime which original `ngx_str_t` belongs to.
201+
// ///
202+
// /// # Panics
203+
// /// This function panics if the `ngx_str_t` is not valid UTF-8.
204+
// ///
205+
// /// # Returns
206+
// /// A mutable string slice (`&mut str`) representing the nginx string.
207+
// pub fn into_str_mut<'a>(self) -> &'a mut str {
208+
// core::str::from_utf8_mut(self.into_bytes_mut()).unwrap()
209+
// }
210+
110211
/// Create an `ngx_str_t` instance from a byte slice.
111212
///
112213
/// # Safety
@@ -130,7 +231,7 @@ impl ngx_str_t {
130231
///
131232
/// # Returns
132233
/// An `ngx_str_t` instance representing the given `String`.
133-
pub unsafe fn from_string(pool: *mut ngx_pool_t, data: String) -> Self {
234+
pub unsafe fn from_string(pool: *mut ngx_pool_t, data: string::String) -> Self {
134235
ngx_str_t {
135236
data: str_to_uchar(pool, data.as_str()),
136237
len: data.len(),
@@ -168,19 +269,18 @@ impl From<ngx_str_t> for &[u8] {
168269
}
169270
}
170271

171-
#[cfg(feature = "std")]
172-
impl TryFrom<ngx_str_t> for String {
173-
type Error = std::string::FromUtf8Error;
272+
impl TryFrom<ngx_str_t> for string::String {
273+
type Error = string::FromUtf8Error;
174274

175275
fn try_from(s: ngx_str_t) -> Result<Self, Self::Error> {
176276
let bytes: &[u8] = s.into();
177-
String::from_utf8(bytes.into())
277+
string::String::from_utf8(bytes.into())
178278
}
179279
}
180280

181281
impl fmt::Display for ngx_str_t {
182282
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183-
write!(f, "{}", String::from_utf8_lossy((*self).into()))
283+
write!(f, "{}", string::String::from_utf8_lossy((*self).into()))
184284
}
185285
}
186286

@@ -234,6 +334,6 @@ pub unsafe fn add_to_ngx_table(
234334
table.key.data = str_to_uchar(pool, key);
235335
table.value.len = value.len();
236336
table.value.data = str_to_uchar(pool, value);
237-
table.lowcase_key = str_to_uchar(pool, String::from(key).to_ascii_lowercase().as_str());
337+
table.lowcase_key = str_to_uchar(pool, string::String::from(key).to_ascii_lowercase().as_str());
238338
})
239339
}

src/core/string.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ use core::str::{self, Utf8Error};
33

44
use crate::ffi::*;
55

6+
#[cfg(not(feature = "std"))]
7+
use alloc::{borrow::Cow, string::String};
8+
#[cfg(feature = "std")]
9+
use std::{borrow::Cow, string::String};
10+
611
/// Static string initializer for [`ngx_str_t`].
712
///
813
/// The resulting byte string is always nul-terminated (just like a C string).
@@ -63,8 +68,7 @@ impl NgxStr {
6368
/// Converts an [`NgxStr`] into a [`Cow<str>`], replacing invalid UTF-8 sequences.
6469
///
6570
/// See [`String::from_utf8_lossy`].
66-
#[cfg(feature = "std")]
67-
pub fn to_string_lossy(&self) -> std::borrow::Cow<str> {
71+
pub fn to_string_lossy(&self) -> Cow<str> {
6872
String::from_utf8_lossy(self.as_bytes())
6973
}
7074

src/http/request.rs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use core::error::Error;
22
use core::ffi::c_void;
33
use core::fmt;
4+
use core::marker::PhantomData;
45
use core::str::FromStr;
56

67
use crate::core::*;
@@ -106,6 +107,32 @@ impl<'a> From<&'a mut Request> for *mut ngx_http_request_t {
106107
}
107108
}
108109

110+
impl crate::log::LogTarget for ngx_http_request_t {
111+
#[inline]
112+
fn debug_mask(&self) -> crate::log::DebugMask {
113+
crate::log::DebugMask::Http
114+
}
115+
116+
#[inline]
117+
fn get_log(&self) -> *const ngx_log_t {
118+
// SAFETY: request must have a connecton and connection must have log
119+
unsafe { (*self.connection).log }
120+
}
121+
}
122+
123+
impl crate::log::LogTarget for Request {
124+
#[inline]
125+
fn debug_mask(&self) -> crate::log::DebugMask {
126+
crate::log::DebugMask::Http
127+
}
128+
129+
#[inline]
130+
fn get_log(&self) -> *const ngx_log_t {
131+
// SAFETY: request must have a connecton and connection must have log
132+
unsafe { (*self.connection()).log }
133+
}
134+
}
135+
109136
impl Request {
110137
/// Create a [`Request`] from an [`ngx_http_request_t`].
111138
///
@@ -427,38 +454,38 @@ impl fmt::Debug for Request {
427454
/// Iterator for [`ngx_list_t`] types.
428455
///
429456
/// Implementes the core::iter::Iterator trait.
430-
pub struct NgxListIterator {
457+
pub struct NgxListIterator<'a> {
431458
done: bool,
432459
part: *const ngx_list_part_t,
433460
h: *const ngx_table_elt_t,
434461
i: ngx_uint_t,
462+
__: PhantomData<&'a ()>,
435463
}
436464

437465
/// Creates new HTTP header iterator
438466
///
439467
/// # Safety
440468
///
441469
/// The caller has provided a valid [`ngx_str_t`] which can be dereferenced validly.
442-
pub unsafe fn list_iterator(list: *const ngx_list_t) -> NgxListIterator {
470+
pub unsafe fn list_iterator<'a>(list: &'a ngx_list_t) -> NgxListIterator<'a> {
443471
let part: *const ngx_list_part_t = &(*list).part;
444472

445473
NgxListIterator {
446474
done: false,
447475
part,
448476
h: (*part).elts as *const ngx_table_elt_t,
449477
i: 0,
478+
__: PhantomData,
450479
}
451480
}
452481

453482
// iterator for ngx_list_t
454-
impl Iterator for NgxListIterator {
455-
// type Item = (&str,&str);
456-
// TODO: try to use str instead of string
483+
impl<'a> Iterator for NgxListIterator<'a> {
484+
type Item = (&'a str, &'a str);
485+
// TODO: try to use struct instead of &str pair
457486
// something like pub struct Header(ngx_table_elt_t);
458487
// then header would have key and value
459488

460-
type Item = (String, String);
461-
462489
fn next(&mut self) -> Option<Self::Item> {
463490
unsafe {
464491
if self.done {
@@ -477,10 +504,10 @@ impl Iterator for NgxListIterator {
477504
}
478505

479506
let header: *const ngx_table_elt_t = self.h.add(self.i);
480-
let header_name: ngx_str_t = (*header).key;
481-
let header_value: ngx_str_t = (*header).value;
507+
let header_name: &ngx_str_t = &(*header).key;
508+
let header_value: &ngx_str_t = &(*header).value;
482509
self.i += 1;
483-
Some((header_name.to_string(), header_value.to_string()))
510+
Some((header_name.to_str(), header_value.to_str()))
484511
}
485512
}
486513
}

src/http/status.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl InvalidHTTPStatusCode {
2525

2626
impl fmt::Display for InvalidHTTPStatusCode {
2727
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28-
f.write_str("invalid status code".to_string().as_str())
28+
f.write_str("invalid status code")
2929
}
3030
}
3131

src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@
3232
//! # now you can use dynamic modules with the NGINX
3333
//! ```
3434
35-
// support both std and no_std
3635
#![cfg_attr(not(feature = "std"), no_std)]
3736
#![warn(missing_docs)]
37+
#[cfg(not(feature = "std"))]
38+
extern crate alloc;
39+
3840
/// The core module.
3941
///
4042
/// This module provides fundamental utilities needed to interface with many NGINX primitives.
@@ -61,8 +63,10 @@ pub mod log;
6163
/// The test utility module.
6264
///
6365
/// This module provides utilities for integration tests with bundled NGINX.
64-
#[cfg(feature = "test_util")]
66+
#[cfg(all(feature = "test_util", feature = "std"))]
6567
pub mod test_util;
68+
#[cfg(all(feature = "test_util", not(feature = "std")))]
69+
compile_error!("feature \"test_util\" requires feature \"std\"");
6670

6771
/// Define modules exported by this library.
6872
///

0 commit comments

Comments
 (0)