use crate::ParseError;
use std::fmt;
use std::fs::File;
use std::io;
use std::path::Path;
pub struct MappedFile {
mmap: memmap2::Mmap,
}
impl fmt::Debug for MappedFile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MappedFile")
.field("len", &self.mmap.len())
.finish()
}
}
impl MappedFile {
pub fn map_path<P: AsRef<Path>>(path: P) -> io::Result<Self> {
let file = File::open(path)?;
let mmap = unsafe { memmap2::MmapOptions::new().map(&file)? };
Ok(Self { mmap })
}
#[inline]
pub fn as_bytes(&self) -> &[u8] {
&self.mmap[..]
}
pub fn as_str_checked(&self) -> Result<&str, ParseError> {
std::str::from_utf8(self.as_bytes()).map_err(|e| ParseError::InvalidUtf8 {
byte: e.valid_up_to(),
})
}
#[inline]
pub fn len(&self) -> usize {
self.mmap.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.mmap.is_empty()
}
#[inline]
pub fn log_stream(
&self,
dialect: crate::LogDialect,
max_line_bytes: Option<usize>,
) -> crate::LogStream<'_> {
crate::LogStream::new(self.as_bytes(), dialect, max_line_bytes)
}
}
#[derive(Debug)]
pub enum Source<'src> {
Str(&'src str),
Bytes(&'src [u8]),
Mapped(MappedFile),
}
impl<'src> Source<'src> {
#[inline]
pub fn borrowed_str(s: &'src str) -> Self {
Source::Str(s)
}
#[inline]
pub fn borrowed_bytes(b: &'src [u8]) -> Self {
Source::Bytes(b)
}
#[inline]
pub fn mapped(m: MappedFile) -> Self {
Source::Mapped(m)
}
pub fn whole_str_checked(&self) -> Result<&str, ParseError> {
match self {
Source::Str(s) => Ok(s),
Source::Bytes(b) => std::str::from_utf8(b).map_err(|e| ParseError::InvalidUtf8 {
byte: e.valid_up_to(),
}),
Source::Mapped(m) => m.as_str_checked(),
}
}
#[inline]
pub fn as_bytes_full(&self) -> &[u8] {
match self {
Source::Str(s) => s.as_bytes(),
Source::Bytes(b) => b,
Source::Mapped(m) => m.as_bytes(),
}
}
}