Mem_Parser 0.1.0

Zero-copy log parser with mmap input, streaming lines, and optional bump arena AST
Documentation
//! High-level streaming records over a byte slice (memory-mapped or borrowed).

use crate::error::ParseError;
use crate::lexer::{fields_on_line, FieldRef, LineIter, LineView, LogDialect};

/// One parsed line with zero-copy field references into the source.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BorrowedRecord<'src> {
    pub line: LineView<'src>,
    pub fields: Vec<FieldRef<'src>>,
}

/// Stream [`BorrowedRecord`] values from a contiguous byte buffer (UTF-8 validated per line).
pub struct LogStream<'src> {
    lines: LineIter<'src>,
    dialect: LogDialect,
}

impl<'src> LogStream<'src> {
    pub fn new(bytes: &'src [u8], dialect: LogDialect, max_line_bytes: Option<usize>) -> Self {
        Self {
            lines: LineIter::new(bytes, max_line_bytes),
            dialect,
        }
    }
}

impl<'src> Iterator for LogStream<'src> {
    type Item = Result<BorrowedRecord<'src>, ParseError>;

    fn next(&mut self) -> Option<Self::Item> {
        let line = match self.lines.next()? {
            Ok(l) => l,
            Err(e) => return Some(Err(e)),
        };
        let fields = fields_on_line(line, self.dialect);
        Some(Ok(BorrowedRecord { line, fields }))
    }
}

/// Convenience: stream from a guaranteed UTF-8 `&str` (same bytes as `src.as_bytes()`).
pub fn parse_log_stream<'src>(
    src: &'src str,
    dialect: LogDialect,
    max_line_bytes: Option<usize>,
) -> LogStream<'src> {
    LogStream::new(src.as_bytes(), dialect, max_line_bytes)
}