// Line scanning over raw WARC header bytes.
//
// WARC headers are CRLF-delimited (ISO 28500 clause 4). Lone CR or LF
// bytes corrupt the framing, so they are reported as structured errors
// instead of being silently tolerated as line breaks.
///|
/// Scan one CRLF-terminated line starting at `from`.
///
/// Returns `(line_start, line_end)` where `[line_start, line_end)`
/// excludes the trailing CRLF. Fails with `UnexpectedEof` when the
/// buffer ends without a line terminator and with `InvalidSeparator`
/// on a bare CR or bare LF.
pub fn scan_line(
data : Bytes,
from : Int,
record_index : Int64,
) -> Result[(Int, Int), WarcError] {
let mut i = from
while i < data.length() {
let b = data[i]
if b == b'\r' {
if i + 1 < data.length() && data[i + 1] == b'\n' {
return Ok((from, i))
}
return Err(
WarcError::new(
WarcErrorStage::Separator,
WarcErrorKind::InvalidSeparator,
i.to_int64(),
record_index,
"bare CR without LF",
),
)
}
if b == b'\n' {
return Err(
WarcError::new(
WarcErrorStage::Separator,
WarcErrorKind::InvalidSeparator,
i.to_int64(),
record_index,
"bare LF without CR",
),
)
}
i = i + 1
}
Err(
WarcError::new(
WarcErrorStage::Separator,
WarcErrorKind::UnexpectedEof,
data.length().to_int64(),
record_index,
"unterminated line",
),
)
}