///|
/// Helper functions
///|
///|
fn ck_parse_cookie_pair(pair : String) -> Result[(String, String), CookieError] {
let eq_pos = ck_find_char(pair, 61) // =
match eq_pos {
None => return Err(InvalidFormat)
Some(pos) => {
let name = ck_trim_string(ck_string_slice(pair, 0, pos))
let value = ck_trim_string(ck_string_slice_from(pair, pos + 1))
if name.length() == 0 {
return Err(InvalidName)
}
if !ck_is_valid_cookie_name(name) {
return Err(InvalidName)
}
let value = if value.length() >= 2 &&
ck_char_at(value, 0) == 34 &&
ck_char_at(value, value.length() - 1) == 34 { // "
ck_string_slice(value, 1, value.length() - 1)
} else {
value
}
Ok((name, value))
}
}
}
///|
fn ck_is_valid_cookie_name(s : String) -> Bool {
if s.length() == 0 {
return false
}
let mut idx = 0
while idx < s.length() {
let ch = ck_char_at(s, idx)
if !ck_is_token_char(ch) {
return false
}
idx = idx + 1
}
true
}
///|
fn ck_is_valid_cookie_value(s : String) -> Bool {
let mut idx = 0
while idx < s.length() {
let ch = ck_char_at(s, idx)
if !ck_is_cookie_octet(ch) {
return false
}
idx = idx + 1
}
true
}
///|
fn ck_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 == 94 ||
b == 95 ||
b == 96 ||
b == 124 ||
b == 126 ||
(b >= 48 && b <= 57) ||
(b >= 65 && b <= 90) ||
(b >= 97 && b <= 122)
}
///|
fn ck_is_cookie_octet(b : Int) -> Bool {
b == 33 ||
(b >= 35 && b <= 43) ||
(b >= 45 && b <= 58) ||
(b >= 60 && b <= 91) ||
(b >= 93 && b <= 126)
}
///|
fn ck_parse_same_site(s : String) -> Result[SameSite, CookieError] {
let s_lower = ck_to_lower_case(s)
match s_lower {
"strict" => Ok(Strict)
"lax" => Ok(Lax)
"none" => Ok(SameSiteNone)
_ => Err(InvalidSameSite)
}
}
///|
fn ck_split_params(input : String) -> Array[String] {
let mut result : Array[String] = []
let mut current = ""
let mut in_quotes = false
let mut idx = 0
let len = input.length()
while idx < len {
let ch = ck_char_at(input, idx)
if ch == 34 { // "
current = current + "\""
in_quotes = !in_quotes
idx = idx + 1
} else if ch == 59 && !in_quotes { // ;
let new_result = []
let mut j = 0
while j < result.length() {
new_result.push(result[j])
j = j + 1
}
new_result.push(current)
result = new_result
current = ""
idx = idx + 1
} else {
current = current + Int::unsafe_to_char(ch).to_string()
idx = idx + 1
}
}
if current.length() > 0 {
let new_result = []
let mut j = 0
while j < result.length() {
new_result.push(result[j])
j = j + 1
}
new_result.push(current)
result = new_result
}
result
}
///|
fn ck_parse_i64(s : String) -> Int? {
let mut result = 0
let mut idx = 0
let len = s.length()
let mut is_negative = false
if len == 0 {
return None
}
if ck_char_at(s, 0) == 45 { // -
is_negative = true
idx = 1
}
while idx < len {
let ch = ck_char_at(s, idx)
if ch >= 48 && ch <= 57 { // 0-9
result = result * 10 + (ch - 48)
} else {
return None
}
idx = idx + 1
}
if is_negative {
Some(-result)
} else {
Some(result)
}
}
///|
fn ck_trim_string(s : String) -> String {
str_trim_string(s)
}
///|
fn ck_char_at(s : String, idx : Int) -> Int {
str_char_at(s, idx)
}
///|
fn ck_find_char(s : String, target : Int) -> Int? {
let mut idx = 0
while idx < s.length() {
if ck_char_at(s, idx) == target {
return Some(idx)
}
idx = idx + 1
}
None
}
///|
fn ck_string_slice(s : String, start : Int, end : Int) -> String {
str_string_slice(s, start, end)
}
///|
fn ck_string_slice_from(s : String, start : Int) -> String {
str_string_slice_from(s, start)
}
///|
fn ck_split_string(s : String, sep : Int) -> Array[String] {
str_split_char(s, sep)
}
///|
fn ck_to_lower_case(s : String) -> String {
str_to_lower_case(s)
}