orderwal 0.5.1

A generic-purpose, atomic, ordered, zero-copy read, zero-cost (in-place) write, Write-Ahead Log implementation for Rust.
Documentation
use base::OrderWal;

use dbutils::{buffer::VacantBuffer, types::MaybeStructured};

use std::collections::BTreeMap;

use crate::{
  memtable::{alternative::TableOptions, Memtable, MemtableEntry},
  swmr::base::{Reader, Writer},
  types::{KeyBuilder, ValueBuilder},
};

use super::*;

fn first<M>(wal: &mut OrderWal<Person, String, M>)
where
  M: Memtable<Key = Person, Value = String> + 'static,
  for<'a> M::Item<'a>: MemtableEntry<'a>,
  M::Error: std::fmt::Debug,
{
  let people = (0..10)
    .map(|_| {
      let p = Person::random();
      let v = std::format!("My name is {}", p.name);
      wal.insert(&p, &v).unwrap();

      (p, v)
    })
    .collect::<BTreeMap<_, _>>();

  let ent = wal.first().unwrap();
  let (p, v) = people.first_key_value().unwrap();
  assert!(ent.key().equivalent(p));
  assert_eq!(ent.value(), v);

  let wal = wal.reader();
  let ent = wal.first().unwrap();
  let (p, v) = people.first_key_value().unwrap();
  assert!(ent.key().equivalent(p));
  assert_eq!(ent.value(), v);
}

fn last<M>(wal: &mut OrderWal<Person, String, M>)
where
  M: Memtable<Key = Person, Value = String> + 'static,
  for<'a> M::Item<'a>: MemtableEntry<'a>,
  M::Error: std::fmt::Debug,
{
  let people = (0..10)
    .map(|_| {
      let p = Person::random();
      let v = std::format!("My name is {}", p.name);
      wal.insert(&p, &v).unwrap();

      (p, v)
    })
    .collect::<BTreeMap<_, _>>();

  let ent = wal.last().unwrap();
  let (p, v) = people.last_key_value().unwrap();
  assert!(ent.key().equivalent(p));
  assert_eq!(ent.value(), v);

  let wal = wal.reader();
  let ent = wal.last().unwrap();
  assert!(ent.key().equivalent(p));
  assert_eq!(ent.value(), v);
}

#[allow(clippy::needless_borrows_for_generic_args)]
fn insert<M>(wal: &mut OrderWal<Person, String, M>)
where
  M: Memtable<Key = Person, Value = String> + 'static,
  for<'a> M::Item<'a>: MemtableEntry<'a>,
  M::Error: std::fmt::Debug,
{
  let people = (0..100)
    .map(|_| {
      let p = Person::random();
      let v = std::format!("My name is {}", p.name);
      wal.insert(&p, &v).unwrap();
      (p, v)
    })
    .collect::<Vec<_>>();

  assert_eq!(wal.len(), 100);

  for (p, pv) in &people {
    assert!(wal.contains_key(p));

    assert_eq!(wal.get(p).unwrap().value(), pv);
  }

  for (p, _) in &people {
    assert!(wal.contains_key(p));
  }
}

fn insert_with_value_builder<M>(wal: &mut OrderWal<Person, String, M>)
where
  M: Memtable<Key = Person, Value = String> + 'static,
  for<'a> M::Item<'a>: MemtableEntry<'a>,
  M::Error: std::fmt::Debug,
{
  let people = (0..100)
    .map(|_| {
      let p = Person::random();
      let v = std::format!("My name is {}", p.name);
      wal
        .insert_with_value_builder(
          &p,
          ValueBuilder::new(v.len(), |buf: &mut VacantBuffer<'_>| {
            buf.put_slice(v.as_bytes()).map(|_| v.len())
          }),
        )
        .unwrap();
      (p, v)
    })
    .collect::<Vec<_>>();

  assert_eq!(wal.len(), 100);

  for (p, _) in &people {
    assert!(wal.contains_key(p));
    assert!(wal.contains_key(&p.as_ref()));
  }
}

