///|
/// RFC token characters needed for range-unit parsing.
fn is_tchar(c : Char) -> Bool {
  is_alpha(c) ||
  is_digit(c) ||
  c == '!' ||
  c == '#' ||
  c == '$' ||
  c == '%' ||
  c == '&' ||
  c == '\'' ||
  c == '*' ||
  c == '+' ||
  c == '-' ||
  c == '.' ||
  c == '^' ||
  c == '_' ||
  c == '`' ||
  c == '|' ||
  c == '~'
}

///|
fn is_alpha(c : Char) -> Bool {
  (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
}

///|
fn is_digit(c : Char) -> Bool {
  c >= '0' && c <= '9'
}

///|
fn is_ows(c : Char) -> Bool {
  c == ' ' || c == '\t'
}

///|
fn ascii_lower(value : String) -> String {
  let builder = StringBuilder()
  for c in value {
    if c >= 'A' && c <= 'Z' {
      builder.write_char((c.to_int() + 32).unsafe_to_char())
    } else {
      builder.write_char(c)
    }
  }
  builder.to_string()
}

///|
fn ascii_equal(left : String, right : String) -> Bool {
  ascii_lower(left) == ascii_lower(right)
}

///|
fn trim_ows(value : String) -> String {
  value.trim(chars=" \t").to_owned()
}

///|
fn utf8_length(value : String) -> Int {
  @utf8.encode(value).length()
}