use std::fs;
use std::path::{Path, PathBuf};
use std::str;
use crate::error::ParseError;
use crate::parser::LogParser;
use crate::parser::encoding::FileEncodingHint;
pub struct LogParserBuilder {
path: PathBuf,
encoding_hint: Option<FileEncodingHint>,
}
impl LogParserBuilder {
pub fn new<P: AsRef<Path>>(path: P) -> Self {
Self {
path: path.as_ref().to_path_buf(),
encoding_hint: None,
}
}
pub fn encoding_hint(mut self, hint: FileEncodingHint) -> Self {
self.encoding_hint = Some(hint);
self
}
pub fn build(self) -> Result<LogParser, ParseError> {
let data = fs::read(&self.path).map_err(|e| ParseError::IoError(e.to_string()))?;
let encoding = match self.encoding_hint {
Some(hint) => hint,
None => {
let head_size = data.len().min(64 * 1024);
let head_ok = str::from_utf8(&data[..head_size]).is_ok();
let tail_start = data.len().saturating_sub(4 * 1024).max(head_size);
let tail_ok =
tail_start >= data.len() || str::from_utf8(&data[tail_start..]).is_ok();
if head_ok && tail_ok {
FileEncodingHint::Utf8
} else {
FileEncodingHint::Gb18030
}
}
};
Ok(LogParser { data, encoding })
}
}