use std::io::Read;
use crate::internet::syntax;
pub struct Parameter<'a> {
pub name: &'a [u8],
pub value: Option<&'a [u8]>,
}
impl<'a> Parameter<'a> {
pub fn reader(&self) -> ParameterReader {
ParameterReader {
n: self.name,
v: self.value,
d: b';',
pos: 0,
}
}
}
impl<'a> From<&'a [u8]> for Parameter<'a> {
fn from(s: &'a [u8]) -> Parameter {
let mut iter = s.iter();
if let Some(position) = iter.position(|c| *c == b'=') {
return Parameter {
name: &s[..position],
value: Some(&s[position + 1..]),
};
}
return Parameter {
name: s,
value: None,
};
}
}
pub struct ParameterParser<'a> {
s: &'a [u8],
d: u8,
p: usize,
ows: bool,
}
impl<'a> ParameterParser<'a> {
pub fn new(s: &'a [u8], d: u8, ows: bool) -> ParameterParser<'a> {
ParameterParser { s, d, p: 0, ows }
}
}
impl<'a> Iterator for ParameterParser<'a> {
type Item = Parameter<'a>;
fn next(&mut self) -> Option<Parameter<'a>> {
if self.p < self.s.len() {
let chunk;
let advance;
if let Some(idx) = syntax::index_with_token_escaping(&self.s[self.p..], self.d) {
chunk = &self.s[self.p..self.p + idx];
advance = idx;
} else {
chunk = &self.s[self.p..];
advance = self.s.len() - self.p;
}
let chunk = syntax::trim(chunk);
if self.p + advance + 1 < self.s.len() {
if self.ows {
self.p = self.p
+ advance
+ syntax::index_skipping_ows_and_obs_fold(&self.s[self.p + advance + 1..])
+ 1;
} else {
self.p = self.p + advance + 1;
}
} else {
self.p = self.p + advance + 1;
}
return Some(Parameter::from(chunk));
}
None
}
}
pub struct ParameterReader<'a> {
n: &'a [u8],
v: Option<&'a [u8]>,
d: u8,
pos: usize,
}
impl<'a> Read for ParameterReader<'a> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let mut i = 0;
let n_length = self.n.len();
while self.pos + i < 1 && i < buf.len() {
buf[i] = self.d;
i += 1;
}
while self.pos + i >= 1 && self.pos + i < 1 + n_length && i < buf.len() {
buf[i] = self.n[self.pos + i - 1];
i += 1;
}
if let Some(v) = self.v {
let v_length = v.len();
while self.pos + i >= 1 + n_length && self.pos + i < 1 + n_length + 1 && i < buf.len() {
buf[i] = b'=';
i += 1;
}
while self.pos + i >= 1 + n_length + 1
&& self.pos + i < 1 + n_length + 1 + v_length
&& i < buf.len()
{
buf[i] = v[self.pos + i - 1 - n_length - 1];
i += 1;
}
}
self.pos += i;
Ok(i)
}
}