use crate::split_off_front_inplace_mut;
use crate::ByteStringSlice;
pub struct Win32ShellWords<'a,T:?Sized+ByteStringSlice>(&'a mut [u8], ::std::marker::PhantomData<T>);
impl<'a, T: ?Sized + ByteStringSlice> Win32ShellWords<'a, T>
{
pub(crate) fn new(input_bytes: &mut [u8]) -> Win32ShellWords<T> {
Win32ShellWords(input_bytes, ::std::marker::PhantomData::<T>)
}
}
impl<'a, T: ?Sized + ByteStringSlice + 'a> Iterator for Win32ShellWords<'a, T>
{
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
if self.0.len() == 0 {
return None;
}
enum State {
Normal,
Quote,
Escape,
}
let mut mode = State::Normal;
let mut outpos = 0;
let mut endpos = self.0.len();
for i in 0 .. self.0.len()
{
let byte = self.0[i];
let out = match mode
{
State::Normal => match byte
{
b' ' => { endpos = i; break; },
b'\t' | b'\n' | b'\r' => { endpos = i; break; },
b'^' => {
mode = State::Escape;
continue
},
b'"' => {
mode = State::Quote;
continue
},
v @ _ => v,
},
State::Quote => match byte
{
b'\n' => { endpos = i; break; },
b'"' => {
mode = State::Normal;
continue
},
v @ _ => v,
},
State::Escape => match byte
{
b'\n' => { endpos = i-1; break; },
v @ _ => v,
},
};
if outpos != i {
assert!(outpos < i);
self.0[i] = 0; self.0[outpos] = out;
}
else {
}
outpos += 1;
}
while endpos < self.0.len() && self.0[endpos] == b' ' {
self.0[endpos] = 0;
endpos += 1;
}
let ret = &split_off_front_inplace_mut(&mut self.0, endpos)[..outpos];
Some( T::from_bytes(ret).expect("POSIX Word spliting caused UTF-8 inconsistency") )
}
}