// Content-Length field handling (ISO 28500:2017 clause 5.3).
//
// Content-Length is the single framing authority of a WARC record: it
// states the exact octet count of the content block. Framing never
// searches for record boundaries in the block itself, so the value is
// parsed with the same overflow-safe decimal machinery as every other
// number in the format, and a missing or repeated field is refused
// before framing can become ambiguous.
///|
/// Extract and parse the mandatory Content-Length field of a parsed
/// record header.
///
/// Fails with `MissingRequiredField` when absent, `DuplicateField`
/// when repeated (both spellings being case-insensitive matches),
/// `InvalidContentLength` on a non-decimal value, `IntegerOverflow`
/// when the digit count or value overflows, and `LimitExceeded` when
/// the declared block size exceeds `max_block_bytes`.
pub fn parse_content_length(
fields : Array[WarcField],
limits : Limits,
record_index : Int64,
) -> Result[Int64, WarcError] {
let found : Array[String] = []
for i = 0; i < fields.length(); i = i + 1 {
if fields[i].name.equal_ignore_ascii_case("Content-Length") {
found.push(fields[i].value)
}
}
if found.length() == 0 {
return Err(
WarcError::new(
WarcErrorStage::ContentLength,
WarcErrorKind::MissingRequiredField,
0L,
record_index,
"missing mandatory Content-Length field",
),
)
}
if found.length() > 1 {
return Err(
WarcError::new(
WarcErrorStage::ContentLength,
WarcErrorKind::DuplicateField,
0L,
record_index,
"Content-Length must not be repeated",
),
)
}
let vb = @utf8.encode(found[0])
let parsed = parse_decimal(
vb,
0,
vb.length(),
limits.max_content_length_digits,
"Content-Length",
)
let len = match parsed {
Ok(x) => x
Err(e) =>
return Err(
WarcError::new(e.stage, e.kind, e.byte_offset, record_index, e.context),
)
}
if len > limits.max_block_bytes {
return Err(
WarcError::new(
WarcErrorStage::ContentLength,
WarcErrorKind::LimitExceeded,
0L,
record_index,
"Content-Length exceeds max_block_bytes",
),
)
}
Ok(len)
}