use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
use sha2::{Digest, Sha256};
pub fn base64url_encode(data: &[u8]) -> String {
URL_SAFE_NO_PAD.encode(data)
}
pub fn base64url_decode(s: &str) -> Result<Vec<u8>, base64::DecodeError> {
URL_SAFE_NO_PAD.decode(s)
}
pub fn sha256(data: &[u8]) -> Vec<u8> {
Sha256::digest(data).to_vec()
}
pub fn write_varint(buf: &mut Vec<u8>, mut value: u64) {
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
buf.push(byte);
if value == 0 {
break;
}
}
}
pub fn read_varint(data: &[u8], mut pos: usize) -> Result<(u64, usize), String> {
let mut value = 0u64;
let mut shift = 0;
loop {
if pos >= data.len() {
return Err("unexpected end of data".to_string());
}
let byte = data[pos];
pos += 1;
value |= ((byte & 0x7F) as u64) << shift;
shift += 7;
if (byte & 0x80) == 0 {
break;
}
if shift >= 64 {
return Err("varint too long".to_string());
}
}
Ok((value, pos))
}
pub fn len_varint(mut value: u64) -> usize {
if value == 0 {
return 1;
}
let mut len = 0;
while value > 0 {
value >>= 7;
len += 1;
}
len
}