Performance
- Fix O(n²) collision scan on lines that exceed mod_logfile's 2 KiB
buffer. The scan is now bounded to a 64-byte window around the
deterministic truncation point. Parsing pathological log files with
60+ KB physical lines (e.g. CHANNEL_DATA dumps containing embedded
XML/SDP) drops from ~6.4 s to ~0.4 s — 15× faster. No effect on
normal-sized log lines.
- LogEntry::attached now uses AttachedLines, a compact contiguous
buffer + offset table, instead of Vec<String>. Reduces heap churn on
CHANNEL_DATA-heavy entries (140+ continuation lines) from one
allocation per line to amortized two allocations per entry.
Reliability
- Lossy UTF-8 line reading. mod_logfile's buffer truncation can chop
multi-byte codepoints mid-character; the strict BufRead::lines reader
panicked on the resulting partial sequence. The fslog binary and the
fixture-test helper now use read_until + String::from_utf8_lossy,
replacing bad bytes with U+FFFD instead of aborting. Library API is
unchanged — consumers control their own line source.
Breaking API
- LogEntry::attached: Vec<String> → AttachedLines. Iteration via
&entry.attached and entry.attached.iter() works unchanged through
IntoIterator for &AttachedLines. Indexed access changes from
attached[i] to attached.get(i) -> Option<&str>. Length and emptiness
checks (len, is_empty) are unchanged.