From c97929400101c6af26536f0f1937388b3dda807d Mon Sep 17 00:00:00 2001 From: al8n Date: Sun, 8 Dec 2024 16:52:15 +0800 Subject: [PATCH] Add missing methods for `unique::SkipMap`s --- Cargo.toml | 2 +- src/dynamic/list.rs | 31 ++-- src/dynamic/list/api.rs | 14 +- src/dynamic/list/api/update.rs | 2 +- src/dynamic/list/entry.rs | 8 +- src/dynamic/list/iterator.rs | 26 ++-- src/dynamic/multiple_version.rs | 26 ++-- src/dynamic/unique.rs | 185 ++++++++++++++++++++--- src/generic/list.rs | 42 +++--- src/generic/list/api.rs | 32 ++-- src/generic/list/api/update.rs | 22 +-- src/generic/list/entry.rs | 24 +-- src/generic/list/iterator.rs | 60 ++++---- src/generic/multiple_version.rs | 82 +++++------ src/generic/unique.rs | 253 ++++++++++++++++++++++++++------ 15 files changed, 551 insertions(+), 258 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9cf231d..884a0e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "skl" -version = "0.22.8" +version = "0.22.9" edition = "2021" rust-version = "1.81.0" repository = "https://github.com/al8n/skl" diff --git a/src/dynamic/list.rs b/src/dynamic/list.rs index ca6c363..50caa39 100644 --- a/src/dynamic/list.rs +++ b/src/dynamic/list.rs @@ -1,10 +1,7 @@ use core::{cmp, ptr::NonNull, sync::atomic::Ordering}; use among::Among; -use dbutils::{ - buffer::VacantBuffer, - equivalentor::{Ascend, BytesComparator}, -}; +use dbutils::{buffer::VacantBuffer, equivalentor::BytesComparator}; use either::Either; use rarena_allocator::Allocator as _; @@ -27,7 +24,7 @@ pub use entry::EntryRef; mod api; pub(super) mod iterator; -type UpdateOk<'a, 'b, A, RC, C> = Either< +type UpdateOk<'a, 'b, C, A, RC> = Either< Option>, Result, EntryRef<'a, MaybeTombstone, C, A, RC>>, >; @@ -35,7 +32,7 @@ type UpdateOk<'a, 'b, A, RC, C> = Either< /// A fast, cocnurrent map implementation based on skiplist that supports forward /// and backward iteration. #[derive(Debug)] -pub struct SkipList +pub struct SkipList where A: Allocator, R: RefCounter, @@ -55,7 +52,7 @@ where cmp: C, } -unsafe impl Send for SkipList +unsafe impl Send for SkipList where C: Send, A: Allocator + Send, @@ -63,7 +60,7 @@ where { } -unsafe impl Sync for SkipList +unsafe impl Sync for SkipList where C: Sync, A: Allocator + Sync, @@ -71,7 +68,7 @@ where { } -impl Clone for SkipList +impl Clone for SkipList where C: Clone, A: Allocator, @@ -93,7 +90,7 @@ where } } -impl SkipList +impl SkipList where A: Allocator, R: RefCounter, @@ -104,7 +101,7 @@ where } } -impl Constructable for SkipList +impl Constructable for SkipList where A: Allocator, R: RefCounter, @@ -171,7 +168,7 @@ where } } -impl SkipList +impl SkipList where A: Allocator, R: RefCounter, @@ -256,7 +253,7 @@ where } } -impl SkipList +impl SkipList where A: Allocator, R: RefCounter, @@ -308,7 +305,7 @@ where } } -impl SkipList +impl SkipList where A: Allocator, C: BytesComparator, @@ -855,7 +852,7 @@ where failure: Ordering, mut ins: Inserter<'a, ::Pointer>, upsert: bool, - ) -> Result, Either> { + ) -> Result, Either> { let is_remove = key.is_remove(); // Safety: a fresh new Inserter, so safe here @@ -1128,7 +1125,7 @@ where value_size: u32, success: Ordering, failure: Ordering, - ) -> Result, Error> { + ) -> Result, Error> { match key { Key::Occupied(_) | Key::Vacant { .. } | Key::Pointer { .. } => { old_node.update_value(&self.arena, value_offset, value_size); @@ -1168,7 +1165,7 @@ where value_builder: Option) -> Result>>, success: Ordering, failure: Ordering, - ) -> Result, Either> { + ) -> Result, Either> { match key { Key::Occupied(_) | Key::Vacant { .. } | Key::Pointer { .. } => self .arena diff --git a/src/dynamic/list/api.rs b/src/dynamic/list/api.rs index a816c17..f43c258 100644 --- a/src/dynamic/list/api.rs +++ b/src/dynamic/list/api.rs @@ -22,7 +22,7 @@ mod update; type RemoveValueBuilder = ValueBuilder) -> Result>>; -impl SkipList +impl SkipList where A: Allocator, R: RefCounter, @@ -152,7 +152,7 @@ where } } -impl SkipList +impl SkipList where A: Allocator, RC: RefCounter, @@ -293,14 +293,14 @@ where } } -impl SkipList +impl SkipList where A: Allocator, RC: RefCounter, { /// Returns a new iterator, this iterator will yield the latest version of all entries in the map less or equal to the given version. #[inline] - pub fn iter(&self, version: Version) -> iterator::Iter<'_, Active, A, RC, C> { + pub fn iter(&self, version: Version) -> iterator::Iter<'_, Active, C, A, RC> { iterator::Iter::new(version, self, false) } @@ -309,7 +309,7 @@ where pub fn iter_with_tombstone( &self, version: Version, - ) -> iterator::Iter<'_, MaybeTombstone, A, RC, C> { + ) -> iterator::Iter<'_, MaybeTombstone, C, A, RC> { iterator::Iter::new(version, self, true) } @@ -319,7 +319,7 @@ where &self, version: Version, range: R, - ) -> iterator::Iter<'_, Active, A, RC, C, Q, R> + ) -> iterator::Iter<'_, Active, C, A, RC, Q, R> where Q: ?Sized + Borrow<[u8]>, R: RangeBounds, @@ -333,7 +333,7 @@ where &self, version: Version, range: R, - ) -> iterator::Iter<'_, MaybeTombstone, A, RC, C, Q, R> + ) -> iterator::Iter<'_, MaybeTombstone, C, A, RC, Q, R> where Q: ?Sized + Borrow<[u8]>, R: RangeBounds, diff --git a/src/dynamic/list/api/update.rs b/src/dynamic/list/api/update.rs index 2c2cc34..63b865c 100644 --- a/src/dynamic/list/api/update.rs +++ b/src/dynamic/list/api/update.rs @@ -8,7 +8,7 @@ use core::sync::atomic::Ordering; use dbutils::{buffer::VacantBuffer, equivalentor::BytesComparator}; use either::Either; -impl SkipList +impl SkipList where A: Allocator, C: BytesComparator, diff --git a/src/dynamic/list/entry.rs b/src/dynamic/list/entry.rs index de3a1e1..252ac24 100644 --- a/src/dynamic/list/entry.rs +++ b/src/dynamic/list/entry.rs @@ -13,7 +13,7 @@ where R: RefCounter, S: State<'a>, { - pub(super) list: &'a SkipList, + pub(super) list: &'a SkipList, pub(super) key: &'a [u8], pub(super) value: S::BytesValue, pub(super) version: Version, @@ -57,7 +57,7 @@ where { } -impl<'a, A, R, C> EntryRef<'a, MaybeTombstone, C, A, R> +impl<'a, C, A, R> EntryRef<'a, MaybeTombstone, C, A, R> where A: Allocator, R: RefCounter, @@ -188,7 +188,7 @@ where pub(crate) fn from_node( query_version: Version, node: ::Pointer, - list: &'a SkipList, + list: &'a SkipList, key: Option<&'a [u8]>, value: S::BytesValue, ) -> Self { @@ -213,7 +213,7 @@ where pub(crate) fn from_node_with_pointer( query_version: Version, node: ::Pointer, - list: &'a SkipList, + list: &'a SkipList, key: Option<&'a [u8]>, value: S::BytesValue, ) -> Self { diff --git a/src/dynamic/list/iterator.rs b/src/dynamic/list/iterator.rs index 539e7d8..1f4051c 100644 --- a/src/dynamic/list/iterator.rs +++ b/src/dynamic/list/iterator.rs @@ -8,14 +8,14 @@ use dbutils::equivalentor::{BytesComparator, BytesRangeComparator}; /// An iterator over the skipmap (this iterator will yields all versions). The current state of the iterator can be cloned by /// simply value copying the struct. -pub struct Iter<'a, S, A, RC, C, Q = [u8], R = core::ops::RangeFull> +pub struct Iter<'a, S, C, A, RC, Q = [u8], R = core::ops::RangeFull> where A: Allocator, RC: RefCounter, Q: ?Sized, S: State<'a>, { - pub(super) map: &'a SkipList, + pub(super) map: &'a SkipList, pub(super) version: Version, pub(super) range: Option, pub(super) all_versions: bool, @@ -24,7 +24,7 @@ where pub(super) _phantom: core::marker::PhantomData, } -impl<'a, S, A, RC, C, Q, R> Clone for Iter<'a, S, A, RC, C, Q, R> +impl<'a, S, C, A, RC, Q, R> Clone for Iter<'a, S, C, A, RC, Q, R> where A: Allocator, RC: RefCounter, @@ -45,7 +45,7 @@ where } } -impl<'a, S, A, RC, C, Q, R> Copy for Iter<'a, S, A, RC, C, Q, R> +impl<'a, S, C, A, RC, Q, R> Copy for Iter<'a, S, C, A, RC, Q, R> where A: Allocator, RC: RefCounter, @@ -55,7 +55,7 @@ where { } -impl<'a, S, A, RC, C> Iter<'a, S, A, RC, C> +impl<'a, S, C, A, RC> Iter<'a, S, C, A, RC> where A: Allocator, RC: RefCounter, @@ -64,7 +64,7 @@ where #[inline] pub(crate) const fn new( version: Version, - map: &'a SkipList, + map: &'a SkipList, all_versions: bool, ) -> Self { Self { @@ -79,7 +79,7 @@ where } } -impl<'a, S, A, RC, C, Q, R> Iter<'a, S, A, RC, C, Q, R> +impl<'a, S, C, A, RC, Q, R> Iter<'a, S, C, A, RC, Q, R> where A: Allocator, RC: RefCounter, @@ -89,7 +89,7 @@ where #[inline] pub(crate) fn range( version: Version, - map: &'a SkipList, + map: &'a SkipList, r: R, all_versions: bool, ) -> Self { @@ -105,7 +105,7 @@ where } } -impl<'a, S, A, RC, C, Q, R> Iter<'a, S, A, RC, C, Q, R> +impl<'a, S, C, A, RC, Q, R> Iter<'a, S, C, A, RC, Q, R> where A: Allocator, RC: RefCounter, @@ -146,7 +146,7 @@ where } } -impl<'a, S, A, RC, C, Q, R> Iter<'a, S, A, RC, C, Q, R> +impl<'a, S, C, A, RC, Q, R> Iter<'a, S, C, A, RC, Q, R> where A: Allocator, C: BytesComparator, @@ -374,7 +374,7 @@ where } } -impl<'a, S, A, RC, C, Q, R> Iter<'a, S, A, RC, C, Q, R> +impl<'a, S, C, A, RC, Q, R> Iter<'a, S, C, A, RC, Q, R> where A: Allocator, C: BytesComparator, @@ -593,7 +593,7 @@ where } } -impl<'a, S, A, RC, C, Q, R> Iterator for Iter<'a, S, A, RC, C, Q, R> +impl<'a, S, C, A, RC, Q, R> Iterator for Iter<'a, S, C, A, RC, Q, R> where A: Allocator, C: BytesComparator, @@ -640,7 +640,7 @@ where } } -impl<'a, S, A, RC, C, Q, R> DoubleEndedIterator for Iter<'a, S, A, RC, C, Q, R> +impl<'a, S, C, A, RC, Q, R> DoubleEndedIterator for Iter<'a, S, C, A, RC, Q, R> where A: Allocator, C: BytesComparator, diff --git a/src/dynamic/multiple_version.rs b/src/dynamic/multiple_version.rs index 9535fde..eb3b377 100644 --- a/src/dynamic/multiple_version.rs +++ b/src/dynamic/multiple_version.rs @@ -33,16 +33,16 @@ pub mod unsync { crate::__dynamic_multiple_version_map_tests!("dynamic_unsync_multiple_version_map": super::SkipMap); } - type SkipList = super::super::list::SkipList; + type SkipList = super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, V, C> = super::super::iter::Iter<'a, V, Allocator, RefCounter, C>; + pub type Iter<'a, S, C> = super::super::iter::Iter<'a, S, C, Allocator, RefCounter>; /// The entry reference of the [`SkipMap`]. - pub type Entry<'a, V, C> = super::super::entry::EntryRef<'a, V, C, Allocator, RefCounter>; + pub type Entry<'a, S, C> = super::super::entry::EntryRef<'a, S, C, Allocator, RefCounter>; /// Iterator over a subset of the [`SkipMap`]. - pub type Range<'a, V, C, Q, R> = super::super::iter::Iter<'a, V, Allocator, RefCounter, C, Q, R>; + pub type Range<'a, S, C, Q, R> = super::super::iter::Iter<'a, S, C, Allocator, RefCounter, Q, R>; /// A fast, ARENA based `SkipMap` that supports multiple versions, forward and backward iteration. /// @@ -130,16 +130,16 @@ pub mod sync { crate::__dynamic_multiple_version_map_tests!(go "dynamic_sync_multiple_version_map": super::SkipMap => crate::tests::dynamic::TEST_OPTIONS_WITH_PESSIMISTIC_FREELIST); } - type SkipList = super::super::list::SkipList; + type SkipList = super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, V, C> = super::super::iter::Iter<'a, V, Allocator, RefCounter, C>; + pub type Iter<'a, S, C> = super::super::iter::Iter<'a, S, C, Allocator, RefCounter>; /// Iterator over a subset of the [`SkipMap`]. - pub type Range<'a, V, C, Q, R> = super::super::iter::Iter<'a, V, Allocator, RefCounter, C, Q, R>; + pub type Range<'a, S, C, Q, R> = super::super::iter::Iter<'a, S, C, Allocator, RefCounter, Q, R>; /// The entry reference of the [`SkipMap`]. - pub type Entry<'a, V, C> = super::super::entry::EntryRef<'a, V, C, Allocator, RefCounter>; + pub type Entry<'a, S, C> = super::super::entry::EntryRef<'a, S, C, Allocator, RefCounter>; /// A fast, lock-free, thread-safe ARENA based `SkipMap` that supports multiple versions, forward and backward iteration. /// @@ -195,7 +195,7 @@ pub mod sync { /// - For non-concurrent environment, use [`unsync::SkipMap`]. pub trait Map where - Self: Arena>, + Self: Arena>, C: 'static, ::Node: WithVersion, { @@ -605,7 +605,7 @@ where /// Returns a new iterator, this iterator will yield the latest version of all entries in the map less or equal to the given version. #[inline] - fn iter(&self, version: Version) -> Iter<'_, Active, Self::Allocator, Self::RefCounter, C> { + fn iter(&self, version: Version) -> Iter<'_, Active, C, Self::Allocator, Self::RefCounter> { self.as_ref().iter(version) } @@ -614,7 +614,7 @@ where fn iter_with_tombstone( &self, version: Version, - ) -> Iter<'_, MaybeTombstone, Self::Allocator, Self::RefCounter, C> { + ) -> Iter<'_, MaybeTombstone, C, Self::Allocator, Self::RefCounter> { self.as_ref().iter_with_tombstone(version) } @@ -624,7 +624,7 @@ where &self, version: Version, range: R, - ) -> Iter<'_, Active, Self::Allocator, Self::RefCounter, C, Q, R> + ) -> Iter<'_, Active, C, Self::Allocator, Self::RefCounter, Q, R> where Q: ?Sized + Borrow<[u8]>, R: RangeBounds, @@ -638,7 +638,7 @@ where &self, version: Version, range: R, - ) -> Iter<'_, MaybeTombstone, Self::Allocator, Self::RefCounter, C, Q, R> + ) -> Iter<'_, MaybeTombstone, C, Self::Allocator, Self::RefCounter, Q, R> where Q: ?Sized + Borrow<[u8]>, R: RangeBounds, diff --git a/src/dynamic/unique.rs b/src/dynamic/unique.rs index df2a0a8..c8d825d 100644 --- a/src/dynamic/unique.rs +++ b/src/dynamic/unique.rs @@ -12,7 +12,7 @@ use crate::{ allocator::{Allocator, Sealed, WithoutVersion}, error::Error, ref_counter::RefCounter, - Active, Arena, Header, Height, KeyBuilder, ValueBuilder, MIN_VERSION, + Active, Arena, Header, Height, KeyBuilder, MaybeTombstone, ValueBuilder, MIN_VERSION, }; use super::{ @@ -25,24 +25,22 @@ pub mod unsync { use dbutils::equivalentor::Ascend; pub use crate::unsync::{map::Allocator, RefCounter}; - use crate::Active; #[cfg(any(all(test, not(miri)), all_skl_tests, test_dynamic_unsync_map,))] mod tests { crate::__dynamic_map_tests!("dynamic_unsync_map": super::SkipMap); } - type SkipList = super::super::list::SkipList; + type SkipList = super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, C> = super::super::iter::Iter<'a, Active, Allocator, RefCounter, C>; - - /// Iterator over a subset of the [`SkipMap`]. - pub type Range<'a, C, Q, R> = - super::super::iter::Iter<'a, Active, Allocator, RefCounter, C, Q, R>; + pub type Iter<'a, S, C> = super::super::iter::Iter<'a, S, C, Allocator, RefCounter>; /// The entry reference of the [`SkipMap`]. - pub type Entry<'a, C> = super::super::entry::EntryRef<'a, Active, C, Allocator, RefCounter>; + pub type Entry<'a, S, C> = super::super::entry::EntryRef<'a, S, C, Allocator, RefCounter>; + + /// Iterator over a subset of the [`SkipMap`]. + pub type Range<'a, S, C, Q, R> = super::super::iter::Iter<'a, S, C, Allocator, RefCounter, Q, R>; /// A fast, ARENA based `SkipMap` that supports forward and backward iteration. /// @@ -97,7 +95,6 @@ pub mod sync { use dbutils::equivalentor::Ascend; pub use crate::sync::{map::Allocator, RefCounter}; - use crate::Active; #[cfg(any(all(test, not(miri)), all_skl_tests, test_dynamic_sync_map,))] mod tests { @@ -127,17 +124,16 @@ pub mod sync { crate::__dynamic_map_tests!(go "sync_map": super::SkipMap => crate::tests::dynamic::TEST_OPTIONS_WITH_PESSIMISTIC_FREELIST); } - type SkipList = super::super::list::SkipList; + type SkipList = super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, C> = super::super::iter::Iter<'a, Active, Allocator, RefCounter, C>; - - /// Iterator over a subset of the [`SkipMap`]. - pub type Range<'a, C, Q, R> = - super::super::iter::Iter<'a, Active, Allocator, RefCounter, C, Q, R>; + pub type Iter<'a, S, C> = super::super::iter::Iter<'a, S, C, Allocator, RefCounter>; /// The entry reference of the [`SkipMap`]. - pub type Entry<'a, C> = super::super::entry::EntryRef<'a, Active, C, Allocator, RefCounter>; + pub type Entry<'a, S, C> = super::super::entry::EntryRef<'a, S, C, Allocator, RefCounter>; + + /// Iterator over a subset of the [`SkipMap`]. + pub type Range<'a, S, C, Q, R> = super::super::iter::Iter<'a, S, C, Allocator, RefCounter, Q, R>; /// A fast, lock-free, thread-safe ARENA based `SkipMap` that supports forward and backward iteration. /// @@ -193,7 +189,7 @@ pub mod sync { /// - For non-concurrent environment, use [`unsync::SkipMap`]. pub trait Map where - Self: Arena>, + Self: Arena>, ::Node: WithoutVersion, C: 'static, { @@ -249,13 +245,15 @@ where self.as_ref().height() } - /// Returns the number of entries in the skipmap. + /// Returns the number of entries in the map, this `len` includes all tombstones. + /// + /// If the map only contains tombstones, this method will not return `0` but the number of tombstones. #[inline] fn len(&self) -> usize { self.as_ref().len() } - /// Returns true if the skipmap is empty. + /// Returns `true` if the map is empty, if the map only contains tombstones, this method will also return `false`. #[inline] fn is_empty(&self) -> bool { self.len() == 0 @@ -304,6 +302,33 @@ where self.as_ref().contains_key(MIN_VERSION, key.borrow()) } + /// Returns `true` if the key exists in the map, even if it is marked as removed. + /// + /// ## Example + /// + /// ```rust + /// use skl::dynamic::{unique::{sync::SkipMap, Map}, Builder}; + /// + /// let map = Builder::new().with_capacity(1024).alloc::().unwrap(); + /// + /// map.insert(b"hello", b"world").unwrap(); + /// + /// map.remove(b"hello").unwrap(); + /// + /// assert!(!map.contains_key(b"hello")); + /// assert!(map.contains_key_with_tombstone(b"hello")); + /// ``` + #[inline] + fn contains_key_with_tombstone(&self, key: &Q) -> bool + where + Q: ?Sized + Borrow<[u8]>, + C: BytesComparator, + { + self + .as_ref() + .contains_key_with_tombstone(MIN_VERSION, key.borrow()) + } + /// Returns the first entry in the map. #[inline] fn first(&self) -> Option> @@ -322,6 +347,34 @@ where self.as_ref().last(MIN_VERSION) } + /// Returns the first entry in the map. The returned entry may not be in valid state. (i.e. the entry is removed) + /// + /// The difference between [`first`](Map::first) and `first_with_tombstone` is that `first_with_tombstone` will return the value even if + /// the entry is removed or not in a valid state. + #[inline] + fn first_with_tombstone( + &self, + ) -> Option> + where + C: BytesComparator, + { + self.as_ref().first_with_tombstone(0) + } + + /// Returns the last entry in the map. The returned entry may not be in valid state. (i.e. the entry is removed) + /// + /// The difference between [`last`](Map::last) and `last_with_tombstone` is that `last_with_tombstone` will return the value even if + /// the entry is removed or not in a valid state. + #[inline] + fn last_with_tombstone( + &self, + ) -> Option> + where + C: BytesComparator, + { + self.as_ref().last_with_tombstone(0) + } + /// Returns the value associated with the given key, if it exists. /// /// ## Example @@ -349,6 +402,39 @@ where self.as_ref().get(MIN_VERSION, key.borrow()) } + /// Returns the value associated with the given key, if it exists. + /// + /// The difference between `get` and `get_with_tombstone` is that `get_with_tombstone` will return the value even if the entry is removed. + /// + /// ## Example + /// + /// ```rust + /// use skl::dynamic::{unique::{sync::SkipMap, Map}, Builder}; + /// + /// let map = Builder::new().with_capacity(1024).alloc::().unwrap(); + /// + /// map.insert(b"hello", b"world").unwrap(); + /// + /// map.remove(b"hello").unwrap(); + /// + /// assert!(map.get(b"hello").is_none()); + /// + /// let ent = map.get_with_tombstone(b"hello").unwrap(); + /// // value is None because the entry is marked as removed. + /// assert!(ent.value().is_none()); + /// ``` + #[inline] + fn get_with_tombstone( + &self, + key: &Q, + ) -> Option> + where + Q: ?Sized + Borrow<[u8]>, + C: BytesComparator, + { + self.as_ref().get_with_tombstone(MIN_VERSION, key.borrow()) + } + /// Returns an `EntryRef` pointing to the highest element whose key is below the given bound. /// If no such element is found then `None` is returned. #[inline] @@ -377,15 +463,53 @@ where self.as_ref().iter(MIN_VERSION).seek_lower_bound(lower) } - /// Returns a new iterator, this iterator will yield the latest version of all entries in the map less or equal to the given version. + /// Returns an `EntryRef` pointing to the highest element whose key is below the given bound. + /// If no such element is found then `None` is returned. + /// + /// The difference between [`upper_bound`](Map::upper_bound) and `upper_bound_with_tombstone` is that `upper_bound_with_tombstone` will return the value even if the entry is removed. + #[inline] + fn upper_bound_with_tombstone( + &self, + upper: Bound<&Q>, + ) -> Option> + where + Q: ?Sized + Borrow<[u8]>, + C: BytesComparator, + { + self.as_ref().iter_with_tombstone(0).seek_upper_bound(upper) + } + + /// Returns an `EntryRef` pointing to the lowest element whose key is above the given bound. + /// If no such element is found then `None` is returned. + /// + /// The difference between [`lower_bound`](Map::lower_bound) and `lower_bound_with_tombstone` is that `lower_bound_with_tombstone` will return the value even if the entry is removed. #[inline] - fn iter(&self) -> Iter<'_, Active, Self::Allocator, Self::RefCounter, C> { + fn lower_bound_with_tombstone( + &self, + lower: Bound<&Q>, + ) -> Option> + where + Q: ?Sized + Borrow<[u8]>, + C: BytesComparator, + { + self.as_ref().iter_with_tombstone(0).seek_lower_bound(lower) + } + + /// Returns a new iterator, this iterator will yield only active entries of all entries in the map less or equal to the given version. + #[inline] + fn iter(&self) -> Iter<'_, Active, C, Self::Allocator, Self::RefCounter> { self.as_ref().iter(MIN_VERSION) } - /// Returns a iterator that within the range, this iterator will yield the latest version of all entries in the range less or equal to the given version. + /// Returns a new iterator, this iterator will yield with tombstones for all entries in the map less or equal to the given version. #[inline] - fn range(&self, range: R) -> Iter<'_, Active, Self::Allocator, Self::RefCounter, C, Q, R> + fn iter_with_tombstone(&self) -> Iter<'_, MaybeTombstone, C, Self::Allocator, Self::RefCounter> { + self.as_ref().iter_with_tombstone(0) + } + + /// Returns a iterator that within the range, this iterator will yield only active entries of all entries in the range less or equal to the given version. + #[inline] + fn range(&self, range: R) -> Iter<'_, Active, C, Self::Allocator, Self::RefCounter, Q, R> where Q: ?Sized + Borrow<[u8]>, R: RangeBounds, @@ -393,6 +517,19 @@ where self.as_ref().range(MIN_VERSION, range) } + /// Returns a iterator that within the range, this iterator will yield with tombstones for all entries in the range less or equal to the given version. + #[inline] + fn range_with_tombstone( + &self, + range: R, + ) -> Iter<'_, MaybeTombstone, C, Self::Allocator, Self::RefCounter, Q, R> + where + Q: ?Sized + Borrow<[u8]>, + R: RangeBounds, + { + self.as_ref().range_with_tombstone(MIN_VERSION, range) + } + /// Upserts a new key-value pair if it does not yet exist, if the key with the given version already exists, it will update the value. /// Unlike [`get_or_insert`](Map::get_or_insert), this method will update the value if the key with the given version already exists. /// diff --git a/src/generic/list.rs b/src/generic/list.rs index b7674f1..897431e 100644 --- a/src/generic/list.rs +++ b/src/generic/list.rs @@ -30,15 +30,15 @@ pub use entry::EntryRef; mod api; pub(super) mod iterator; -type UpdateOk<'a, 'b, K, V, A, R, C> = Either< - Option>, - Result, EntryRef<'a, K, V, MaybeTombstone, A, R, C>>, +type UpdateOk<'a, 'b, K, V, C, A, R> = Either< + Option>, + Result, EntryRef<'a, K, V, MaybeTombstone, C, A, R>>, >; /// A fast, cocnurrent map implementation based on skiplist that supports forward /// and backward iteration. #[derive(Debug)] -pub struct SkipList { +pub struct SkipList { pub(crate) arena: A, meta: RefMeta, head: ::Pointer, @@ -56,7 +56,7 @@ pub struct SkipList { _m: PhantomData<(fn() -> K, fn() -> V)>, } -unsafe impl Send for SkipList +unsafe impl Send for SkipList where K: ?Sized, V: ?Sized, @@ -66,7 +66,7 @@ where { } -unsafe impl Sync for SkipList +unsafe impl Sync for SkipList where K: ?Sized, V: ?Sized, @@ -76,7 +76,7 @@ where { } -impl Clone for SkipList +impl Clone for SkipList where K: ?Sized, V: ?Sized, @@ -102,7 +102,7 @@ where } } -impl SkipList +impl SkipList where K: ?Sized, V: ?Sized, @@ -120,7 +120,7 @@ where } } -impl Constructable for SkipList +impl Constructable for SkipList where K: ?Sized, V: ?Sized, @@ -190,7 +190,7 @@ where } } -impl SkipList +impl SkipList where K: ?Sized + Type, V: ?Sized + Type, @@ -289,7 +289,7 @@ where } } -impl SkipList +impl SkipList where K: ?Sized + Type, V: ?Sized + Type, @@ -343,7 +343,7 @@ where } } -impl SkipList +impl SkipList where K: ?Sized + Type, V: ?Sized + Type, @@ -355,7 +355,7 @@ where nd: &mut ::Pointer, version: Version, contains_key: impl Fn(&K::Ref<'a>) -> bool, - ) -> Option> + ) -> Option> where S: State<'a>, { @@ -389,7 +389,7 @@ where nd: &mut ::Pointer, version: Version, contains_key: impl Fn(&K::Ref<'a>) -> bool, - ) -> Option> + ) -> Option> where S: State<'a>, { @@ -461,7 +461,7 @@ where nd: &mut ::Pointer, version: Version, contains_key: impl Fn(&K::Ref<'a>) -> bool, - ) -> Option> + ) -> Option> where S: State<'a>, { @@ -495,7 +495,7 @@ where nd: &mut ::Pointer, version: Version, contains_key: impl Fn(&K::Ref<'a>) -> bool, - ) -> Option> + ) -> Option> where S: State<'a>, { @@ -907,7 +907,7 @@ where failure: Ordering, mut ins: Inserter<'a, ::Pointer>, upsert: bool, - ) -> Result, Among> + ) -> Result, Among> where C: TypeRefComparator<'a, K>, { @@ -1176,14 +1176,14 @@ where unsafe fn upsert_value<'a, 'b: 'a>( &'a self, version: Version, - old: EntryRef<'a, K, V, MaybeTombstone, A, R, C>, + old: EntryRef<'a, K, V, MaybeTombstone, C, A, R>, old_node: ::Pointer, key: &Key<'a, 'b, K, A>, value_offset: u32, value_size: u32, success: Ordering, failure: Ordering, - ) -> Result, Error> { + ) -> Result, Error> { match key { Key::Structured(_) | Key::Occupied(_) | Key::Vacant { .. } | Key::Pointer { .. } => { old_node.update_value(&self.arena, value_offset, value_size); @@ -1215,13 +1215,13 @@ where unsafe fn upsert<'a, 'b: 'a, E>( &'a self, version: Version, - old: EntryRef<'a, K, V, MaybeTombstone, A, R, C>, + old: EntryRef<'a, K, V, MaybeTombstone, C, A, R>, old_node: ::Pointer, key: &Key<'a, 'b, K, A>, value_builder: Option) -> Result>>, success: Ordering, failure: Ordering, - ) -> Result, Either> { + ) -> Result, Either> { match key { Key::Structured(_) | Key::Occupied(_) | Key::Vacant { .. } | Key::Pointer { .. } => self .arena diff --git a/src/generic/list/api.rs b/src/generic/list/api.rs index 4cf3c13..ed6e45e 100644 --- a/src/generic/list/api.rs +++ b/src/generic/list/api.rs @@ -22,7 +22,7 @@ mod update; type RemoveValueBuilder = ValueBuilder) -> Result>>; -impl SkipList +impl SkipList where K: ?Sized, V: ?Sized, @@ -154,7 +154,7 @@ where } } -impl SkipList +impl SkipList where K: ?Sized + Type, V: ?Sized + Type, @@ -185,7 +185,7 @@ where } /// Returns the first entry in the map. - pub fn first<'a>(&'a self, version: Version) -> Option> + pub fn first<'a>(&'a self, version: Version) -> Option> where C: TypeRefQueryComparator<'a, K, K::Ref<'a>>, { @@ -193,7 +193,7 @@ where } /// Returns the last entry in the map. - pub fn last<'a>(&'a self, version: Version) -> Option> + pub fn last<'a>(&'a self, version: Version) -> Option> where C: TypeRefQueryComparator<'a, K, K::Ref<'a>>, { @@ -204,7 +204,7 @@ where pub fn first_with_tombstone<'a>( &'a self, version: Version, - ) -> Option> + ) -> Option> where C: TypeRefQueryComparator<'a, K, K::Ref<'a>>, { @@ -215,7 +215,7 @@ where pub fn last_with_tombstone<'a>( &'a self, version: Version, - ) -> Option> + ) -> Option> where C: TypeRefQueryComparator<'a, K, K::Ref<'a>>, { @@ -230,7 +230,7 @@ where &'a self, version: Version, key: &Q, - ) -> Option> + ) -> Option> where Q: ?Sized, C: TypeRefQueryComparator<'a, K, Q>, @@ -276,7 +276,7 @@ where &'a self, version: Version, key: &Q, - ) -> Option> + ) -> Option> where Q: ?Sized, C: TypeRefQueryComparator<'a, K, Q>, @@ -324,7 +324,7 @@ where &'a self, version: Version, upper: Bound<&Q>, - ) -> Option> + ) -> Option> where Q: ?Sized, C: TypeRefQueryComparator<'a, K, Q>, @@ -338,7 +338,7 @@ where &'a self, version: Version, lower: Bound<&Q>, - ) -> Option> + ) -> Option> where Q: ?Sized, C: TypeRefQueryComparator<'a, K, Q>, @@ -352,7 +352,7 @@ where &'a self, version: Version, upper: Bound<&Q>, - ) -> Option> + ) -> Option> where Q: ?Sized, C: TypeRefQueryComparator<'a, K, Q>, @@ -369,7 +369,7 @@ where &'a self, version: Version, lower: Bound<&Q>, - ) -> Option> + ) -> Option> where Q: ?Sized, C: TypeRefQueryComparator<'a, K, Q>, @@ -382,7 +382,7 @@ where /// Returns a new iterator, this iterator will yield the latest version of all entries in the map less or equal to the given version. #[inline] - pub fn iter(&self, version: Version) -> iterator::Iter<'_, K, V, Active, A, RC, C> { + pub fn iter(&self, version: Version) -> iterator::Iter<'_, K, V, Active, C, A, RC> { iterator::Iter::new(version, self, false) } @@ -391,7 +391,7 @@ where pub fn iter_with_tombstone( &self, version: Version, - ) -> iterator::Iter<'_, K, V, MaybeTombstone, A, RC, C> + ) -> iterator::Iter<'_, K, V, MaybeTombstone, C, A, RC> where { iterator::Iter::new(version, self, true) } @@ -402,7 +402,7 @@ where { &self, version: Version, range: R, - ) -> iterator::Iter<'_, K, V, Active, A, RC, C, Q, R> + ) -> iterator::Iter<'_, K, V, Active, C, A, RC, Q, R> where Q: ?Sized, R: RangeBounds, @@ -416,7 +416,7 @@ where { &self, version: Version, range: R, - ) -> iterator::Iter<'_, K, V, MaybeTombstone, A, RC, C, Q, R> + ) -> iterator::Iter<'_, K, V, MaybeTombstone, C, A, RC, Q, R> where Q: ?Sized, R: RangeBounds, diff --git a/src/generic/list/api/update.rs b/src/generic/list/api/update.rs index 8e2752d..fc3329c 100644 --- a/src/generic/list/api/update.rs +++ b/src/generic/list/api/update.rs @@ -15,7 +15,7 @@ use super::{ Active, Allocator, EntryRef, Error, Height, RemoveValueBuilder, SkipList, ValueBuilder, Version, }; -impl SkipList +impl SkipList where K: ?Sized + Type + 'static, V: ?Sized + Type + 'static, @@ -33,7 +33,7 @@ where version: Version, key: impl Into>, value: impl Into>, - ) -> Result>, Among> + ) -> Result>, Among> where C: TypeRefComparator<'a, K>, { @@ -51,7 +51,7 @@ where height: Height, key: impl Into>, value: impl Into>, - ) -> Result>, Among> + ) -> Result>, Among> where C: TypeRefComparator<'a, K>, { @@ -105,7 +105,7 @@ where height: Height, key: impl Into>, value_builder: ValueBuilder) -> Result>, - ) -> Result>, Among> + ) -> Result>, Among> where C: TypeRefComparator<'a, K>, { @@ -148,7 +148,7 @@ where height: Height, key: impl Into>, value: impl Into>, - ) -> Result>, Among> + ) -> Result>, Among> where C: TypeRefComparator<'a, K>, { @@ -202,7 +202,7 @@ where height: Height, key: impl Into>, value_builder: ValueBuilder) -> Result>, - ) -> Result>, Among> + ) -> Result>, Among> where C: TypeRefComparator<'a, K>, { @@ -250,7 +250,7 @@ where height: Height, key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, - ) -> Result>, Among> + ) -> Result>, Among> where C: TypeRefComparator<'a, K>, { @@ -306,7 +306,7 @@ where height: Height, key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, - ) -> Result>, Among> + ) -> Result>, Among> where C: TypeRefComparator<'a, K>, { @@ -363,7 +363,7 @@ where key: impl Into>, success: Ordering, failure: Ordering, - ) -> Result>, Either> + ) -> Result>, Either> where C: TypeRefComparator<'a, K>, { @@ -416,7 +416,7 @@ where version: Version, height: Height, key: impl Into>, - ) -> Result>, Either> + ) -> Result>, Either> where C: TypeRefComparator<'a, K>, { @@ -468,7 +468,7 @@ where version: Version, height: Height, key_builder: KeyBuilder) -> Result>, - ) -> Result>, Either> + ) -> Result>, Either> where C: TypeRefComparator<'a, K>, { diff --git a/src/generic/list/entry.rs b/src/generic/list/entry.rs index 6a0224c..4ebe90c 100644 --- a/src/generic/list/entry.rs +++ b/src/generic/list/entry.rs @@ -14,7 +14,7 @@ use crate::{ }; /// An entry reference of the `SkipMap`. -pub struct EntryRef<'a, K, V, S, A, R, C> +pub struct EntryRef<'a, K, V, S, C, A, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -22,7 +22,7 @@ where R: RefCounter, S: State<'a>, { - pub(super) list: &'a SkipList, + pub(super) list: &'a SkipList, pub(super) key: LazyRef<'a, K>, pub(super) value: S::Value, pub(super) value_part_pointer: ValuePointer, @@ -32,7 +32,7 @@ where _m: PhantomData, } -impl<'a, K, V, S, A, R, C> core::fmt::Debug for EntryRef<'a, K, V, S, A, R, C> +impl<'a, K, V, S, C, A, R> core::fmt::Debug for EntryRef<'a, K, V, S, C, A, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -50,7 +50,7 @@ where } } -impl<'a, K, V, S, A, R, C> Clone for EntryRef<'a, K, V, S, A, R, C> +impl<'a, K, V, S, C, A, R> Clone for EntryRef<'a, K, V, S, C, A, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -72,7 +72,7 @@ where } } -impl<'a, K, V, A, R, C> EntryRef<'a, K, V, MaybeTombstone, A, R, C> +impl<'a, K, V, C, A, R> EntryRef<'a, K, V, MaybeTombstone, C, A, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -80,7 +80,7 @@ where R: RefCounter, { #[inline] - pub(super) fn into_active(self) -> EntryRef<'a, K, V, Active, A, R, C> { + pub(super) fn into_active(self) -> EntryRef<'a, K, V, Active, C, A, R> { EntryRef { list: self.list, key: self.key, @@ -94,7 +94,7 @@ where } } -impl<'a, K, V, S, A, R, C> EntryRef<'a, K, V, S, A, R, C> +impl<'a, K, V, S, C, A, R> EntryRef<'a, K, V, S, C, A, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -139,7 +139,7 @@ where } } -impl<'a, K, V, S, A, R, C> EntryRef<'a, K, V, S, A, R, C> +impl<'a, K, V, S, C, A, R> EntryRef<'a, K, V, S, C, A, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -199,7 +199,7 @@ where } } -impl<'a, K, V, S, A, R, C> EntryRef<'a, K, V, S, A, R, C> +impl<'a, K, V, S, C, A, R> EntryRef<'a, K, V, S, C, A, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -215,7 +215,7 @@ where } } -impl<'a, K, V, S, A, R, C> EntryRef<'a, K, V, S, A, R, C> +impl<'a, K, V, S, C, A, R> EntryRef<'a, K, V, S, C, A, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -227,7 +227,7 @@ where pub(crate) fn from_node( query_version: Version, node: ::Pointer, - list: &'a SkipList, + list: &'a SkipList, raw_key: Option<&'a [u8]>, key: Option>, ) -> Self { @@ -265,7 +265,7 @@ where pub(crate) fn from_node_with_pointer( query_version: Version, node: ::Pointer, - list: &'a SkipList, + list: &'a SkipList, pointer: ValuePointer, raw_key: Option<&'a [u8]>, key: Option>, diff --git a/src/generic/list/iterator.rs b/src/generic/list/iterator.rs index 8a28acd..91d3b1a 100644 --- a/src/generic/list/iterator.rs +++ b/src/generic/list/iterator.rs @@ -11,7 +11,7 @@ use super::{Allocator, EntryRef, NodePointer, RefCounter, SkipList, Version}; /// An iterator over the skipmap (this iterator will yields all versions). The current state of the iterator can be cloned by /// simply value copying the struct. -pub struct Iter<'a, K, V, S, A, RC, C, Q = ::Ref<'a>, R = core::ops::RangeFull> +pub struct Iter<'a, K, V, S, C, A, RC, Q = ::Ref<'a>, R = core::ops::RangeFull> where A: Allocator, K: ?Sized + Type, @@ -20,16 +20,16 @@ where Q: ?Sized, RC: RefCounter, { - pub(super) map: &'a SkipList, + pub(super) map: &'a SkipList, pub(super) version: Version, pub(super) range: Option, pub(super) all_versions: bool, - pub(super) head: Option>, - pub(super) tail: Option>, + pub(super) head: Option>, + pub(super) tail: Option>, pub(super) _phantom: core::marker::PhantomData, } -impl<'a, K, V, S, A, RC, C, Q, R: Clone> Clone for Iter<'a, K, V, S, A, RC, C, Q, R> +impl<'a, K, V, S, C, A, RC, Q, R: Clone> Clone for Iter<'a, K, V, S, C, A, RC, Q, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -51,7 +51,7 @@ where } } -impl<'a, K, V, S, A, RC, C> Iter<'a, K, V, S, A, RC, C> +impl<'a, K, V, S, C, A, RC> Iter<'a, K, V, S, C, A, RC> where K: ?Sized + Type, V: ?Sized + Type, @@ -62,7 +62,7 @@ where #[inline] pub(crate) const fn new( version: Version, - map: &'a SkipList, + map: &'a SkipList, all_versions: bool, ) -> Self { Self { @@ -78,7 +78,7 @@ where /// Changes the `Q` type of the iterator to adapt to a different query type for the iterator. #[inline] - pub fn map(&self) -> Iter<'a, K, V, S, A, RC, C, Q> { + pub fn map(&self) -> Iter<'a, K, V, S, C, A, RC, Q> { Iter { map: self.map, head: None, @@ -91,7 +91,7 @@ where } } -impl<'a, K, V, S, A, RC, C, Q, R> Iter<'a, K, V, S, A, RC, C, Q, R> +impl<'a, K, V, S, C, A, RC, Q, R> Iter<'a, K, V, S, C, A, RC, Q, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -103,7 +103,7 @@ where #[inline] pub(crate) fn range( version: Version, - map: &'a SkipList, + map: &'a SkipList, r: R, all_versions: bool, ) -> Self { @@ -119,7 +119,7 @@ where } } -impl<'a, K, V, S, A, RC, C, Q, R> Iter<'a, K, V, S, A, RC, C, Q, R> +impl<'a, K, V, S, C, A, RC, Q, R> Iter<'a, K, V, S, C, A, RC, Q, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -151,18 +151,18 @@ where /// Returns the entry at the current head position of the iterator. #[inline] - pub const fn head(&self) -> Option<&EntryRef<'a, K, V, S, A, RC, C>> { + pub const fn head(&self) -> Option<&EntryRef<'a, K, V, S, C, A, RC>> { self.head.as_ref() } /// Returns the entry at the current tail position of the iterator. #[inline] - pub const fn tail(&self) -> Option<&EntryRef<'a, K, V, S, A, RC, C>> { + pub const fn tail(&self) -> Option<&EntryRef<'a, K, V, S, C, A, RC>> { self.tail.as_ref() } } -impl<'a, K, V, S, A, RC, C, Q, R> Iter<'a, K, V, S, A, RC, C, Q, R> +impl<'a, K, V, S, C, A, RC, Q, R> Iter<'a, K, V, S, C, A, RC, Q, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -175,7 +175,7 @@ where { /// Advances to the next position. Returns the key and value if the /// iterator is pointing at a valid entry, and `None` otherwise. - fn next_in(&mut self) -> Option> { + fn next_in(&mut self) -> Option> { unsafe { let mut next_head = match self.head.as_ref() { Some(head) => self.map.get_next(head.ptr, 0), @@ -224,7 +224,7 @@ where /// Advances to the prev position. Returns the key and value if the /// iterator is pointing at a valid entry, and `None` otherwise. - fn prev(&mut self) -> Option> { + fn prev(&mut self) -> Option> { unsafe { let mut next_tail = match self.tail.as_ref() { Some(tail) => self.map.get_prev(tail.ptr, 0), @@ -272,7 +272,7 @@ where } } - fn range_next_in(&mut self) -> Option> { + fn range_next_in(&mut self) -> Option> { unsafe { let mut next_head = match self.head.as_ref() { Some(head) => self.map.get_next(head.ptr, 0), @@ -330,7 +330,7 @@ where } } - fn range_prev(&mut self) -> Option> { + fn range_prev(&mut self) -> Option> { unsafe { let mut next_tail = match self.tail.as_ref() { Some(tail) => self.map.get_prev(tail.ptr, 0), @@ -389,7 +389,7 @@ where } } -impl<'a, K, V, S, A, RC, C, Q, R> Iter<'a, K, V, S, A, RC, C, Q, R> +impl<'a, K, V, S, C, A, RC, Q, R> Iter<'a, K, V, S, C, A, RC, Q, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -407,7 +407,7 @@ where pub fn seek_upper_bound( &mut self, upper: Bound<&QR>, - ) -> Option> + ) -> Option> where QR: ?Sized, C: TypeRefQueryComparator<'a, K, QR>, @@ -433,7 +433,7 @@ where pub fn seek_lower_bound( &mut self, lower: Bound<&QR>, - ) -> Option> + ) -> Option> where QR: ?Sized, C: TypeRefQueryComparator<'a, K, QR>, @@ -455,7 +455,7 @@ where /// Moves the iterator to the first entry whose key is greater than or /// equal to the given key. Returns the key and value if the iterator is /// pointing at a valid entry, and `None` otherwise. - fn seek_ge(&self, key: &QR) -> Option> + fn seek_ge(&self, key: &QR) -> Option> where QR: ?Sized, C: TypeRefQueryComparator<'a, K, QR>, @@ -493,7 +493,7 @@ where /// Moves the iterator to the first entry whose key is greater than /// the given key. Returns the key and value if the iterator is /// pointing at a valid entry, and `None` otherwise. - fn seek_gt(&self, key: &QR) -> Option> + fn seek_gt(&self, key: &QR) -> Option> where QR: ?Sized, C: TypeRefQueryComparator<'a, K, QR>, @@ -531,7 +531,7 @@ where /// Moves the iterator to the first entry whose key is less than or /// equal to the given key. Returns the key and value if the iterator is /// pointing at a valid entry, and `None` otherwise. - fn seek_le(&self, key: &QR) -> Option> + fn seek_le(&self, key: &QR) -> Option> where QR: ?Sized, C: TypeRefQueryComparator<'a, K, QR>, @@ -569,7 +569,7 @@ where /// Moves the iterator to the last entry whose key is less than the given /// key. Returns the key and value if the iterator is pointing at a valid entry, /// and `None` otherwise. - fn seek_lt(&self, key: &QR) -> Option> + fn seek_lt(&self, key: &QR) -> Option> where QR: ?Sized, C: TypeRefQueryComparator<'a, K, QR>, @@ -599,14 +599,14 @@ where } #[inline] - fn first(&mut self) -> Option> { + fn first(&mut self) -> Option> { self.head = None; self.tail = None; self.next() } #[inline] - fn last(&mut self) -> Option> { + fn last(&mut self) -> Option> { self.tail = None; self.head = None; self.prev() @@ -622,7 +622,7 @@ where } } -impl<'a, K, V, S, A, RC, C, Q, R> Iterator for Iter<'a, K, V, S, A, RC, C, Q, R> +impl<'a, K, V, S, C, A, RC, Q, R> Iterator for Iter<'a, K, V, S, C, A, RC, Q, R> where K: ?Sized + Type, V: ?Sized + Type, @@ -633,7 +633,7 @@ where R: RangeBounds, C: TypeRefQueryComparator<'a, K, Q>, { - type Item = EntryRef<'a, K, V, S, A, RC, C>; + type Item = EntryRef<'a, K, V, S, C, A, RC>; #[inline] fn next(&mut self) -> Option { @@ -671,7 +671,7 @@ where } } -impl<'a, K, V, S, A, RC, C, Q, R> DoubleEndedIterator for Iter<'a, K, V, S, A, RC, C, Q, R> +impl<'a, K, V, S, C, A, RC, Q, R> DoubleEndedIterator for Iter<'a, K, V, S, C, A, RC, Q, R> where K: ?Sized + Type, V: ?Sized + Type, diff --git a/src/generic/multiple_version.rs b/src/generic/multiple_version.rs index 31ea967..fa975ab 100644 --- a/src/generic/multiple_version.rs +++ b/src/generic/multiple_version.rs @@ -34,19 +34,19 @@ pub mod unsync { crate::__generic_multiple_version_map_tests!("unsync_multiple_version_map": super::SkipMap<[u8], [u8]>); } - type SkipList = super::super::list::SkipList; + type SkipList = super::super::list::SkipList; /// Iterator over the [`SkipMap`]. pub type Iter<'a, K, V, S, C = Ascend> = - super::super::iter::Iter<'a, K, V, S, Allocator, RefCounter, C>; + super::super::iter::Iter<'a, K, V, S, C, Allocator, RefCounter>; /// Iterator over a subset of the [`SkipMap`]. pub type Range<'a, K, V, S, Q, R, C = Ascend> = - super::super::iter::Iter<'a, K, V, S, Allocator, RefCounter, C, Q, R>; + super::super::iter::Iter<'a, K, V, S, C, Allocator, RefCounter, Q, R>; /// The entry reference of the [`SkipMap`]. pub type Entry<'a, K, V, S, C = Ascend> = - super::super::entry::EntryRef<'a, K, V, S, Allocator, RefCounter, C>; + super::super::entry::EntryRef<'a, K, V, S, C, Allocator, RefCounter>; /// A fast, ARENA based `SkipMap` that supports multiple versions, forward and backward iteration. /// @@ -138,19 +138,19 @@ pub mod sync { crate::__generic_multiple_version_map_tests!(go "sync_multiple_version_map": super::SkipMap<[u8], [u8]> => crate::tests::generic::TEST_OPTIONS_WITH_PESSIMISTIC_FREELIST); } - type SkipList = super::super::list::SkipList; + type SkipList = super::super::list::SkipList; /// Iterator over the [`SkipMap`]. pub type Iter<'a, K, V, S, C = Ascend> = - super::super::iter::Iter<'a, K, V, S, Allocator, RefCounter, C>; + super::super::iter::Iter<'a, K, V, S, C, Allocator, RefCounter>; /// Iterator over a subset of the [`SkipMap`]. pub type Range<'a, K, V, S, Q, R, C = Ascend> = - super::super::iter::Iter<'a, K, V, S, Allocator, RefCounter, C, Q, R>; + super::super::iter::Iter<'a, K, V, S, C, Allocator, RefCounter, Q, R>; /// The entry reference of the [`SkipMap`]. pub type Entry<'a, K, V, S, C = Ascend> = - super::super::entry::EntryRef<'a, K, V, S, Allocator, RefCounter, C>; + super::super::entry::EntryRef<'a, K, V, S, C, Allocator, RefCounter>; /// A fast, lock-free, thread-safe ARENA based `SkipMap` that supports multiple versions, forward and backward iteration. /// @@ -214,7 +214,7 @@ where K: ?Sized + 'static, V: ?Sized + 'static, C: 'static, - Self: Arena>, + Self: Arena>, ::Node: WithVersion, { /// The allocator type used to allocate nodes in the map. @@ -396,7 +396,7 @@ where fn first<'a>( &'a self, version: Version, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -414,7 +414,7 @@ where fn last<'a>( &'a self, version: Version, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -435,7 +435,7 @@ where fn first_with_tombstone<'a>( &'a self, version: Version, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -456,7 +456,7 @@ where fn last_with_tombstone<'a>( &'a self, version: Version, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -495,7 +495,7 @@ where &'a self, version: Version, key: &Q, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -535,7 +535,7 @@ where &'a self, version: Version, key: &Q, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -556,7 +556,7 @@ where &'a self, version: Version, upper: Bound<&Q>, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -577,7 +577,7 @@ where &'a self, version: Version, lower: Bound<&Q>, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -600,7 +600,7 @@ where &'a self, version: Version, upper: Bound<&Q>, - ) -> Option> + ) -> Option> where K: Type, @@ -624,7 +624,7 @@ where &'a self, version: Version, lower: Bound<&Q>, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -640,7 +640,7 @@ where /// Returns a new iterator, this iterator will yield the latest version of all entries in the map less or equal to the given version. #[inline] - fn iter(&self, version: Version) -> Iter<'_, K, V, Active, Self::Allocator, Self::RefCounter, C> + fn iter(&self, version: Version) -> Iter<'_, K, V, Active, C, Self::Allocator, Self::RefCounter> where K: Type, V: Type, @@ -653,7 +653,7 @@ where fn iter_with_tombstone( &self, version: Version, - ) -> Iter<'_, K, V, MaybeTombstone, Self::Allocator, Self::RefCounter, C> + ) -> Iter<'_, K, V, MaybeTombstone, C, Self::Allocator, Self::RefCounter> where K: Type, V: Type, @@ -667,7 +667,7 @@ where &self, version: Version, range: R, - ) -> Iter<'_, K, V, Active, Self::Allocator, Self::RefCounter, C, Q, R> + ) -> Iter<'_, K, V, Active, C, Self::Allocator, Self::RefCounter, Q, R> where K: Type, V: Type, @@ -683,7 +683,7 @@ where &self, version: Version, range: R, - ) -> Iter<'_, K, V, MaybeTombstone, Self::Allocator, Self::RefCounter, C, Q, R> + ) -> Iter<'_, K, V, MaybeTombstone, C, Self::Allocator, Self::RefCounter, Q, R> where K: Type, V: Type, @@ -705,7 +705,7 @@ where key: impl Into>, value: impl Into>, ) -> Result< - Option>, + Option>, Among, > where @@ -740,7 +740,7 @@ where key: impl Into>, value: impl Into>, ) -> Result< - Option>, + Option>, Among, > where @@ -805,7 +805,7 @@ where key: impl Into>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -877,7 +877,7 @@ where key: impl Into>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -903,7 +903,7 @@ where key: impl Into>, value: impl Into>, ) -> Result< - Option>, + Option>, Among, > where @@ -930,7 +930,7 @@ where key: impl Into>, value: impl Into>, ) -> Result< - Option>, + Option>, Among, > where @@ -997,7 +997,7 @@ where key: impl Into>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -1070,7 +1070,7 @@ where key: impl Into>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -1142,7 +1142,7 @@ where key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -1220,7 +1220,7 @@ where key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -1290,7 +1290,7 @@ where key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -1365,7 +1365,7 @@ where key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -1394,7 +1394,7 @@ where success: Ordering, failure: Ordering, ) -> Result< - Option>, + Option>, Either, > where @@ -1422,7 +1422,7 @@ where success: Ordering, failure: Ordering, ) -> Result< - Option>, + Option>, Either, > where @@ -1447,7 +1447,7 @@ where version: Version, key: impl Into>, ) -> Result< - Option>, + Option>, Either, > where @@ -1484,7 +1484,7 @@ where height: Height, key: impl Into>, ) -> Result< - Option>, + Option>, Either, > where @@ -1545,7 +1545,7 @@ where version: Version, key_builder: KeyBuilder) -> Result>, ) -> Result< - Option>, + Option>, Either, > where @@ -1610,7 +1610,7 @@ where height: Height, key_builder: KeyBuilder) -> Result>, ) -> Result< - Option>, + Option>, Either, > where diff --git a/src/generic/unique.rs b/src/generic/unique.rs index a010c6a..aa3bc39 100644 --- a/src/generic/unique.rs +++ b/src/generic/unique.rs @@ -16,7 +16,7 @@ use crate::{ error::Error, generic::Active, ref_counter::RefCounter, - Arena, Header, Height, KeyBuilder, ValueBuilder, MIN_VERSION, + Arena, Header, Height, KeyBuilder, MaybeTombstone, ValueBuilder, MIN_VERSION, }; use super::{ @@ -26,7 +26,7 @@ use super::{ /// Implementations for single-threaded environments. pub mod unsync { - use crate::generic::{Active, Ascend}; + use crate::generic::Ascend; pub use crate::unsync::{map::Allocator, RefCounter}; #[cfg(any(all(test, not(miri)), all_skl_tests, test_generic_unsync_map,))] @@ -34,19 +34,19 @@ pub mod unsync { crate::__generic_map_tests!("unsync_map": super::SkipMap<[u8], [u8]>); } - type SkipList = super::super::list::SkipList; + type SkipList = super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, K, V, C = Ascend> = - super::super::iter::Iter<'a, K, V, Active, Allocator, RefCounter, C>; + pub type Iter<'a, K, V, S, C = Ascend> = + super::super::iter::Iter<'a, K, V, S, C, Allocator, RefCounter>; /// Iterator over a subset of the [`SkipMap`]. - pub type Range<'a, K, V, Q, R, C = Ascend> = - super::super::iter::Iter<'a, K, V, Active, Allocator, RefCounter, C, Q, R>; + pub type Range<'a, K, V, S, Q, R, C = Ascend> = + super::super::iter::Iter<'a, K, V, S, C, Allocator, RefCounter, Q, R>; /// The entry reference of the [`SkipMap`]. - pub type Entry<'a, K, V, C = Ascend> = - super::super::entry::EntryRef<'a, K, V, Active, Allocator, RefCounter, C>; + pub type Entry<'a, K, V, S, C = Ascend> = + super::super::entry::EntryRef<'a, K, V, S, C, Allocator, RefCounter>; /// A fast, ARENA based `SkipMap` that supports forward and backward iteration. /// @@ -102,7 +102,7 @@ pub mod unsync { /// Implementations for concurrent environments. pub mod sync { - use crate::generic::{Active, Ascend}; + use crate::generic::Ascend; pub use crate::sync::{map::Allocator, RefCounter}; #[cfg(any(all(test, not(miri)), all_skl_tests, test_generic_sync_map,))] @@ -133,19 +133,19 @@ pub mod sync { crate::__generic_map_tests!(go "sync_map": super::SkipMap<[u8], [u8]> => crate::tests::generic::TEST_OPTIONS_WITH_PESSIMISTIC_FREELIST); } - type SkipList = super::super::list::SkipList; + type SkipList = super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, K, V, C = Ascend> = - super::super::iter::Iter<'a, K, V, Active, Allocator, RefCounter, C>; + pub type Iter<'a, K, V, S, C = Ascend> = + super::super::iter::Iter<'a, K, V, S, C, Allocator, RefCounter>; /// Iterator over a subset of the [`SkipMap`]. - pub type Range<'a, K, V, Q, R, C = Ascend> = - super::super::iter::Iter<'a, K, V, Active, Allocator, RefCounter, C, Q, R>; + pub type Range<'a, K, V, S, Q, R, C = Ascend> = + super::super::iter::Iter<'a, K, V, S, C, Allocator, RefCounter, Q, R>; /// The entry reference of the [`SkipMap`]. - pub type Entry<'a, K, V, C = Ascend> = - super::super::entry::EntryRef<'a, K, V, Active, Allocator, RefCounter, C>; + pub type Entry<'a, K, V, S, C = Ascend> = + super::super::entry::EntryRef<'a, K, V, S, C, Allocator, RefCounter>; /// A fast, lock-free, thread-safe ARENA based `SkipMap` that supports forward and backward iteration. /// @@ -209,7 +209,7 @@ where K: ?Sized + 'static, V: ?Sized + 'static, C: 'static, - Self: Arena>, + Self: Arena>, ::Node: WithoutVersion, { /// The allocator used to allocate nodes in the `SkipMap`. @@ -264,13 +264,15 @@ where self.as_ref().height() } - /// Returns the number of entries in the skipmap. + /// Returns the number of entries in the map, this `len` includes all tombstones. + /// + /// If the map only contains tombstones, this method will not return `0` but the number of tombstones. #[inline] fn len(&self) -> usize { self.as_ref().len() } - /// Returns true if the skipmap is empty. + /// Returns `true` if the map is empty, if the map only contains tombstones, this method will also return `false`. #[inline] fn is_empty(&self) -> bool { self.len() == 0 @@ -321,9 +323,36 @@ where self.as_ref().contains_key(MIN_VERSION, key) } + /// Returns `true` if the key exists in the map, even if it is marked as removed. + /// + /// ## Example + /// + /// ```rust + /// use skl::generic::{unique::{sync::SkipMap, Map}, Builder}; + /// + /// let map = Builder::new().with_capacity(1024).alloc::>().unwrap(); + /// + /// map.insert("hello", "world").unwrap(); + /// + /// map.remove("hello").unwrap(); + /// + /// assert!(!map.contains_key("hello")); + /// assert!(map.contains_key_with_tombstone("hello")); + /// ``` + #[inline] + fn contains_key_with_tombstone<'a, Q>(&'a self, key: &Q) -> bool + where + K: Type, + V: Type, + Q: ?Sized, + C: TypeRefQueryComparator<'a, K, Q>, + { + self.as_ref().contains_key_with_tombstone(MIN_VERSION, key) + } + /// Returns the first entry in the map. #[inline] - fn first<'a>(&'a self) -> Option> + fn first<'a>(&'a self) -> Option> where K: Type, V: Type, @@ -334,7 +363,7 @@ where /// Returns the last entry in the map. #[inline] - fn last<'a>(&'a self) -> Option> + fn last<'a>(&'a self) -> Option> where K: Type, V: Type, @@ -343,6 +372,38 @@ where self.as_ref().last(MIN_VERSION) } + /// Returns the first entry in the map. The returned entry may not be in valid state. (i.e. the entry is removed) + /// + /// The difference between [`first`](Map::first) and `first_with_tombstone` is that `first_with_tombstone` will return the value even if + /// the entry is removed or not in a valid state. + #[inline] + fn first_with_tombstone<'a>( + &'a self, + ) -> Option> + where + K: Type, + V: Type, + C: TypeRefQueryComparator<'a, K, K::Ref<'a>>, + { + self.as_ref().first_with_tombstone(0) + } + + /// Returns the last entry in the map. The returned entry may not be in valid state. (i.e. the entry is removed) + /// + /// The difference between [`last`](Map::last) and `last_with_tombstone` is that `last_with_tombstone` will return the value even if + /// the entry is removed or not in a valid state. + #[inline] + fn last_with_tombstone<'a>( + &'a self, + ) -> Option> + where + K: Type, + V: Type, + C: TypeRefQueryComparator<'a, K, K::Ref<'a>>, + { + self.as_ref().last_with_tombstone(0) + } + /// Returns the value associated with the given key, if it exists. /// /// ## Example @@ -365,7 +426,7 @@ where fn get<'a, Q>( &'a self, key: &Q, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -375,13 +436,48 @@ where self.as_ref().get(MIN_VERSION, key) } + /// Returns the value associated with the given key, if it exists. + /// + /// The difference between `get` and `get_with_tombstone` is that `get_with_tombstone` will return the value even if the entry is removed. + /// + /// ## Example + /// + /// ```rust + /// use skl::generic::{unique::{sync::SkipMap, Map}, Builder}; + /// + /// let map = Builder::new().with_capacity(1024).alloc::>().unwrap(); + /// + /// map.insert("hello", "world").unwrap(); + /// + /// map.remove("hello").unwrap(); + /// + /// assert!(map.get("hello").is_none()); + /// + /// let ent = map.get_with_tombstone("hello").unwrap(); + /// // value is None because the entry is marked as removed. + /// assert!(ent.value().is_none()); + /// ``` + #[inline] + fn get_with_tombstone<'a, Q>( + &'a self, + key: &Q, + ) -> Option> + where + K: Type, + V: Type, + Q: ?Sized, + C: TypeRefQueryComparator<'a, K, Q>, + { + self.as_ref().get_with_tombstone(MIN_VERSION, key) + } + /// Returns an `EntryRef` pointing to the highest element whose key is below the given bound. /// If no such element is found then `None` is returned. #[inline] fn upper_bound<'a, Q>( &'a self, upper: Bound<&Q>, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -397,7 +493,7 @@ where fn lower_bound<'a, Q>( &'a self, lower: Bound<&Q>, - ) -> Option> + ) -> Option> where K: Type, V: Type, @@ -407,9 +503,45 @@ where self.as_ref().lower_bound(MIN_VERSION, lower) } - /// Returns a new iterator, this iterator will yield the latest version of all entries in the map less or equal to the given version. + /// Returns an `EntryRef` pointing to the highest element whose key is below the given bound. + /// If no such element is found then `None` is returned. + /// + /// The difference between [`upper_bound`](Map::upper_bound) and `upper_bound_with_tombstone` is that `upper_bound_with_tombstone` will return the value even if the entry is removed. #[inline] - fn iter(&self) -> Iter<'_, K, V, Active, Self::Allocator, Self::RefCounter, C> + fn upper_bound_with_tombstone<'a, Q>( + &'a self, + upper: Bound<&Q>, + ) -> Option> + where + K: Type, + V: Type, + Q: ?Sized, + C: TypeRefQueryComparator<'a, K, Q>, + { + self.as_ref().upper_bound_with_tombstone(MIN_VERSION, upper) + } + + /// Returns an `EntryRef` pointing to the lowest element whose key is above the given bound. + /// If no such element is found then `None` is returned. + /// + /// The difference between [`lower_bound`](Map::lower_bound) and `lower_bound_with_tombstone` is that `lower_bound_with_tombstone` will return the value even if the entry is removed. + #[inline] + fn lower_bound_with_tombstone<'a, Q>( + &'a self, + lower: Bound<&Q>, + ) -> Option> + where + K: Type, + V: Type, + Q: ?Sized, + C: TypeRefQueryComparator<'a, K, Q>, + { + self.as_ref().lower_bound_with_tombstone(MIN_VERSION, lower) + } + + /// Returns a new iterator, this iterator will yield only active entries of all entries in the map less or equal to the given version. + #[inline] + fn iter(&self) -> Iter<'_, K, V, Active, C, Self::Allocator, Self::RefCounter> where K: Type, V: Type, @@ -417,12 +549,24 @@ where self.as_ref().iter(MIN_VERSION) } - /// Returns a iterator that within the range, this iterator will yield the latest version of all entries in the range less or equal to the given version. + /// Returns a new iterator, this iterator will yield with tombstones for all entries in the map less or equal to the given version. + #[inline] + fn iter_with_tombstone( + &self, + ) -> Iter<'_, K, V, MaybeTombstone, C, Self::Allocator, Self::RefCounter> + where + K: Type, + V: Type, + { + self.as_ref().iter_with_tombstone(0) + } + + /// Returns a iterator that within the range, this iterator will yield only active entries of all entries in the range less or equal to the given version. #[inline] fn range( &self, range: R, - ) -> Iter<'_, K, V, Active, Self::Allocator, Self::RefCounter, C, Q, R> + ) -> Iter<'_, K, V, Active, C, Self::Allocator, Self::RefCounter, Q, R> where K: Type, V: Type, @@ -432,6 +576,21 @@ where self.as_ref().range(MIN_VERSION, range) } + /// Returns a iterator that within the range, this iterator will yield with tombstones for all entries in the range less or equal to the given version. + #[inline] + fn range_with_tombstone( + &self, + range: R, + ) -> Iter<'_, K, V, MaybeTombstone, C, Self::Allocator, Self::RefCounter, Q, R> + where + K: Type, + V: Type, + Q: ?Sized, + R: RangeBounds, + { + self.as_ref().range_with_tombstone(MIN_VERSION, range) + } + /// Upserts a new key-value pair if it does not yet exist, if the key with the given version already exists, it will update the value. /// Unlike [`get_or_insert`](Map::get_or_insert), this method will update the value if the key with the given version already exists. /// @@ -443,7 +602,7 @@ where key: impl Into>, value: impl Into>, ) -> Result< - Option>, + Option>, Among, > where @@ -477,7 +636,7 @@ where key: impl Into>, value: impl Into>, ) -> Result< - Option>, + Option>, Among, > where @@ -544,7 +703,7 @@ where key: impl Into>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -611,7 +770,7 @@ where key: impl Into>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -636,7 +795,7 @@ where key: impl Into>, value: impl Into>, ) -> Result< - Option>, + Option>, Among, > where @@ -660,7 +819,7 @@ where key: impl Into>, value: impl Into>, ) -> Result< - Option>, + Option>, Among, > where @@ -727,7 +886,7 @@ where key: impl Into>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -795,7 +954,7 @@ where key: impl Into>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -869,7 +1028,7 @@ where key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -941,7 +1100,7 @@ where key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -1010,7 +1169,7 @@ where key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -1079,7 +1238,7 @@ where key_builder: KeyBuilder) -> Result>, value_builder: ValueBuilder) -> Result>, ) -> Result< - Option>, + Option>, Among, > where @@ -1108,7 +1267,7 @@ where &'a self, key: impl Into>, ) -> Result< - Option>, + Option>, Either, > where @@ -1134,7 +1293,7 @@ where height: Height, key: impl Into>, ) -> Result< - Option>, + Option>, Either, > where @@ -1162,7 +1321,7 @@ where &'a self, key: impl Into>, ) -> Result< - Option>, + Option>, Either, > where @@ -1199,7 +1358,7 @@ where height: Height, key: impl Into>, ) -> Result< - Option>, + Option>, Either, > where @@ -1261,7 +1420,7 @@ where &'a self, key_builder: KeyBuilder) -> Result>, ) -> Result< - Option>, + Option>, Either, > where @@ -1323,7 +1482,7 @@ where height: Height, key_builder: KeyBuilder) -> Result>, ) -> Result< - Option>, + Option>, Either, > where