use byteorder::{BigEndian, ReadBytesExt};
use bytes::{BufMut, BytesMut};
use std::io::{self, Cursor};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum DelDupLnEntryError {
#[error("I/O error: {0}")]
Io(#[from] io::Error),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DelDupLnEntry {
pub key: Vec<u8>,
pub dup_key: Vec<u8>,
}
impl DelDupLnEntry {
pub fn new(key: Vec<u8>, dup_key: Vec<u8>) -> Self {
Self { key, dup_key }
}
pub fn log_size(&self) -> usize {
4 + self.key.len() + 4 + self.dup_key.len() }
pub fn write_to_log(&self, buf: &mut BytesMut) {
buf.put_u32(self.key.len() as u32);
buf.extend_from_slice(&self.key);
buf.put_u32(self.dup_key.len() as u32);
buf.extend_from_slice(&self.dup_key);
}
pub fn read_from_log(buf: &[u8]) -> Result<Self, DelDupLnEntryError> {
let mut cursor = Cursor::new(buf);
let key_len = cursor.read_u32::<BigEndian>()? as usize;
let mut key = vec![0u8; key_len];
io::Read::read_exact(&mut cursor, &mut key)?;
let dup_key_len = cursor.read_u32::<BigEndian>()? as usize;
let mut dup_key = vec![0u8; dup_key_len];
io::Read::read_exact(&mut cursor, &mut dup_key)?;
Ok(Self { key, dup_key })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_del_dup_ln_roundtrip() {
let entry = DelDupLnEntry::new(
b"primary_key".to_vec(),
b"dup_key_value".to_vec(),
);
let mut buf = BytesMut::new();
entry.write_to_log(&mut buf);
let decoded = DelDupLnEntry::read_from_log(&buf).unwrap();
assert_eq!(entry, decoded);
assert_eq!(decoded.key, b"primary_key");
assert_eq!(decoded.dup_key, b"dup_key_value");
}
#[test]
fn test_del_dup_ln_empty_keys() {
let entry = DelDupLnEntry::new(vec![], vec![]);
let mut buf = BytesMut::new();
entry.write_to_log(&mut buf);
let decoded = DelDupLnEntry::read_from_log(&buf).unwrap();
assert_eq!(entry, decoded);
}
#[test]
fn test_log_size() {
let key = b"pk".to_vec();
let dup_key = b"dk".to_vec();
let entry = DelDupLnEntry::new(key.clone(), dup_key.clone());
assert_eq!(entry.log_size(), 4 + key.len() + 4 + dup_key.len());
let mut buf = BytesMut::new();
entry.write_to_log(&mut buf);
assert_eq!(buf.len(), entry.log_size());
}
}