///|
/// Parsed Accept-Ranges field. `NoneAccepted` is the reserved `none` value.
pub(all) enum AcceptRanges {
NoneAccepted
Units(Array[String])
} derive(Eq, Debug)
///|
pub fn parse_accept_ranges(input : String) -> Result[AcceptRanges, RangeError] {
parse_accept_ranges_with_limits(input, Limits::default())
}
///|
pub fn parse_accept_ranges_with_limits(
input : String,
limits : Limits,
) -> Result[AcceptRanges, RangeError] {
if utf8_length(input) > limits.max_input_bytes() {
return Err(
range_error(
Limit,
LimitExceeded,
0,
"Accept-Ranges exceeds max_input_bytes",
),
)
}
let trimmed = trim_ows(input)
if trimmed.length() == 0 {
return Err(
range_error(AcceptRanges, EmptyInput, 0, "Accept-Ranges is empty"),
)
}
if ascii_equal(trimmed, "none") {
return Ok(NoneAccepted)
}
let units : Array[String] = []
let mut start = 0
for i = 0; i <= trimmed.length(); i = i + 1 {
if i == trimmed.length() || trimmed[i] == ','.to_int().to_uint16() {
let value = trim_ows(trimmed[start:i].to_owned())
if value.length() == 0 {
return Err(
range_error(
AcceptRanges,
InvalidUnit,
start,
"empty Accept-Ranges unit",
),
)
}
if utf8_length(value) > limits.max_unit_bytes() {
return Err(
range_error(
Limit,
LimitExceeded,
start,
"Accept-Ranges unit exceeds limit",
),
)
}
for c in value {
if !is_tchar(c) {
return Err(
range_error(
AcceptRanges,
InvalidUnit,
start,
"invalid Accept-Ranges unit",
),
)
}
}
if ascii_equal(value, "none") {
return Err(
range_error(
AcceptRanges,
InvalidUnit,
start,
"none cannot be combined with range units",
),
)
}
units.push(ascii_lower(value))
start = i + 1
}
}
Ok(Units(units))
}
///|
pub fn AcceptRanges::supports(self : AcceptRanges, unit : String) -> Bool {
match self {
NoneAccepted => false
Units(units) => {
for value in units {
if ascii_equal(value, unit) {
return true
}
}
false
}
}
}
///|
pub fn AcceptRanges::supports_bytes(self : AcceptRanges) -> Bool {
self.supports("bytes")
}
///|
pub fn AcceptRanges::units(self : AcceptRanges) -> Array[String] {
match self {
NoneAccepted => []
Units(units) => units.copy()
}
}
///|
pub fn serialize_accept_ranges(value : AcceptRanges) -> String {
match value {
NoneAccepted => "none"
Units(units) => join_strings(units, ", ")
}
}