use core::{iter::FusedIterator, marker::PhantomData};
use crate::{
allocator::{Allocator, Global},
map::DEFAULT_PREFIX_LEN,
raw::{maximum_unchecked, minimum_unchecked, OpaqueNodePtr, RawIterator},
AsBytes, TreeMap,
};
macro_rules! implement_prefix_iter {
(
$(#[$outer:meta])*
struct $name:ident {
tree: $tree_ty:ty,
item: $item_ty:ty,
$leaf_accessor_func:ident
}
) => {
$(#[$outer])*
pub struct $name<'a, K, V, const PREFIX_LEN: usize = DEFAULT_PREFIX_LEN, A: Allocator = Global> {
inner: RawIterator<K, V, PREFIX_LEN>,
marker: PhantomData<$tree_ty>,
}
impl<'a, K: AsBytes, V, A: Allocator, const PREFIX_LEN: usize> $name<'a, K, V, PREFIX_LEN, A> {
pub(crate) unsafe fn new(
root: OpaqueNodePtr<K, V, PREFIX_LEN>,
) -> Self {
let (start, end) =
unsafe { (minimum_unchecked(root), maximum_unchecked(root)) };
Self {
inner: unsafe { RawIterator::new(start, end) },
marker: PhantomData,
}
}
}
impl<'a, K, V, const PREFIX_LEN: usize, A: Allocator> Iterator for $name<'a, K, V, PREFIX_LEN, A> {
type Item = $item_ty;
fn next(&mut self) -> Option<Self::Item> {
let leaf_ptr = unsafe { self.inner.next()? };
Some(unsafe { leaf_ptr.$leaf_accessor_func() })
}
}
impl<'a, K, V, const PREFIX_LEN: usize, A: Allocator> DoubleEndedIterator
for $name<'a, K, V, PREFIX_LEN, A>
{
fn next_back(&mut self) -> Option<Self::Item> {
let leaf_ptr = unsafe { self.inner.next_back()? };
Some(unsafe { leaf_ptr.$leaf_accessor_func() })
}
}
impl<'a, K, V, const PREFIX_LEN: usize, A: Allocator> FusedIterator for $name<'a, K, V, PREFIX_LEN, A> {}
};
}
implement_prefix_iter!(
struct SubtreeIter {
tree: &'a TreeMap<K, V, PREFIX_LEN, A>,
item: (&'a K, &'a V),
as_key_value_ref
}
);
unsafe impl<K, V, A, const PREFIX_LEN: usize> Send for SubtreeIter<'_, K, V, PREFIX_LEN, A>
where
K: Sync,
V: Sync,
A: Sync + Allocator,
{
}
unsafe impl<K, V, A, const PREFIX_LEN: usize> Sync for SubtreeIter<'_, K, V, PREFIX_LEN, A>
where
K: Sync,
V: Sync,
A: Sync + Allocator,
{
}
implement_prefix_iter!(
struct SubtreeIterMut {
tree: &'a mut TreeMap<K, V, PREFIX_LEN, A>,
item: (&'a K, &'a mut V),
as_key_ref_value_mut
}
);
unsafe impl<K, V, A, const PREFIX_LEN: usize> Send for SubtreeIterMut<'_, K, V, PREFIX_LEN, A>
where
K: Send,
V: Send,
A: Send + Allocator,
{
}
unsafe impl<K, V, A, const PREFIX_LEN: usize> Sync for SubtreeIterMut<'_, K, V, PREFIX_LEN, A>
where
K: Sync,
V: Sync,
A: Sync + Allocator,
{
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn iterators_are_send_sync() {
fn is_send<T: Send>() {}
fn is_sync<T: Sync>() {}
fn subtree_is_send<'a, K: Sync + 'a, V: Sync + 'a, A: Sync + Allocator + 'a>() {
is_send::<SubtreeIter<'a, K, V, DEFAULT_PREFIX_LEN, A>>();
}
fn subtree_is_sync<'a, K: Sync + 'a, V: Sync + 'a, A: Sync + Allocator + 'a>() {
is_sync::<SubtreeIter<'a, K, V, DEFAULT_PREFIX_LEN, A>>();
}
subtree_is_send::<[u8; 3], usize, Global>();
subtree_is_sync::<[u8; 3], usize, Global>();
fn subtree_mut_is_send<'a, K: Send + 'a, V: Send + 'a, A: Send + Allocator + 'a>() {
is_send::<SubtreeIterMut<'a, K, V, DEFAULT_PREFIX_LEN, A>>();
}
fn subtree_mut_is_sync<'a, K: Sync + 'a, V: Sync + 'a, A: Sync + Allocator + 'a>() {
is_sync::<SubtreeIterMut<'a, K, V, DEFAULT_PREFIX_LEN, A>>();
}
subtree_mut_is_send::<[u8; 3], usize, Global>();
subtree_mut_is_sync::<[u8; 3], usize, Global>();
}
}