#[allow(clippy::needless_borrows_for_generic_args)]
fn insert_with_key_builder<M>(wal: &mut OrderWal<Person, String, M>)
where
  M: Memtable<Key = Person, Value = String> + 'static,
  for<'a> M::Item<'a>: MemtableEntry<'a>,
  M::Error: std::fmt::Debug,
{
  let people = (0..100)
    .map(|_| {
      let p = Person::random();
      let pvec = p.to_vec();
      let v = std::format!("My name is {}", p.name);
      unsafe {
        wal
          .insert_with_key_builder(
            KeyBuilder::once(p.encoded_len(), |buf| p.encode_to_buffer(buf)),
            &v,
          )
          .unwrap();
      }
      (p, v)
    })
    .collect::<Vec<_>>();

  assert_eq!(wal.len(), 100);

  for (p, pv) in &people {
    assert!(wal.contains_key(p));
    assert_eq!(wal.get(p).unwrap().value(), pv);
  }

  for (p, _) in &people {
    assert!(wal.contains_key(p));
  }
}

fn insert_with_bytes<M>(wal: &mut OrderWal<Person, String, M>)
where
  M: Memtable<Key = Person, Value = String> + 'static,
  for<'a> M::Item<'a>: MemtableEntry<'a>,
  M::Error: std::fmt::Debug,
{
  let people = (0..100)
    .map(|_| {
      let p = Person::random();
      let v = std::format!("My name is {}", p.name);
      unsafe {
        wal
          .insert(
            MaybeStructured::from_slice(p.to_vec().as_slice()),
            MaybeStructured::from_slice(v.as_bytes()),
          )
          .unwrap();
      }
      (p, v)
    })
    .collect::<Vec<_>>();

  assert_eq!(wal.len(), 100);

  for (p, pv) in &people {
    assert!(wal.contains_key(p));
    assert!(wal.contains_key(&p.as_ref()));
    assert_eq!(wal.get(p).unwrap().value(), pv);
  }
}

fn insert_with_builders<M>(wal: &mut OrderWal<Person, String, M>)
where
  M: Memtable<Key = Person, Value = String> + 'static,
  for<'a> M::Item<'a>: MemtableEntry<'a> + std::fmt::Debug,
  M::Error: std::fmt::Debug,
{
  let people = (0..1)
    .map(|_| {
      let p = Person::random();
      let pvec = p.to_vec();
      let v = std::format!("My name is {}", p.name);
      wal
        .insert_with_builders(
          KeyBuilder::new(pvec.len(), |buf: &mut VacantBuffer<'_>| {
            p.encode_to_buffer(buf)
          }),
          ValueBuilder::new(v.len(), |buf: &mut VacantBuffer<'_>| {
            buf.put_slice(v.as_bytes()).map(|_| v.len())
          }),
        )
        .unwrap();
      (p, pvec, v)
    })
    .collect::<Vec<_>>();

  assert_eq!(wal.len(), 1);

  for (p, pvec, pv) in &people {
    assert!(wal.contains_key(p));
    unsafe {
      assert_eq!(wal.get_by_bytes(pvec.as_ref()).unwrap().value(), pv);
    }
  }

  for (p, _, _) in &people {
    assert!(wal.contains_key(p));
  }
}

#[cfg(feature = "std")]
expand_unit_tests!("linked": OrderWalAlternativeTable<Person, String> [TableOptions::Linked]: crate::memtable::alternative::Table<_, _> {
  first,
  last,
  insert,
  insert_with_value_builder,
  insert_with_key_builder,
  insert_with_bytes,
  insert_with_builders,
});

expand_unit_tests!("arena": OrderWalAlternativeTable<Person, String> [TableOptions::Arena(Default::default())]: crate::memtable::alternative::Table<_, _> {
  first,
  last,
  insert,
  insert_with_value_builder,
  insert_with_key_builder,
  insert_with_bytes,
  insert_with_builders,
});