use crate::{binary_put_uvariant_to_bufmut, binary_put_uvariant_to_vec, binary_uvarint};
use alloc::vec::Vec;
use bytes::{BufMut, Bytes, BytesMut};
pub const MAX_HEADER_SIZE: usize = 21;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(C)]
pub struct Header {
meta: u8,
user_meta: u8,
k_len: u32,
v_len: u32,
expires_at: u64,
}
impl Header {
pub fn encode(&self) -> (usize, Vec<u8>) {
let mut buf = Vec::with_capacity(MAX_HEADER_SIZE);
buf.push(self.meta);
buf.push(self.user_meta);
let mut index = 2;
index += binary_put_uvariant_to_vec(&mut buf, self.k_len as u64);
index += binary_put_uvariant_to_vec(&mut buf, self.v_len as u64);
index += binary_put_uvariant_to_vec(&mut buf, self.expires_at);
(index, buf)
}
pub fn encode_to_bytes(&self) -> (usize, Bytes) {
let mut buf = BytesMut::with_capacity(MAX_HEADER_SIZE);
buf.put_u8(self.meta);
buf.put_u8(self.user_meta);
let mut index = 2;
index += binary_put_uvariant_to_bufmut(&mut buf, self.k_len as u64);
index += binary_put_uvariant_to_bufmut(&mut buf, self.v_len as u64);
index += binary_put_uvariant_to_bufmut(&mut buf, self.expires_at);
(index, buf.freeze())
}
pub fn decode(data: &[u8]) -> (usize, Self) {
let mut index = 2;
let (k_len, ctr) = binary_uvarint(&data[index..]);
index += ctr;
let (v_len, ctr) = binary_uvarint(&data[index..]);
index += ctr;
let (expires_at, ctr) = binary_uvarint(&data[index..]);
(
index + ctr,
Self {
k_len: k_len as u32,
v_len: v_len as u32,
expires_at,
meta: data[0],
user_meta: data[1],
},
)
}
#[cfg(feature = "std")]
pub fn decode_reader(
reader: &mut impl ByteReader,
hash_buf: &mut BytesMut,
) -> std::io::Result<(usize, Self)> {
use crate::binary_read_and_put_uvarint;
let start = reader.position();
let meta = reader.read_byte()?;
hash_buf.put_u8(meta);
let user_meta = reader.read_byte()?;
hash_buf.put_u8(user_meta);
let k_len = binary_read_and_put_uvarint(reader, hash_buf)?;
let v_len = binary_read_and_put_uvarint(reader, hash_buf)?;
let expires_at = binary_read_and_put_uvarint(reader, hash_buf)?;
let h_len = reader.position() - start;
let h = Header {
k_len: k_len as u32,
v_len: v_len as u32,
expires_at,
meta,
user_meta,
};
Ok((h_len as usize, h))
}
pub fn update(&mut self, data: &[u8]) -> usize {
self.meta = data[0];
self.user_meta = data[1];
let mut index = 2;
let (k_len, ctr) = binary_uvarint(&data[index..]);
self.k_len = k_len as u32;
index += ctr;
let (v_len, ctr) = binary_uvarint(&data[index..]);
self.v_len = v_len as u32;
index += ctr;
let (expires_at, ctr) = binary_uvarint(&data[index..]);
self.expires_at = expires_at;
index + ctr
}
#[inline]
pub fn get_value_len(&self) -> u32 {
self.v_len
}
#[inline]
pub fn set_value_len(&mut self, vlen: u32) {
self.v_len = vlen
}
#[inline]
pub fn get_key_len(&self) -> u32 {
self.k_len
}
#[inline]
pub fn set_key_len(&mut self, klen: u32) {
self.k_len = klen
}
#[inline]
pub fn get_meta(&self) -> u8 {
self.meta
}
#[inline]
pub fn set_meta(&mut self, meta: u8) {
self.meta = meta
}
#[inline]
pub fn get_user_meta(&self) -> u8 {
self.user_meta
}
#[inline]
pub fn set_user_meta(&mut self, user_meta: u8) {
self.meta = user_meta
}
#[inline]
pub fn get_expires_at(&self) -> u64 {
self.expires_at
}
#[inline]
pub fn set_expires_at(&mut self, expires_at: u64) {
self.expires_at = expires_at
}
}
cfg_std! {
use std::io::Read;
pub trait ByteReader {
fn read_byte(&mut self) -> std::io::Result<u8>;
fn position(&self) -> u64;
}
macro_rules! impl_byte_reader_for_cursor {
($($ty: ty),+ $(,)?) => {
$(
impl ByteReader for std::io::Cursor<$ty> {
#[inline]
fn read_byte(&mut self) -> std::io::Result<u8> {
let mut buf = [0; 1];
self.read_exact(&mut buf).map(|_| buf[0])
}
#[inline]
fn position(&self) -> u64 {
self.position()
}
}
)*
};
}
impl_byte_reader_for_cursor! {
Box<[u8]>,
&[u8],
&mut [u8],
Vec<u8>,
&Vec<u8>,
&mut Vec<u8>
}
}