use std::io::prelude::*;
use std::str as stdstr;
use traits::Valid;
use super::alias::{BufferType, ResultType};
use super::error::ErrorKind;
pub struct StrictIter<T: Valid, U: Iterator<Item = ResultType<T>>> {
iter: U,
}
impl<T: Valid, U: Iterator<Item = ResultType<T>>> StrictIter<T, U> {
#[inline]
pub fn new(iter: U) -> Self {
StrictIter {
iter: iter
}
}
}
impl<T: Valid, U: Iterator<Item = ResultType<T>>> Iterator for StrictIter<T, U> {
type Item = U::Item;
fn next(&mut self) -> Option<Self::Item> {
Some(self.iter.next()?.and_then(|r| {
match r.is_valid() {
true => Ok(r),
false => Err(From::from(ErrorKind::InvalidRecord)),
}
}))
}
}
pub struct LenientIter<T: Valid, U: Iterator<Item = ResultType<T>>> {
iter: U,
}
impl<T: Valid, U: Iterator<Item = ResultType<T>>> LenientIter<T, U> {
#[inline]
pub fn new(iter: U) -> Self {
LenientIter {
iter: iter
}
}
}
impl<T: Valid, U: Iterator<Item = ResultType<T>>> Iterator for LenientIter<T, U> {
type Item = U::Item;
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.iter.next()? {
Err(e) => return Some(Err(e)),
Ok(r) => {
if r.is_valid() {
return Some(Ok(r));
}
},
}
}
}
}
pub fn reference_iterator_export<
'a, 'b,
Iter,
Writer,
InnerWriter,
Record,
InitCb,
ExportCb,
DestCb
>
(
writer: &'b mut Writer,
iter: Iter,
delimiter: u8,
init_cb: &InitCb,
export_cb: &ExportCb,
dest_cb: &DestCb
)
-> ResultType<()>
where Writer: Write,
Iter: Iterator<Item = &'a Record>,
Record: 'a + Valid,
InitCb: Fn(&'b mut Writer, u8) -> ResultType<InnerWriter>,
ExportCb: Fn(&mut InnerWriter, &'a Record) -> ResultType<()>,
DestCb: Fn(&mut InnerWriter) -> ResultType<()>
{
let mut inner = init_cb(writer, delimiter)?;
for record in iter {
export_cb(&mut inner, record)?;
}
dest_cb(&mut inner)
}
pub fn value_iterator_export<
'a,
Iter,
Writer,
InnerWriter,
Record,
InitCb,
ExportCb,
DestCb
>
(
writer: &'a mut Writer,
iter: Iter,
delimiter: u8,
init_cb: &InitCb,
export_cb: &ExportCb,
dest_cb: &DestCb
)
-> ResultType<()>
where Writer: Write,
Iter: Iterator<Item = ResultType<Record>>,
Record: Valid,
InitCb: Fn(&'a mut Writer, u8) -> ResultType<InnerWriter>,
ExportCb: Fn(&mut InnerWriter, &Record) -> ResultType<()>,
DestCb: Fn(&mut InnerWriter) -> ResultType<()>
{
let mut inner = init_cb(writer, delimiter)?;
for record in iter {
export_cb(&mut inner, &record?)?;
}
dest_cb(&mut inner)
}
pub fn reference_iterator_export_strict<
'a, 'b,
Iter,
Writer,
InnerWriter,
Record,
InitCb,
ExportCb,
DestCb
>
(
writer: &'b mut Writer,
iter: Iter,
delimiter: u8,
init_cb: &InitCb,
export_cb: &ExportCb,
dest_cb: &DestCb
)
-> ResultType<()>
where Writer: Write,
Iter: Iterator<Item = &'a Record>,
Record: 'a + Valid,
InitCb: Fn(&'b mut Writer, u8) -> ResultType<InnerWriter>,
ExportCb: Fn(&mut InnerWriter, &'a Record) -> ResultType<()>,
DestCb: Fn(&mut InnerWriter) -> ResultType<()>
{
let mut inner = init_cb(writer, delimiter)?;
for record in iter {
bool_to_error!(record.is_valid(), InvalidRecord);
export_cb(&mut inner, record)?;
}
dest_cb(&mut inner)
}
pub fn value_iterator_export_strict<
'a,
Iter,
Writer,
InnerWriter,
Record,
InitCb,
ExportCb,
DestCb
>
(
writer: &'a mut Writer,
iter: Iter,
delimiter: u8,
init_cb: &InitCb,
export_cb: &ExportCb,
dest_cb: &DestCb
)
-> ResultType<()>
where Writer: Write,
Iter: Iterator<Item = ResultType<Record>>,
Record: Valid,
InitCb: Fn(&'a mut Writer, u8) -> ResultType<InnerWriter>,
ExportCb: Fn(&mut InnerWriter, &Record) -> ResultType<()>,
DestCb: Fn(&mut InnerWriter) -> ResultType<()>
{
let mut inner = init_cb(writer, delimiter)?;
for result in iter {
let record = result?;
bool_to_error!(record.is_valid(), InvalidRecord);
export_cb(&mut inner, &record)?;
}
dest_cb(&mut inner)
}
pub fn reference_iterator_export_lenient<
'a, 'b,
Iter,
Writer,
InnerWriter,
Record,
InitCb,
ExportCb,
DestCb
>
(
writer: &'b mut Writer,
iter: Iter,
delimiter: u8,
init_cb: &InitCb,
export_cb: &ExportCb,
dest_cb: &DestCb
)
-> ResultType<()>
where Writer: Write,
Iter: Iterator<Item = &'a Record>,
Record: 'a + Valid,
InitCb: Fn(&'b mut Writer, u8) -> ResultType<InnerWriter>,
ExportCb: Fn(&mut InnerWriter, &'a Record) -> ResultType<()>,
DestCb: Fn(&mut InnerWriter) -> ResultType<()>
{
let mut inner = init_cb(writer, delimiter)?;
for record in iter {
if record.is_valid() {
export_cb(&mut inner, record)?;
}
}
dest_cb(&mut inner)
}
pub fn value_iterator_export_lenient<
'a,
Iter,
Writer,
InnerWriter,
Record,
InitCb,
ExportCb,
DestCb
>
(
writer: &'a mut Writer,
iter: Iter,
delimiter: u8,
init_cb: &InitCb,
export_cb: &ExportCb,
dest_cb: &DestCb
)
-> ResultType<()>
where Writer: Write,
Iter: Iterator<Item = ResultType<Record>>,
Record: Valid,
InitCb: Fn(&'a mut Writer, u8) -> ResultType<InnerWriter>,
ExportCb: Fn(&mut InnerWriter, &Record) -> ResultType<()>,
DestCb: Fn(&mut InnerWriter) -> ResultType<()>
{
let mut inner = init_cb(writer, delimiter)?;
for result in iter {
let record = result?;
if record.is_valid() {
export_cb(&mut inner, &record)?;
}
}
dest_cb(&mut inner)
}
#[doc(hidden)]
#[macro_export]
macro_rules! buffer_to_string {
($buf:expr) => ({
let result = match $buf.len() {
0 => None,
_ => Some(match stdstr::from_utf8(&$buf) {
Err(e) => Err(From::from(e)),
Ok(v) => Ok(String::from(v)),
}),
};
$buf.set_len(0);
result
})
}
#[doc(hidden)]
#[macro_export]
macro_rules! text_next {
($reader:expr, $buf:expr, $line:expr, $block:expr) => ({
loop {
match $reader.read_line($line) {
Err(e) => return Some(Err(From::from(e))),
Ok(size) => match size {
0 => return unsafe { buffer_to_string!($buf) },
_ => $block,
}
}
}
})
}
pub fn text_next_skip_whitespace<T: BufRead>(
start: &str,
reader: &mut T,
buf: &mut BufferType,
line: &mut String
)
-> Option<ResultType<String>>
{
text_next!(reader, buf, line, unsafe {
if line == "\n" || line == "\r\n" {
line.as_mut_vec().set_len(0);
continue;
} else if buf.len() > 0 && line.starts_with(start) {
let result = buffer_to_string!(buf);
buf.append(line.as_mut_vec());
return result;
} else {
buf.append(line.as_mut_vec());
}
})
}