use std::{
fs::File,
io::{stdin, Read},
};
pub trait SliceExt {
fn trim(&self) -> &Self;
fn trim_end_matches(&self, m: u8) -> &Self;
}
impl SliceExt for [u8] {
fn trim(&self) -> &[u8] {
fn is_not_whitespace(c: &u8) -> bool {
!matches!(c, b' ' | b'\x09'..=b'\x0d')
}
match (
self.iter().position(is_not_whitespace),
self.iter().rposition(is_not_whitespace),
) {
(Some(start), Some(end)) => &self[start..end + 1],
(..) => &[],
}
}
fn trim_end_matches(&self, m: u8) -> &[u8] {
match self.iter().rposition(|c| c != &m) {
Some(end) => &self[..end + 1],
None => &[],
}
}
}
pub fn read_lua_file(filename: &str) -> Result<Vec<u8>, std::io::Error> {
let mut chunk = Vec::new();
if filename == "-" {
stdin().read_to_end(&mut chunk)?;
} else {
let mut file = File::open(&filename)?;
file.read_to_end(&mut chunk)?;
}
if chunk.len() >= 3 && chunk[0] == 0xEF && chunk[1] == 0xBB && chunk[2] == 0xBF {
chunk.drain(0..3);
}
let mut iter = chunk.iter().enumerate();
if matches!(iter.next(), Some((_, &b'#'))) {
loop {
match iter.next() {
Some((pos, c)) if c == &b'\n' => {
if chunk[pos + 1..].starts_with(&[b'\x1b']) {
chunk.drain(0..=pos);
} else {
chunk.drain(0..pos);
}
break;
}
None => return Ok(Vec::new()),
_ => {}
}
}
}
Ok(chunk)
}