Skip to content

Commit 0174f10

Browse files
committed
fix: refactor NgxListIterator to remove String usage
1 parent 98cb85d commit 0174f10

File tree

1 file changed

+35
-36
lines changed

1 file changed

+35
-36
lines changed

src/http/request.rs

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use core::ffi::c_void;
22
use core::fmt;
3+
use core::slice::from_raw_parts;
34
use core::str::FromStr;
45

56
use crate::core::*;
@@ -394,13 +395,13 @@ impl Request {
394395
}
395396

396397
/// Iterate over headers_in
397-
/// each header item is (String, String) (copied)
398+
/// each header item is (&str, &str) (borrowed)
398399
pub fn headers_in_iterator(&self) -> NgxListIterator {
399400
unsafe { list_iterator(&self.0.headers_in.headers) }
400401
}
401402

402403
/// Iterate over headers_out
403-
/// each header item is (String, String) (copied)
404+
/// each header item is (&str, &str) (borrowed)
404405
pub fn headers_out_iterator(&self) -> NgxListIterator {
405406
unsafe { list_iterator(&self.0.headers_out.headers) }
406407
}
@@ -424,62 +425,60 @@ impl fmt::Debug for Request {
424425
/// Iterator for [`ngx_list_t`] types.
425426
///
426427
/// Implementes the core::iter::Iterator trait.
427-
pub struct NgxListIterator {
428-
done: bool,
429-
part: *const ngx_list_part_t,
430-
h: *const ngx_table_elt_t,
428+
pub struct NgxListIterator<'a> {
429+
part: Option<ListPart<'a>>,
431430
i: ngx_uint_t,
432431
}
432+
struct ListPart<'a> {
433+
raw: &'a ngx_list_part_t,
434+
arr: &'a [ngx_table_elt_t],
435+
}
436+
impl<'a> From<&'a ngx_list_part_t> for ListPart<'a> {
437+
fn from(raw: &'a ngx_list_part_t) -> Self {
438+
let arr = if let Some(elts) = unsafe { raw.elts.cast::<ngx_table_elt_t>().as_ref() } {
439+
unsafe { from_raw_parts(elts, raw.nelts) }
440+
} else {
441+
&[]
442+
};
443+
Self { raw, arr }
444+
}
445+
}
433446

434447
/// Creates new HTTP header iterator
435448
///
436449
/// # Safety
437450
///
438451
/// The caller has provided a valid [`ngx_str_t`] which can be dereferenced validly.
439-
pub unsafe fn list_iterator(list: *const ngx_list_t) -> NgxListIterator {
440-
let part: *const ngx_list_part_t = &(*list).part;
441-
452+
pub unsafe fn list_iterator(list: &ngx_list_t) -> NgxListIterator {
442453
NgxListIterator {
443-
done: false,
444-
part,
445-
h: (*part).elts as *const ngx_table_elt_t,
454+
part: Some((&list.part).into()),
446455
i: 0,
447456
}
448457
}
449458

450459
// iterator for ngx_list_t
451-
impl Iterator for NgxListIterator {
452-
// type Item = (&str,&str);
453-
// TODO: try to use str instead of string
460+
impl<'a> Iterator for NgxListIterator<'a> {
461+
// TODO: try to use struct instead of &str pair
454462
// something like pub struct Header(ngx_table_elt_t);
455463
// then header would have key and value
456464

457-
type Item = (String, String);
465+
type Item = (&'a str, &'a str);
458466

459467
fn next(&mut self) -> Option<Self::Item> {
460-
unsafe {
461-
if self.done {
462-
None
468+
let part = self.part.as_mut()?;
469+
if self.i >= part.arr.len() {
470+
if let Some(next_part_raw) = unsafe { part.raw.next.as_ref() } {
471+
// loop back
472+
*part = next_part_raw.into();
473+
self.i = 0;
463474
} else {
464-
if self.i >= (*self.part).nelts {
465-
if (*self.part).next.is_null() {
466-
self.done = true;
467-
return None;
468-
}
469-
470-
// loop back
471-
self.part = (*self.part).next;
472-
self.h = (*self.part).elts as *mut ngx_table_elt_t;
473-
self.i = 0;
474-
}
475-
476-
let header: *const ngx_table_elt_t = self.h.add(self.i);
477-
let header_name: ngx_str_t = (*header).key;
478-
let header_value: ngx_str_t = (*header).value;
479-
self.i += 1;
480-
Some((header_name.to_string(), header_value.to_string()))
475+
self.part = None;
476+
return None;
481477
}
482478
}
479+
let header = &part.arr[self.i];
480+
self.i += 1;
481+
Some((header.key.to_str(), header.value.to_str()))
483482
}
484483
}
485484

0 commit comments

Comments
 (0)