use std::io::{self, BufRead, Read};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CapOutcome {
Line,
TooLarge,
Eof,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum HeadOutcome {
Head(Vec<u8>),
TooLarge,
Eof,
Truncated(Vec<u8>),
}
pub fn read_capped_line<R: BufRead>(
reader: &mut R,
buf: &mut String,
cap: usize,
) -> io::Result<CapOutcome> {
buf.clear();
let read = Read::take(&mut *reader, cap as u64 + 1).read_line(buf)?;
if buf.len() > cap {
return Ok(CapOutcome::TooLarge);
}
if read == 0 {
return Ok(CapOutcome::Eof);
}
Ok(CapOutcome::Line)
}
pub fn read_head_until_double_crlf<R: Read>(reader: &mut R, cap: usize) -> io::Result<HeadOutcome> {
let mut head = Vec::new();
let mut byte = [0u8; 1];
loop {
match reader.read(&mut byte) {
Ok(0) if head.is_empty() => return Ok(HeadOutcome::Eof),
Ok(0) => return Ok(HeadOutcome::Truncated(head)),
Ok(_) => {
head.push(byte[0]);
if head.len() > cap {
return Ok(HeadOutcome::TooLarge);
}
if head.ends_with(b"\r\n\r\n") {
return Ok(HeadOutcome::Head(head));
}
}
Err(ref error) if error.kind() == io::ErrorKind::Interrupted => {}
Err(error) => return Err(error),
}
}
}