novakv 1.0.1

An embedded, ordered key-value store for Rust.
Documentation
use crate::status::{Result, Status};

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WriteBatchRecord {
    Delete { key: Vec<u8> },
    Put { key: Vec<u8>, value: Vec<u8> },
}

impl WriteBatchRecord {
    pub fn encode(&self, dst: &mut Vec<u8>) {
        match self {
            Self::Delete { key } => {
                dst.push(0u8);
                crate::coding::put_length_prefixed_slice(dst, key);
            }
            Self::Put { key, value } => {
                dst.push(1u8);
                crate::coding::put_length_prefixed_slice(dst, key);
                crate::coding::put_length_prefixed_slice(dst, value);
            }
        }
    }

    pub fn decode_from(input: &mut &[u8]) -> Result<Self> {
        let tag = crate::coding::get_u8(input)
            .ok_or_else(|| Status::corruption("WriteBatchRecord: missing tag"))?;
        match tag {
            0 => {
                let key = crate::coding::get_length_prefixed_slice(input)
                    .map(<[u8]>::to_vec)
                    .ok_or_else(|| Status::corruption("WriteBatchRecord: missing key"))?;
                Ok(Self::Delete { key })
            }
            1 => {
                let key = crate::coding::get_length_prefixed_slice(input)
                    .map(<[u8]>::to_vec)
                    .ok_or_else(|| Status::corruption("WriteBatchRecord: missing key"))?;
                let value = crate::coding::get_length_prefixed_slice(input)
                    .map(<[u8]>::to_vec)
                    .ok_or_else(|| Status::corruption("WriteBatchRecord: missing value"))?;
                Ok(Self::Put { key, value })
            }
            other => Err(Status::corruption(format!(
                "WriteBatchRecord: unknown tag {other}"
            ))),
        }
    }

    pub fn encode_delete(dst: &mut Vec<u8>, key: &[u8]) {
        dst.reserve(6 + key.len());
        dst.push(0u8);
        crate::coding::put_length_prefixed_slice(dst, key);
    }

    pub fn encode_put(dst: &mut Vec<u8>, key: &[u8], value: &[u8]) {
        dst.reserve(11 + key.len() + value.len());
        dst.push(1u8);
        crate::coding::put_length_prefixed_slice(dst, key);
        crate::coding::put_length_prefixed_slice(dst, value);
    }

    pub fn visit<V: WriteBatchRecordVisitor>(input: &mut &[u8], visitor: &mut V) -> Result<()> {
        let tag = crate::coding::get_u8(input)
            .ok_or_else(|| Status::corruption("WriteBatchRecord: missing tag"))?;
        match tag {
            0 => {
                let key = crate::coding::get_length_prefixed_slice(input)
                    .ok_or_else(|| Status::corruption("WriteBatchRecord: missing key"))?;
                visitor.delete(key);
            }
            1 => {
                let key = crate::coding::get_length_prefixed_slice(input)
                    .ok_or_else(|| Status::corruption("WriteBatchRecord: missing key"))?;
                let value = crate::coding::get_length_prefixed_slice(input)
                    .ok_or_else(|| Status::corruption("WriteBatchRecord: missing value"))?;
                visitor.put(key, value);
            }
            other => {
                return Err(Status::corruption(format!(
                    "WriteBatchRecord: unknown tag {other}"
                )))
            }
        }
        Ok(())
    }
}

pub trait WriteBatchRecordVisitor {
    fn delete(&mut self, key: &[u8]);
    fn put(&mut self, key: &[u8], value: &[u8]);
}