use std::sync::{ atomic::{AtomicUsize, Ordering}, Arc, }; use sled::{CompareAndSwapError, IVec, Iter, Result, Tree}; #[derive(Clone)] pub struct SledCountedTree(Arc); struct SledCountedTreeInternal { tree: Tree, len: AtomicUsize, } impl SledCountedTree { pub fn new(tree: Tree) -> Self { let len = tree.len(); Self(Arc::new(SledCountedTreeInternal { tree, len: AtomicUsize::new(len), })) } pub fn len(&self) -> usize { self.0.len.load(Ordering::Relaxed) } pub fn is_empty(&self) -> bool { self.0.tree.is_empty() } pub fn get>(&self, key: K) -> Result> { self.0.tree.get(key) } pub fn iter(&self) -> Iter { self.0.tree.iter() } // ---- writing functions ---- pub fn insert(&self, key: K, value: V) -> Result> where K: AsRef<[u8]>, V: Into, { let res = self.0.tree.insert(key, value); if res == Ok(None) { self.0.len.fetch_add(1, Ordering::Relaxed); } res } pub fn remove>(&self, key: K) -> Result> { let res = self.0.tree.remove(key); if matches!(res, Ok(Some(_))) { self.0.len.fetch_sub(1, Ordering::Relaxed); } res } pub fn pop_min(&self) -> Result> { let res = self.0.tree.pop_min(); if let Ok(Some(_)) = &res { self.0.len.fetch_sub(1, Ordering::Relaxed); }; res } pub fn compare_and_swap( &self, key: K, old: Option, new: Option, ) -> Result> where K: AsRef<[u8]>, OV: AsRef<[u8]>, NV: Into, { let old_some = old.is_some(); let new_some = new.is_some(); let res = self.0.tree.compare_and_swap(key, old, new); if res == Ok(Ok(())) { match (old_some, new_some) { (false, true) => { self.0.len.fetch_add(1, Ordering::Relaxed); } (true, false) => { self.0.len.fetch_sub(1, Ordering::Relaxed); } _ => (), } } res } }