use bindings::{
ngx_http_headers_in_t, ngx_list_part_t, ngx_list_t, ngx_str_t, ngx_table_elt_t, ngx_uint_t,
};
use std::slice;
use std::str;
impl ngx_str_t {
pub fn to_str(&self) -> &str {
let bytes = unsafe { slice::from_raw_parts(self.data, self.len) };
str::from_utf8(bytes).unwrap_or_default()
}
pub fn to_string(&self) -> String {
String::from(self.to_str())
}
}
impl ngx_http_headers_in_t {
pub fn host_str(&self) -> &str {
if self.host.is_null() {
return "";
}
unsafe { (*self.host).value.to_str() }
}
pub fn headers_iterator(&self) -> NgxListIterator {
NgxListIterator::from_ngx_list(&self.headers)
}
}
pub struct NgxListIterator {
done: bool,
part: *const ngx_list_part_t,
h: *const ngx_table_elt_t,
i: ngx_uint_t,
}
impl NgxListIterator {
pub fn from_ngx_list(list: *const ngx_list_t) -> Self {
let part: *const ngx_list_part_t = unsafe { &(*list).part };
NgxListIterator {
done: false,
part: part,
h: unsafe { (*part).elts as *const ngx_table_elt_t },
i: 0,
}
}
}
impl Iterator for NgxListIterator {
type Item = (String, String);
fn next(&mut self) -> Option<Self::Item> {
if self.done {
None
} else {
if self.i >= unsafe { (*self.part).nelts } {
if unsafe { (*self.part).next.is_null() } {
self.done = true;
return None;
}
self.part = unsafe { (*self.part).next };
self.h = unsafe { (*self.part).elts as *mut ngx_table_elt_t };
self.i = 0;
}
let header = unsafe { self.h.offset(self.i as isize) };
let header_name = unsafe { (*header).key };
let header_value = unsafe { (*header).value };
self.i += 1;
Some((header_name.to_string(), header_value.to_string()))
}
}
}