use serde::{Deserialize, Serialize};
pub const IS_DELTA: u8 = 0x01;
pub const IS_COMPRESSED: u8 = 0x02;
pub const IS_TOMBSTONE: u8 = 0x04;
pub const HEADER_SIZE: usize = 15;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub enum Atom {
Null,
Float(f64),
Int(i64),
Text(String),
Bytes(Vec<u8>),
Vector(Vec<f32>, u16),
}
impl Atom {
pub fn type_name(&self) -> &'static str {
match self {
Atom::Null => "Null",
Atom::Float(_) => "Float",
Atom::Int(_) => "Int",
Atom::Text(_) => "Text",
Atom::Bytes(_) => "Bytes",
Atom::Vector(_, _) => "Vector",
}
}
pub fn is_float(&self) -> bool {
matches!(self, Atom::Float(_))
}
pub fn as_float(&self) -> Option<f64> {
match self {
Atom::Float(f) => Some(*f),
_ => None,
}
}
pub fn is_vector(&self) -> bool {
matches!(self, Atom::Vector(_, _))
}
pub fn as_vector(&self) -> Option<(&[f32], u16)> {
match self {
Atom::Vector(data, dims) => Some((data, *dims)),
_ => None,
}
}
}
impl From<f64> for Atom {
fn from(value: f64) -> Self {
Atom::Float(value)
}
}
impl From<i64> for Atom {
fn from(value: i64) -> Self {
Atom::Int(value)
}
}
impl From<String> for Atom {
fn from(value: String) -> Self {
Atom::Text(value)
}
}
impl From<Vec<u8>> for Atom {
fn from(value: Vec<u8>) -> Self {
Atom::Bytes(value)
}
}
#[repr(C, packed)]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct LogHeader {
pub timestamp: u64,
pub key_len: u16,
pub val_len: u32,
pub flags: u8,
}
impl LogHeader {
pub fn new(key_len: u16, val_len: u32, flags: u8) -> Self {
use std::time::{SystemTime, UNIX_EPOCH};
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_micros() as u64)
.unwrap_or(0);
Self {
timestamp,
key_len,
val_len,
flags,
}
}
pub fn to_bytes(&self) -> [u8; HEADER_SIZE] {
let mut buf = [0u8; HEADER_SIZE];
buf[0..8].copy_from_slice(&self.timestamp.to_le_bytes());
buf[8..10].copy_from_slice(&self.key_len.to_le_bytes());
buf[10..14].copy_from_slice(&self.val_len.to_le_bytes());
buf[14] = self.flags;
buf
}
pub fn from_bytes(buf: &[u8; HEADER_SIZE]) -> Self {
let timestamp = u64::from_le_bytes([
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
]);
let key_len = u16::from_le_bytes([buf[8], buf[9]]);
let val_len = u32::from_le_bytes([buf[10], buf[11], buf[12], buf[13]]);
let flags = buf[14];
Self {
timestamp,
key_len,
val_len,
flags,
}
}
pub fn is_valid(&self) -> bool {
self.key_len < 65535 && self.val_len < 1_000_000_000
}
}