mod cache;
mod iterator;
mod node;
pub(crate) mod proxy;
use crate::__private::storage_traits;
use crate::__private::storage_traits::private::Sealed;
use cache::Cache;
use iterator::LazyVecIt;
use node::Node;
use proxy::{Proxy, ProxyMut};
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::cmp::Ordering;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
pub(crate) const ROOT_KEY: u64 = 0;
pub(crate) const ORDER: usize = 16;
pub struct LazyVec<V> {
cache: Cache<V>,
}
impl<V: Serialize> Debug for LazyVec<V>
where
V: Serialize + DeserializeOwned + Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if self.fmt_internal(ROOT_KEY, 0, f).is_ok() {
writeln!(f)?;
}
Ok(())
}
}
impl<V> LazyVec<V>
where
V: Serialize + DeserializeOwned + Debug,
{
fn fmt_internal(&self, node_key: u64, depth: usize, f: &mut Formatter<'_>) -> std::fmt::Result {
let indent = " ".repeat(depth);
let node = self.cache.read(node_key);
if f.alternate() {
writeln!(f, "{}{:#?}", indent, node)?;
} else {
writeln!(f, "{}{:?}", indent, node)?;
}
for child_key in node.borrow().children.iter() {
self.fmt_internal(*child_key, depth.saturating_add(1), f)?;
}
Ok(())
}
}
impl<V> LazyVec<V>
where
V: Serialize + DeserializeOwned + PartialEq,
{
pub fn contains(&self, value: V) -> bool {
let mut node = self.cache.read(ROOT_KEY);
while !node.borrow().is_leaf() {
let child_key = node.borrow().children[0];
node = self.cache.read(child_key);
}
loop {
if node.borrow().values.contains(&value) {
return true;
}
let next = node.borrow().next;
match next {
None => return false,
Some(key) => node = self.cache.read(key),
}
}
}
}
impl<V> Sealed for LazyVec<V> where V: Serialize + DeserializeOwned {}
impl<V> storage_traits::Storeable for LazyVec<V>
where
V: Serialize + DeserializeOwned,
{
fn decode(base_key: u64) -> Self {
LazyVec::open(base_key)
}
fn parse_value(value: serde_json::Value, base_key: u64) -> anyhow::Result<Self> {
let values: Vec<V> = serde_json::from_value(value)?;
let mut out = Self::new(base_key);
for v in values {
out.push(v);
}
Ok(out)
}
fn commit(self, _base_key: u64) {
self.cache.commit();
}
}
impl<V> storage_traits::ToPayload for LazyVec<V>
where
V: Serialize + DeserializeOwned,
{
fn to_payload(&self, path: &str) -> anyhow::Result<Option<String>> {
if !path.is_empty() {
return Ok(None);
}
let n_items = self.len();
if n_items == 0 {
return Ok(Some("[]".to_string()));
}
let first = self.iter().next().unwrap();
let encoded = serde_json::to_string(first.as_ref())?;
let mut buf = String::with_capacity(encoded.len() * n_items + n_items + 10);
buf.push('[');
for item in self.iter() {
let encoded = serde_json::to_string(item.as_ref())?;
buf.push_str(&encoded);
buf.push(',');
}
if n_items > 0 {
buf.pop();
}
buf.push(']');
Ok(Some(buf))
}
}
impl<V> LazyVec<V>
where
V: Serialize + DeserializeOwned,
{
fn get_node_rank(&self, key: u64) -> usize {
self.cache.read(key).borrow().rank()
}
fn is_node_empty(&self, key: u64) -> bool {
let node = self.cache.read(key);
let node = node.borrow();
if node.is_leaf() {
node.values.is_empty()
} else {
match node.level {
1 => node.keys.is_empty(),
_ => node.keys.len() == 1 && node.keys[0] == 0,
}
}
}
pub(crate) fn new(base_key: u64) -> Self {
Self {
cache: Cache::new(base_key, true),
}
}
pub(crate) fn open(base_key: u64) -> Self {
Self {
cache: Cache::new(base_key, false),
}
}
fn get_elements(&self) -> usize {
self.cache.read(ROOT_KEY).borrow().rank()
}
pub fn len(&self) -> usize {
self.get_elements()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn clear(&mut self) {
self.cache.reset();
self.load(ROOT_KEY);
self.cache.clear();
}
pub fn get_mut(&mut self, index: usize) -> Option<ProxyMut<'_, V>> {
match index.cmp(&self.get_elements()) {
Ordering::Less => Some(self.get_mut_internal(index, ROOT_KEY)),
_ => None,
}
}
pub fn get(&self, index: usize) -> Option<Proxy<'_, V>> {
match index.cmp(&self.get_elements()) {
Ordering::Less => Some(self.get_internal(index, ROOT_KEY)),
_ => None,
}
}
pub fn push(&mut self, value: V) {
if let Some(new_subtree) = self.push_internal(value, ROOT_KEY) {
self.update_root(new_subtree);
}
}
pub fn pop(&mut self) -> Option<V> {
if self.is_empty() {
return None;
}
let (value, _) = self.pop_internal(ROOT_KEY);
self.prune_root();
Some(value)
}
pub fn insert(&mut self, index: usize, element: V) {
match index.cmp(&self.get_elements()) {
Ordering::Greater => {
panic!("Out of bounds");
}
Ordering::Equal => {
self.push(element);
}
Ordering::Less => {
if let Some(leaf_key) = self.insert_internal(index, element, ROOT_KEY) {
let root = self.cache.read(ROOT_KEY);
let subtree_key = self.create_subtree(root.borrow().level(), leaf_key);
self.update_root(subtree_key);
}
}
}
}
pub fn remove(&mut self, index: usize) -> V {
match index.cmp(&self.get_elements()) {
Ordering::Greater => {
panic!("Out of bounds");
}
Ordering::Equal => {
match self.pop() {
None => panic!("Out of bounds"),
Some(value) => value,
}
}
Ordering::Less => {
let (_empty, val) = self.remove_internal(index, ROOT_KEY);
self.prune_root();
val
}
}
}
fn get_mut_internal(&mut self, index: usize, node_key: u64) -> ProxyMut<'_, V> {
debug_assert!(index < self.get_elements(), "index out of bounds");
let node = self.cache.read(node_key);
if node.borrow().is_leaf() {
self.cache.flag_write(node_key);
ProxyMut {
node_ptr: node,
elem_idx: index,
_back_ref: PhantomData,
}
} else {
let (tgt_index, acc) = Self::select_child(&node.borrow().keys, index);
let new_index = index.saturating_sub(acc);
self.get_mut_internal(new_index, node.borrow().children[tgt_index])
}
}
fn get_internal(&self, index: usize, node_key: u64) -> Proxy<'_, V> {
debug_assert!(index < self.get_elements(), "index out of bounds");
let node = self.cache.read(node_key);
if node.borrow().is_leaf() {
Proxy {
node_ptr: node,
elem_idx: index,
_back_ref: PhantomData,
}
} else {
let (tgt_index, acc) = Self::select_child(&node.borrow().keys, index);
let new_index = index.saturating_sub(acc);
self.get_internal(new_index, node.borrow().children[tgt_index])
}
}
fn push_internal(&mut self, value: V, node_key: u64) -> Option<u64> {
let node = self.cache.read(node_key);
let mut node = node.borrow_mut();
if node.is_leaf() {
if node.values.len() >= ORDER {
let new_leaf = Node::generate_leaf(ORDER, vec![value], node.next);
let new_key = self.new_key();
self.cache.write(new_key, new_leaf);
node.next = Some(new_key); self.cache.flag_write(node_key);
return Some(new_key);
}
node.values.push(value); } else {
let last_child = *node.children.last().unwrap();
match self.push_internal(value, last_child) {
Some(key) => {
if node.keys.len() >= ORDER {
let new_int = Node::generate_internal(ORDER, node.level, key);
let new_key = self.new_key();
self.cache.write(new_key, new_int);
return Some(new_key);
}
node.keys.push(1); node.children.push(key); }
None => {
if let Some(last_key) = node.keys.last_mut() {
*last_key = last_key.saturating_add(1);
}
}
}
}
self.cache.flag_write(node_key);
None
}
fn pop_internal(&mut self, node_key: u64) -> (V, bool) {
let node = self.cache.read(node_key);
let mut node = node.borrow_mut();
if node.is_leaf() {
let value = node.values.pop().unwrap(); let empty = node.values.is_empty();
self.cache.flag_write(node_key);
(value, empty)
} else {
let (value, empty) = self.pop_internal(*node.children.last().unwrap());
if empty {
node.keys.pop();
self.cache.remove(node.children.pop().unwrap());
let empty = node.keys.is_empty();
self.cache.flag_write(node_key);
if !empty {
drop(node);
self.reset_next(node_key);
}
(value, empty)
} else {
if let Some(last_key) = node.keys.last_mut() {
*last_key = last_key.saturating_sub(1);
}
self.cache.flag_write(node_key);
(value, false)
}
}
}
fn insert_internal(&mut self, index: usize, element: V, node_key: u64) -> Option<u64> {
let node = self.cache.read(node_key);
let mut node = node.borrow_mut();
let mut result = None;
if node.is_leaf() {
node.values.insert(index, element);
if node.values.len() >= ORDER * 2 {
let new_leaf = Node::generate_leaf(ORDER, node.values.split_off(ORDER), node.next);
let new_key = self.new_key();
self.cache.write(new_key, new_leaf);
node.next = Some(new_key);
result = Some(new_key);
}
self.cache.flag_write(node_key);
return result;
}
let (tgt_index, acc) = Self::select_child(&node.keys, index);
let new_index = index.saturating_sub(acc);
let child_idx = node.children[tgt_index];
let leaf = match self.insert_internal(new_index, element, child_idx) {
Some(leaf) => leaf,
None => {
node.keys[tgt_index] = node.keys[tgt_index].saturating_add(1);
self.cache.flag_write(node_key);
return None;
}
};
let level = node.level;
match level {
1 => {
node.keys[tgt_index] = ORDER;
let pos = tgt_index.saturating_add(1);
node.keys.insert(pos, ORDER);
node.children.insert(pos, leaf);
if node.keys.len() > ORDER {
node.keys.pop();
result = node.children.pop();
}
self.cache.flag_write(node_key);
}
_ => {
let start = tgt_index.saturating_add(1);
drop(node);
result = self.propagate(node_key, leaf, start);
}
}
result
}
fn remove_internal(&mut self, index: usize, node_key: u64) -> (bool, V) {
let node = self.cache.read(node_key);
let mut node = node.borrow_mut();
if node.is_leaf() {
let val = node.values.remove(index);
let empty = node.values.is_empty();
self.cache.flag_write(node_key);
return (empty, val);
}
let (tgt_index, acc) = Self::select_child(&node.keys, index);
let new_index = index.saturating_sub(acc);
let (empty, value) = self.remove_internal(new_index, node.children[tgt_index]);
if empty {
match node.level {
1 => {
node.keys.remove(tgt_index);
self.cache.remove(node.children.remove(tgt_index));
}
_ => {
drop(node);
self.compact(node_key, tgt_index, true);
return (empty, value);
}
}
} else {
node.keys[tgt_index] = node.keys[tgt_index].saturating_sub(1);
}
self.cache.flag_write(node_key);
(empty, value)
}
fn update_root(&mut self, child_key: u64) {
let former_root = self.cache.read(ROOT_KEY);
let node = former_root.borrow();
let key_old_root = self.new_key();
let new_root = Node {
keys: vec![node.rank(), self.get_node_rank(child_key)],
level: node.level().saturating_add(1),
children: vec![key_old_root, child_key],
values: vec![],
next: None,
};
drop(node);
self.cache.replace(ROOT_KEY, key_old_root, former_root);
self.cache.write(ROOT_KEY, new_root);
}
fn propagate(&mut self, node_key: u64, leaf_key: u64, start: usize) -> Option<u64> {
let node = self.cache.read(node_key);
let mut node = node.borrow_mut();
assert!(!node.is_leaf(), "Leaves are not supported");
let popped_leaf = match node.level {
1 => {
node.children.insert(0, leaf_key);
node.keys.insert(0, self.get_node_rank(leaf_key));
let last_key = node.children.last().cloned().unwrap();
let last_child = self.cache.read(last_key);
let last_child = last_child.borrow();
if last_child.next.is_none() && node.keys.len() <= ORDER {
None
} else {
node.keys.pop();
Some(node.children.pop().unwrap())
}
}
_ => {
let mut current = Some(leaf_key);
for i in start..node.children.len() {
current = self.propagate(node.children[i], current.unwrap(), 0);
if current.is_none() {
break;
}
}
if current.is_some() {
if node.keys.len() < ORDER {
let leaf_key = current.take().unwrap();
let subtree = self.create_subtree(node.level().saturating_sub(1), leaf_key);
node.keys.push(self.get_node_rank(subtree));
node.children.push(subtree);
}
}
for i in 0..node.keys.len() {
node.keys[i] = self.get_node_rank(node.children[i]);
}
current
}
};
self.cache.flag_write(node_key);
popped_leaf
}
fn compact(&mut self, node_key: u64, start: usize, origin: bool) -> Option<u64> {
let node = self.cache.read(node_key);
let mut node = node.borrow_mut();
assert!(!node.is_leaf(), "Leaves are not supported");
let popped_leaf = match node.level {
1 => {
node.keys.remove(0);
Some(node.children.remove(0))
}
_ => {
let start = start.saturating_add(1);
let end = node.children.len();
for i in start..end {
match self.compact(node.children[i], 0, false) {
Some(key) => self.append(node.children[i.saturating_sub(1)], key),
None => break,
}
}
if let Some(last_child) = node.children.last() {
if self.is_node_empty(*last_child) {
node.keys.pop();
node.children.pop();
}
}
match origin {
true => None,
false => self.compact(node.children[0], 0, false),
}
}
};
for i in 0..node.keys.len() {
node.keys[i] = self.get_node_rank(node.children[i]);
}
self.cache.flag_write(node_key);
popped_leaf
}
fn prune_root(&mut self) {
let root = self.cache.read(ROOT_KEY);
let mut root = root.borrow_mut();
if !root.is_leaf() {
if root.keys.last().unwrap() == &0 {
root.keys.pop();
root.children.pop();
self.cache.flag_write(ROOT_KEY);
}
if root.keys.len() == 1 {
let child_key = root.children[0];
let child = self.cache.read(child_key);
self.cache.replace(child_key, ROOT_KEY, child);
}
}
}
fn append(&mut self, node_key: u64, leaf_key: u64) {
let node = self.cache.read(node_key);
let mut node = node.borrow_mut();
assert!(!node.is_leaf(), "Leaves are not supported");
match node.level {
1 => {
node.children.push(leaf_key);
node.keys.push(self.get_node_rank(leaf_key));
}
_ => {
self.append(*node.children.last().unwrap(), leaf_key);
}
}
for i in 0..node.keys.len() {
node.keys[i] = self.get_node_rank(node.children[i]);
}
self.cache.flag_write(node_key);
}
fn create_subtree(&mut self, tgt_level: usize, node_key: u64) -> u64 {
let mut current_key = node_key;
for level in 1..=tgt_level {
let current_node = self.cache.read(current_key);
let current_node = current_node.borrow();
let new_int = Node {
keys: vec![current_node.rank()],
children: vec![current_key],
level,
values: vec![],
next: None,
};
let new_key = self.new_key();
self.cache.write(new_key, new_int);
current_key = new_key;
}
current_key
}
fn select_child(keys: &[usize], index: usize) -> (usize, usize) {
let len = keys.len();
let mut accumulative: usize = 0;
for (i, key) in keys.iter().enumerate().take(len) {
if index < accumulative.saturating_add(*key) {
return (i, accumulative);
}
accumulative = accumulative.saturating_add(*key);
}
unreachable!("Insert_internal() and remove_internal() always use a valid index")
}
fn new_key(&mut self) -> u64 {
self.cache.new_key()
}
fn reset_next(&mut self, start: u64) {
let mut node = self.cache.read(start);
let mut leaf_key = u64::MAX;
while !node.borrow().is_leaf() {
let last_child = *node.borrow().children.last().unwrap();
node = self.cache.read(last_child);
leaf_key = last_child;
}
node.borrow_mut().next = None;
self.cache.flag_write(leaf_key);
}
fn load(&mut self, key: u64) {
if self.cache.exists() {
let node = self.cache.read(key);
for child in node.borrow().children.iter() {
self.load(*child);
}
}
}
pub fn iter(&self) -> LazyVecIt<V> {
LazyVecIt::new(self)
}
}
#[cfg(not(target_arch = "wasm32"))]
#[cfg(test)]
mod tests {
use crate::__private::dev::rand;
use crate::collections::lazyvec::LazyVec;
use anyhow::Context;
const KEY: u64 = 123456;
const N: usize = 5000;
#[test]
fn is_empty() -> anyhow::Result<()> {
let vec: LazyVec<u64> = LazyVec::new(KEY);
assert!(vec.is_empty(), "LazyVec must be empty");
Ok(())
}
#[test]
fn clear() -> anyhow::Result<()> {
let mut vec: LazyVec<u64> = LazyVec::new(KEY);
for _ in 0..N {
let random = rand(0, u64::MAX);
vec.push(random);
}
vec.clear();
assert!(vec.is_empty(), "LazyVec clear() failed");
Ok(())
}
#[test]
fn contains() -> anyhow::Result<()> {
let mut vec: LazyVec<u64> = LazyVec::new(KEY);
for _ in 0..N {
vec.push(0);
}
let pos = 700;
let target: u64 = 1;
assert!(!vec.contains(target), "Vector must not contain target");
vec.insert(pos, target);
assert!(vec.contains(target), "Vector must contain target");
vec.remove(pos);
assert!(!vec.contains(target), "Vector must not contain target");
Ok(())
}
#[test]
fn push() -> anyhow::Result<()> {
let mut vec: LazyVec<u64> = LazyVec::new(KEY);
let mut oracle = Vec::with_capacity(N);
for _ in 0..N {
let random = rand(0, u64::MAX);
vec.push(random);
oracle.push(random);
}
assert_eq!(vec.len(), oracle.len(), "Length mismatch");
for i in 0..N {
let val = vec.get(i).context("Get({i}) must return some value")?;
assert_eq!(oracle.get(i), Some(&*val), "Element mismatch")
}
Ok(())
}
#[test]
fn pop() -> anyhow::Result<()> {
let mut vec: LazyVec<u64> = LazyVec::new(KEY);
let mut oracle = Vec::with_capacity(N);
for _ in 0..N {
let random = rand(0, u64::MAX);
vec.push(random);
oracle.push(random);
}
assert_eq!(vec.len(), oracle.len(), "Length mismatch");
for _ in 0..N {
assert_eq!(vec.pop(), oracle.pop(), "Element mismatch")
}
assert!(vec.is_empty(), "Vector must be empty");
assert!(vec.pop().is_none(), "None must be returned");
Ok(())
}
#[test]
pub(crate) fn insert() -> anyhow::Result<()> {
let mut vec: LazyVec<u64> = LazyVec::new(KEY);
let mut oracle = Vec::with_capacity(N);
for _ in 0..N {
let random = rand(0, u64::MAX);
vec.push(random);
oracle.push(random);
}
assert_eq!(vec.len(), oracle.len(), "Length mismatch");
for _ in 0..N {
let pos = rand(0, vec.len() as u64) as usize;
let random = rand(0, u64::MAX);
vec.insert(pos, random);
oracle.insert(pos, random)
}
assert_eq!(vec.len(), oracle.len(), "Length mismatch 2");
let end = vec.len();
for i in 0..end {
let val = vec.get(i).context("Get({i}) must return some value")?;
assert_eq!(oracle.get(i), Some(&*val), "Element mismatch")
}
Ok(())
}
#[test]
fn remove() -> anyhow::Result<()> {
let mut vec: LazyVec<u64> = LazyVec::new(KEY);
let mut oracle = Vec::with_capacity(N);
for _ in 0..N {
let random = rand(0, u64::MAX);
vec.push(random);
oracle.push(random);
}
assert_eq!(vec.len(), oracle.len(), "Length mismatch");
for _ in 0..N {
let pos: usize = rand(0, vec.len() as u64) as usize;
assert_eq!(vec.remove(pos), oracle.remove(pos), "Element mismatch");
}
assert!(vec.is_empty(), "Vector must be empty");
Ok(())
}
}