use std::{
fmt,
io::{BufRead, Error as ioError, Read},
str::FromStr,
};
#[inline(always)]
pub fn skip_bytes<R>(read: &mut R, n_bytes: usize) -> std::io::Result<()>
where
R: Read,
{
let mut buffer = [0u8; 1];
for _ in 0..n_bytes {
let _ = read.read_exact(&mut buffer)?;
}
Ok(())
}
#[inline(always)]
pub fn skip_n<I>(i: &mut I, n: usize)
where
I: Iterator,
{
for _ in 0..n {
i.next();
}
}
pub fn trim_start(text: &[u8]) -> &[u8] {
let mut to_drop = 0;
for c in text {
if !(*c == b' ' || *c == b'\t') {
break;
}
to_drop += 1;
}
&text[to_drop..]
}
#[inline(always)]
pub fn from_ascii<T>(bytes: &[u8]) -> Option<T>
where
T: FromStr,
{
if bytes.is_ascii() {
unsafe { T::from_str(std::str::from_utf8_unchecked(bytes)).ok() }
} else {
None
}
}
#[inline(always)]
pub fn fetch_line<'a, R>(read: &mut R, line_buffer: &'a mut Vec<u8>) -> FetchLineResult<&'a [u8]>
where
R: BufRead,
{
line_buffer.clear();
let n_read = read.read_until(b'\n', line_buffer)?;
if n_read == 0 {
return Err(FetchLineError);
}
let mut ignore_end = 1;
for i in 1..line_buffer.len() {
if (line_buffer[line_buffer.len() - i - 1] as char).is_whitespace() {
ignore_end += 1;
} else {
break;
}
}
Ok(&line_buffer[0..line_buffer.len() - ignore_end])
}
pub struct FetchLineError;
pub type FetchLineResult<T> = std::result::Result<T, FetchLineError>;
impl fmt::Debug for FetchLineError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Unable to fetch line")
}
}
impl From<ioError> for FetchLineError {
fn from(_error: ioError) -> Self {
FetchLineError {}
}
}