use crate::{ZeroMap2d, ZeroSlice};
use core::cmp::Ordering;
use core::fmt;
use core::ops::Range;
use crate::map::ZeroMapKV;
use crate::map::ZeroVecLike;
use super::ZeroMap2dBorrowed;
pub struct ZeroMap2dCursor<'l, 'a, K0, K1, V>
where
K0: ZeroMapKV<'a>,
K1: ZeroMapKV<'a>,
V: ZeroMapKV<'a>,
K0: ?Sized,
K1: ?Sized,
V: ?Sized,
{
keys0: &'l K0::Slice,
joiner: &'l ZeroSlice<u32>,
keys1: &'l K1::Slice,
values: &'l V::Slice,
key0_index: usize,
}
impl<'a, K0, K1, V> ZeroMap2dCursor<'a, 'a, K0, K1, V>
where
K0: ZeroMapKV<'a>,
K1: ZeroMapKV<'a>,
V: ZeroMapKV<'a>,
K0: ?Sized,
K1: ?Sized,
V: ?Sized,
{
pub(crate) fn from_borrowed(
borrowed: &ZeroMap2dBorrowed<'a, K0, K1, V>,
key0_index: usize,
) -> Self {
debug_assert!(key0_index < borrowed.joiner.len());
ZeroMap2dCursor {
keys0: borrowed.keys0,
joiner: borrowed.joiner,
keys1: borrowed.keys1,
values: borrowed.values,
key0_index,
}
}
}
impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
where
K0: ZeroMapKV<'a>,
K1: ZeroMapKV<'a>,
V: ZeroMapKV<'a>,
K0: ?Sized,
K1: ?Sized,
V: ?Sized,
{
pub(crate) fn from_cow(cow: &'l ZeroMap2d<'a, K0, K1, V>, key0_index: usize) -> Self {
debug_assert!(key0_index < cow.joiner.len());
Self {
keys0: cow.keys0.zvl_as_borrowed(),
joiner: &cow.joiner,
keys1: cow.keys1.zvl_as_borrowed(),
values: cow.values.zvl_as_borrowed(),
key0_index,
}
}
pub fn key0(&self) -> &'l K0::GetType {
#[allow(clippy::unwrap_used)] self.keys0.zvl_get(self.key0_index).unwrap()
}
pub fn iter1(
&self,
) -> impl Iterator<
Item = (
&'l <K1 as ZeroMapKV<'a>>::GetType,
&'l <V as ZeroMapKV<'a>>::GetType,
),
> + '_ {
let range = self.get_range();
#[allow(clippy::unwrap_used)] range.map(move |idx| {
(
self.keys1.zvl_get(idx).unwrap(),
self.values.zvl_get(idx).unwrap(),
)
})
}
pub fn into_iter1(
self,
) -> impl Iterator<
Item = (
&'l <K1 as ZeroMapKV<'a>>::GetType,
&'l <V as ZeroMapKV<'a>>::GetType,
),
> {
let range = self.get_range();
#[allow(clippy::unwrap_used)] range.map(move |idx| {
(
self.keys1.zvl_get(idx).unwrap(),
self.values.zvl_get(idx).unwrap(),
)
})
}
pub(super) fn get_range(&self) -> Range<usize> {
debug_assert!(self.key0_index < self.joiner.len());
let start = if self.key0_index == 0 {
0
} else {
#[allow(clippy::unwrap_used)] self.joiner.get(self.key0_index - 1).unwrap()
};
#[allow(clippy::unwrap_used)] let limit = self.joiner.get(self.key0_index).unwrap();
debug_assert!(start < limit);
debug_assert!((limit as usize) <= self.values.zvl_len());
(start as usize)..(limit as usize)
}
}
impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
where
K0: ZeroMapKV<'a>,
K1: ZeroMapKV<'a>,
V: ZeroMapKV<'a>,
K0: ?Sized,
K1: ?Sized,
V: Copy,
{
pub fn iter1_copied(
&self,
) -> impl Iterator<Item = (&'l <K1 as ZeroMapKV<'a>>::GetType, V)> + '_ {
let range = self.get_range();
#[allow(clippy::unwrap_used)] range.map(move |idx| {
(
self.keys1.zvl_get(idx).unwrap(),
self.get1_copied_at(idx).unwrap(),
)
})
}
fn get1_copied_at(&self, index: usize) -> Option<V> {
let ule = self.values.zvl_get(index)?;
let mut result = Option::<V>::None;
V::Container::zvl_get_as_t(ule, |v| result.replace(*v));
#[allow(clippy::unwrap_used)] Some(result.unwrap())
}
}
impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
where
K0: ZeroMapKV<'a>,
K1: ZeroMapKV<'a> + Ord,
V: ZeroMapKV<'a>,
K0: ?Sized,
K1: ?Sized,
V: ?Sized,
{
pub fn get1(&self, key1: &K1) -> Option<&'l V::GetType> {
let key1_index = self.get_key1_index(key1)?;
#[allow(clippy::unwrap_used)] Some(self.values.zvl_get(key1_index).unwrap())
}
pub fn get1_by(&self, predicate: impl FnMut(&K1) -> Ordering) -> Option<&'l V::GetType> {
let key1_index = self.get_key1_index_by(predicate)?;
#[allow(clippy::unwrap_used)] Some(self.values.zvl_get(key1_index).unwrap())
}
fn get_key1_index_by(&self, predicate: impl FnMut(&K1) -> Ordering) -> Option<usize> {
let range = self.get_range();
debug_assert!(range.start < range.end); debug_assert!(range.end <= self.keys1.zvl_len());
let start = range.start;
#[allow(clippy::expect_used)] let binary_search_result = self
.keys1
.zvl_binary_search_in_range_by(predicate, range)
.expect("in-bounds range");
binary_search_result.ok().map(move |s| s + start)
}
fn get_key1_index(&self, key1: &K1) -> Option<usize> {
let range = self.get_range();
debug_assert!(range.start < range.end); debug_assert!(range.end <= self.keys1.zvl_len());
let start = range.start;
#[allow(clippy::expect_used)] let binary_search_result = self
.keys1
.zvl_binary_search_in_range(key1, range)
.expect("in-bounds range");
binary_search_result.ok().map(move |s| s + start)
}
}
impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
where
K0: ZeroMapKV<'a>,
K1: ZeroMapKV<'a> + Ord,
V: ZeroMapKV<'a>,
V: Copy,
K0: ?Sized,
K1: ?Sized,
{
#[inline]
pub fn get1_copied(&self, key1: &K1) -> Option<V> {
let key1_index = self.get_key1_index(key1)?;
self.get1_copied_at(key1_index)
}
#[inline]
pub fn get1_copied_by(&self, predicate: impl FnMut(&K1) -> Ordering) -> Option<V> {
let key1_index = self.get_key1_index_by(predicate)?;
self.get1_copied_at(key1_index)
}
}
impl<'m, 'n, 'a, 'b, K0, K1, V> PartialEq<ZeroMap2dCursor<'n, 'b, K0, K1, V>>
for ZeroMap2dCursor<'m, 'a, K0, K1, V>
where
K0: for<'c> ZeroMapKV<'c> + ?Sized,
K1: for<'c> ZeroMapKV<'c> + ?Sized,
V: for<'c> ZeroMapKV<'c> + ?Sized,
<K0 as ZeroMapKV<'a>>::Slice: PartialEq<<K0 as ZeroMapKV<'b>>::Slice>,
<K1 as ZeroMapKV<'a>>::Slice: PartialEq<<K1 as ZeroMapKV<'b>>::Slice>,
<V as ZeroMapKV<'a>>::Slice: PartialEq<<V as ZeroMapKV<'b>>::Slice>,
{
fn eq(&self, other: &ZeroMap2dCursor<'n, 'b, K0, K1, V>) -> bool {
self.keys0.eq(other.keys0)
&& self.joiner.eq(other.joiner)
&& self.keys1.eq(other.keys1)
&& self.values.eq(other.values)
&& self.key0_index.eq(&other.key0_index)
}
}
impl<'l, 'a, K0, K1, V> fmt::Debug for ZeroMap2dCursor<'l, 'a, K0, K1, V>
where
K0: ZeroMapKV<'a> + ?Sized,
K1: ZeroMapKV<'a> + ?Sized,
V: ZeroMapKV<'a> + ?Sized,
K0::Slice: fmt::Debug,
K1::Slice: fmt::Debug,
V::Slice: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("ZeroMap2d")
.field("keys0", &self.keys0)
.field("joiner", &self.joiner)
.field("keys1", &self.keys1)
.field("values", &self.values)
.field("key0_index", &self.key0_index)
.finish()
}
}