///|
pub fn bytes_concat(left : Bytes, right : Bytes) -> Bytes {
let buffer = @buffer.Buffer(size_hint=left.length() + right.length())
buffer.write_bytes(left)
buffer.write_bytes(right)
buffer.to_bytes()
}
///|
pub fn bytes_slice(
input : Bytes,
start : Int,
end : Int,
) -> Result[Bytes, ProxyError] {
if start < 0 || end < start || end > input.length() {
Err(proxy_error(InvalidLength, start, "invalid byte slice"))
} else {
Ok(Bytes::from_array(input.to_array()[start:end]))
}
}
///|
pub fn bytes_equal_constant_time(left : Bytes, right : Bytes) -> Bool {
let mut different = left.length() ^ right.length()
let limit = if left.length() < right.length() {
left.length()
} else {
right.length()
}
for i = 0; i < limit; i = i + 1 {
different = different | (left[i].to_int() ^ right[i].to_int())
}
different == 0
}
///|
fn hex_nibble(value : Int) -> Char {
if value < 10 {
('0'.to_int() + value).to_char().unwrap()
} else {
('a'.to_int() + value - 10).to_char().unwrap()
}
}
///|
pub fn hex_encode(input : Bytes) -> String {
let chars = Array::make(input.length() * 2, '0')
for i = 0; i < input.length(); i = i + 1 {
chars[i * 2] = hex_nibble(input[i].to_int() / 16)
chars[i * 2 + 1] = hex_nibble(input[i].to_int() % 16)
}
String::from_array(chars)
}
///|
fn decode_hex_char(ch : Char) -> Int {
let n = ch.to_int()
if n >= '0'.to_int() && n <= '9'.to_int() {
n - '0'.to_int()
} else if n >= 'a'.to_int() && n <= 'f'.to_int() {
n - 'a'.to_int() + 10
} else if n >= 'A'.to_int() && n <= 'F'.to_int() {
n - 'A'.to_int() + 10
} else {
-1
}
}
///|
pub fn hex_decode(input : String) -> Result[Bytes, ProxyError] {
let chars = input.to_array()
if chars.length() % 2 != 0 {
return Err(
proxy_error(
InvalidLength,
chars.length(),
"hex needs an even number of characters",
),
)
}
let buffer = @buffer.Buffer(size_hint=chars.length() / 2)
for i = 0; i < chars.length(); i = i + 2 {
let hi = decode_hex_char(chars[i])
let lo = decode_hex_char(chars[i + 1])
if hi < 0 || lo < 0 {
return Err(proxy_error(InvalidLength, i, "invalid hexadecimal digit"))
}
buffer.write_byte((hi * 16 + lo).to_byte())
}
Ok(buffer.to_bytes())
}