use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Key {
pub data: Vec<u8>,
pub metadata: Option<Vec<u8>>,
}
impl Key {
pub fn new(data: Vec<u8>) -> Self {
Self {
data,
metadata: None,
}
}
pub fn with_metadata(data: Vec<u8>, metadata: Vec<u8>) -> Self {
Self {
data,
metadata: Some(metadata),
}
}
pub fn as_bytes(&self) -> &[u8] {
&self.data
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
impl PartialOrd for Key {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Key {
fn cmp(&self, other: &Self) -> Ordering {
self.data.cmp(&other.data)
}
}
impl From<Vec<u8>> for Key {
fn from(data: Vec<u8>) -> Self {
Self::new(data)
}
}
impl From<&[u8]> for Key {
fn from(data: &[u8]) -> Self {
Self::new(data.to_vec())
}
}
impl From<String> for Key {
fn from(s: String) -> Self {
Self::new(s.into_bytes())
}
}
impl From<&str> for Key {
fn from(s: &str) -> Self {
Self::new(s.as_bytes().to_vec())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Value {
pub data: Vec<u8>,
pub compressed: bool,
pub checksum: Option<u32>,
}
impl Value {
pub fn new(data: Vec<u8>) -> Self {
Self {
data,
compressed: false,
checksum: None,
}
}
pub fn compressed(data: Vec<u8>, checksum: u32) -> Self {
Self {
data,
compressed: true,
checksum: Some(checksum),
}
}
pub fn as_bytes(&self) -> &[u8] {
&self.data
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn is_large(&self, threshold: usize) -> bool {
self.data.len() >= threshold
}
}
impl From<Vec<u8>> for Value {
fn from(data: Vec<u8>) -> Self {
Self::new(data)
}
}
impl From<&[u8]> for Value {
fn from(data: &[u8]) -> Self {
Self::new(data.to_vec())
}
}
impl From<String> for Value {
fn from(s: String) -> Self {
Self::new(s.into_bytes())
}
}
impl From<&str> for Value {
fn from(s: &str) -> Self {
Self::new(s.as_bytes().to_vec())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ValuePointer {
pub segment_id: u64,
pub offset: u64,
pub length: u32,
pub checksum: Option<u32>,
}
impl ValuePointer {
pub fn new(segment_id: u64, offset: u64, length: u32) -> Self {
Self {
segment_id,
offset,
length,
checksum: None,
}
}
pub fn with_checksum(segment_id: u64, offset: u64, length: u32, checksum: u32) -> Self {
Self {
segment_id,
offset,
length,
checksum: Some(checksum),
}
}
pub fn end_offset(&self) -> u64 {
self.offset + self.length as u64
}
pub fn is_valid(&self) -> bool {
self.segment_id > 0 && self.offset > 0 && self.length > 0
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entry {
pub key: Key,
pub value: Option<Value>,
pub value_pointer: Option<ValuePointer>,
pub sequence: u64,
pub op_type: OpType,
pub timestamp: u64,
}
impl Entry {
pub fn new(key: Key, value: Value, sequence: u64) -> Self {
Self {
key,
value: Some(value),
value_pointer: None,
sequence,
op_type: OpType::Put,
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64,
}
}
pub fn with_pointer(key: Key, value_pointer: ValuePointer, sequence: u64) -> Self {
Self {
key,
value: None,
value_pointer: Some(value_pointer),
sequence,
op_type: OpType::Put,
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64,
}
}
pub fn delete(key: Key, sequence: u64) -> Self {
Self {
key,
value: None,
value_pointer: None,
sequence,
op_type: OpType::Delete,
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64,
}
}
pub fn has_inline_value(&self) -> bool {
self.value.is_some()
}
pub fn has_value_pointer(&self) -> bool {
self.value_pointer.is_some()
}
pub fn is_delete(&self) -> bool {
matches!(self.op_type, OpType::Delete)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum OpType {
Put,
Delete,
Merge,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Batch {
pub operations: Vec<Entry>,
pub sequence: u64,
pub sync: bool,
}
impl Batch {
pub fn new() -> Self {
Self {
operations: Vec::new(),
sequence: 0,
sync: false,
}
}
pub fn add(&mut self, operation: Entry) {
self.operations.push(operation);
}
pub fn with_sequence(mut self, sequence: u64) -> Self {
self.sequence = sequence;
self
}
pub fn with_sync(mut self, sync: bool) -> Self {
self.sync = sync;
self
}
pub fn is_empty(&self) -> bool {
self.operations.is_empty()
}
pub fn len(&self) -> usize {
self.operations.len()
}
}
impl Default for Batch {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Range {
pub start: Key,
pub end: Key,
pub limit: Option<usize>,
}
impl Range {
pub fn new(start: Key, end: Key) -> Self {
Self {
start,
end,
limit: None,
}
}
pub fn with_limit(mut self, limit: usize) -> Self {
self.limit = Some(limit);
self
}
}