use crate::error::{Result, TakError};
use bytes::{Buf, BufMut, BytesMut};
use prost::Message;
const TAK_MAGIC_BYTE: u8 = 0xbf;
pub fn encode_varint(value: u64, buf: &mut BytesMut) {
let mut val = value;
loop {
let mut byte = (val & 0x7F) as u8;
val >>= 7;
if val != 0 {
byte |= 0x80;
}
buf.put_u8(byte);
if val == 0 {
break;
}
}
}
pub fn decode_varint(buf: &mut impl Buf) -> Result<u64> {
let mut result: u64 = 0;
let mut shift = 0;
for _ in 0..10 {
if !buf.has_remaining() {
return Err(TakError::InvalidVarint);
}
let byte = buf.get_u8();
result |= ((byte & 0x7F) as u64) << shift;
if byte & 0x80 == 0 {
return Ok(result);
}
shift += 7;
}
Err(TakError::InvalidVarint)
}
pub fn encode_tak_message<M: Message>(message: &M) -> Result<BytesMut> {
let mut payload = BytesMut::new();
message.encode(&mut payload)?;
let payload_len = payload.len() as u64;
let mut frame = BytesMut::with_capacity(1 + 10 + payload.len());
frame.put_u8(TAK_MAGIC_BYTE);
encode_varint(payload_len, &mut frame);
frame.put(payload);
Ok(frame)
}
pub fn decode_tak_header(buf: &mut BytesMut) -> Result<Option<usize>> {
if buf.is_empty() {
return Ok(None);
}
if buf.len() < 1 {
return Ok(None);
}
if buf[0] != TAK_MAGIC_BYTE {
return Err(TakError::InvalidMessage(format!(
"Expected magic byte 0xbf, got 0x{:02x}",
buf[0]
)));
}
let mut temp_buf = &buf[1..];
let start_remaining = temp_buf.remaining();
match decode_varint(&mut temp_buf) {
Ok(length) => {
let varint_len = start_remaining - temp_buf.remaining();
let header_len = 1 + varint_len;
buf.advance(header_len);
Ok(Some(length as usize))
}
Err(TakError::InvalidVarint) => {
Ok(None)
}
Err(e) => Err(e),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_varint_encoding() {
let test_cases = vec![
(0u64, vec![0x00]),
(1u64, vec![0x01]),
(127u64, vec![0x7F]),
(128u64, vec![0x80, 0x01]),
(300u64, vec![0xAC, 0x02]),
];
for (value, expected) in test_cases {
let mut buf = BytesMut::new();
encode_varint(value, &mut buf);
assert_eq!(buf.to_vec(), expected, "Failed for value {}", value);
let mut decode_buf = buf.clone();
let decoded = decode_varint(&mut decode_buf).unwrap();
assert_eq!(decoded, value, "Failed decoding value {}", value);
}
}
#[test]
fn test_tak_header() {
let mut buf = BytesMut::new();
buf.put_u8(TAK_MAGIC_BYTE);
encode_varint(42, &mut buf);
let length = decode_tak_header(&mut buf).unwrap().unwrap();
assert_eq!(length, 42);
}
}