///|
/// Vary header parsing errors (RFC 9110 Section 12.5.5)
pub(all) enum VaryError {
Empty
InvalidFormat
InvalidFieldName
} derive(Show, Eq)
///|
/// Vary header (RFC 9110 Section 12.5.5)
pub(all) struct Vary {
any : Bool
fields : Array[String]
} derive(Show, Eq)
///|
pub fn Vary::parse(input : String) -> Result[Vary, VaryError] {
let s = vary_trim_string(input)
if s.length() == 0 {
return Err(Empty)
}
if s == "*" {
return Ok({ any: true, fields: [] })
}
let parts = vary_split_string(s, ",")
let fields : Array[String] = []
let mut idx = 0
while idx < parts.length() {
let name = vary_trim_string(parts[idx])
if name.length() == 0 {
return Err(InvalidFormat)
}
if !vary_is_valid_token(name) {
return Err(InvalidFieldName)
}
fields.push(vary_to_lower_case(name))
idx = idx + 1
}
if fields.length() == 0 {
return Err(Empty)
}
Ok({ any: false, fields })
}
///|
pub fn Vary::is_any(self : Vary) -> Bool {
self.any
}
///|
pub fn Vary::fields(self : Vary) -> Array[String] {
self.fields
}
///|
pub fn Vary::to_string(self : Vary) -> String {
if self.any {
"*"
} else {
vary_join_strings(self.fields, ", ")
}
}
///|
/// Helper functions
///
///|
fn vary_is_valid_token(s : String) -> Bool {
if s.length() == 0 {
return false
}
let mut idx = 0
while idx < s.length() {
if !vary_is_token_char(vary_char_at(s, idx)) {
return false
}
idx = idx + 1
}
true
}
///|
fn vary_is_token_char(b : Int) -> Bool {
b == 33 ||
b == 35 ||
b == 36 ||
b == 37 ||
b == 38 ||
b == 39 ||
b == 42 ||
b == 43 ||
b == 45 ||
b == 46 ||
b == 48 ||
b == 49 ||
b == 50 ||
b == 51 ||
b == 52 ||
b == 53 ||
b == 54 ||
b == 55 ||
b == 56 ||
b == 57 ||
(b >= 65 && b <= 90) ||
b == 94 ||
b == 95 ||
b == 96 ||
(b >= 97 && b <= 122) ||
b == 124 ||
b == 126
}
///|
fn vary_char_at(s : String, idx : Int) -> Int {
str_char_at(s, idx)
}
///|
fn vary_to_lower_case(s : String) -> String {
str_to_lower_case(s)
}
///|
fn vary_trim_string(s : String) -> String {
str_trim_string(s)
}
///|
fn vary_split_string(s : String, sep : String) -> Array[String] {
str_split_string(s, sep)
}
///|
fn vary_join_strings(strs : Array[String], sep : String) -> String {
let mut result = ""
let mut idx = 0
while idx < strs.length() {
if idx > 0 {
result = result + sep
}
result = result + strs[idx]
idx = idx + 1
}
result
}