///|
fn canonical_header_name(name : StringView) -> String {
let raw = clean(name).to_lower()
let buf = StringBuilder(size_hint=raw.length())
let mut upper_next = true
for c in raw.iter() {
if c == '-' {
buf.write_char('-')
upper_next = true
} else if upper_next && is_ascii_alpha(c) {
buf.write_string(c.to_string().to_upper())
upper_next = false
} else {
buf.write_char(c)
upper_next = false
}
}
buf.to_string()
}
///|
pub fn normalize_header_name(name : StringView) -> Result[String, ParseError] {
let raw = clean(name)
if raw.is_empty() {
return Err(InvalidToken(0, "header name", raw))
}
if !is_token(raw) {
return Err(InvalidToken(0, "header name", raw))
}
Ok(canonical_header_name(raw[:]))
}
///|
pub fn parse_header_list(
value : StringView,
) -> Result[Array[String], ParseError] {
let text = clean(value)
let result : Array[String] = []
if text.is_empty() {
return Ok(result)
}
let parts = split_quoted(text, ',')
for i in 0.. Result[Array[String], ParseError] {
let fields = match parse_header_list(value) {
Ok(fields) => fields
Err(err) => return Err(err)
}
let result : Array[String] = []
for i in 0.. push_unique(result, name)
Err(_) => return Err(InvalidToken(i, "Vary field", fields[i]))
}
}
Ok(result)
}
///|
pub fn join_header_names(names : Array[String]) -> String {
let buf = StringBuilder()
for i in 0.. 0 {
buf.write_string(", ")
}
buf.write_string(canonical_header_name(names[i][:]))
}
buf.to_string()
}
///|
pub fn vary_contains(vary : Array[String], field : StringView) -> Bool {
let wanted = canonical_header_name(field)
for item in vary {
if item == "*" || canonical_header_name(item[:]) == wanted {
return true
}
}
false
}
///|
pub fn merge_vary(
left : Array[String],
right : Array[String],
) -> Result[Array[String], ParseError] {
let result : Array[String] = []
for item in left {
if item == "*" {
return Ok(["*"])
}
match normalize_header_name(item[:]) {
Ok(name) => push_unique(result, name)
Err(err) => return Err(err)
}
}
for item in right {
if item == "*" {
return Ok(["*"])
}
match normalize_header_name(item[:]) {
Ok(name) => push_unique(result, name)
Err(err) => return Err(err)
}
}
Ok(result)
}
///|
pub fn decision_vary_header(decision : VariantDecision) -> String {
join_header_names(decision.vary)
}