1use crate::{ZeroMap2d, ZeroSlice};
6
7use core::cmp::Ordering;
8use core::fmt;
9use core::ops::Range;
10
11use crate::map::ZeroMapKV;
12use crate::map::ZeroVecLike;
13
14use super::ZeroMap2dBorrowed;
15
16pub struct ZeroMap2dCursor<'l, 'a, K0, K1, V>
18where
19 K0: ZeroMapKV<'a>,
20 K1: ZeroMapKV<'a>,
21 V: ZeroMapKV<'a>,
22 K0: ?Sized,
23 K1: ?Sized,
24 V: ?Sized,
25{
26 keys0: &'l K0::Slice,
28 joiner: &'l ZeroSlice<u32>,
29 keys1: &'l K1::Slice,
30 values: &'l V::Slice,
31 key0_index: usize,
33}
34
35impl<'a, K0, K1, V> ZeroMap2dCursor<'a, 'a, K0, K1, V>
36where
37 K0: ZeroMapKV<'a>,
38 K1: ZeroMapKV<'a>,
39 V: ZeroMapKV<'a>,
40 K0: ?Sized,
41 K1: ?Sized,
42 V: ?Sized,
43{
44 pub(crate) fn from_borrowed(
46 borrowed: &ZeroMap2dBorrowed<'a, K0, K1, V>,
47 key0_index: usize,
48 ) -> Self {
49 debug_assert!(key0_index < borrowed.joiner.len());
50 ZeroMap2dCursor {
51 keys0: borrowed.keys0,
52 joiner: borrowed.joiner,
53 keys1: borrowed.keys1,
54 values: borrowed.values,
55 key0_index,
56 }
57 }
58}
59
60impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
61where
62 K0: ZeroMapKV<'a>,
63 K1: ZeroMapKV<'a>,
64 V: ZeroMapKV<'a>,
65 K0: ?Sized,
66 K1: ?Sized,
67 V: ?Sized,
68{
69 pub(crate) fn from_cow(cow: &'l ZeroMap2d<'a, K0, K1, V>, key0_index: usize) -> Self {
71 debug_assert!(key0_index < cow.joiner.len());
72 Self {
73 keys0: cow.keys0.zvl_as_borrowed(),
74 joiner: &cow.joiner,
75 keys1: cow.keys1.zvl_as_borrowed(),
76 values: cow.values.zvl_as_borrowed(),
77 key0_index,
78 }
79 }
80
81 pub fn key0(&self) -> &'l K0::GetType {
91 #[allow(clippy::unwrap_used)] self.keys0.zvl_get(self.key0_index).unwrap()
93 }
94
95 pub fn iter1(
101 &self,
102 ) -> impl DoubleEndedIterator<
103 Item = (
104 &'l <K1 as ZeroMapKV<'a>>::GetType,
105 &'l <V as ZeroMapKV<'a>>::GetType,
106 ),
107 > + ExactSizeIterator
108 + '_ {
109 let range = self.get_range();
110 #[allow(clippy::unwrap_used)] range.map(move |idx| {
112 (
113 self.keys1.zvl_get(idx).unwrap(),
114 self.values.zvl_get(idx).unwrap(),
115 )
116 })
117 }
118
119 pub fn into_iter1(
121 self,
122 ) -> impl DoubleEndedIterator<
123 Item = (
124 &'l <K1 as ZeroMapKV<'a>>::GetType,
125 &'l <V as ZeroMapKV<'a>>::GetType,
126 ),
127 > + ExactSizeIterator {
128 let range = self.get_range();
129 #[allow(clippy::unwrap_used)] range.map(move |idx| {
131 (
132 self.keys1.zvl_get(idx).unwrap(),
133 self.values.zvl_get(idx).unwrap(),
134 )
135 })
136 }
137
138 pub(super) fn get_range(&self) -> Range<usize> {
140 debug_assert!(self.key0_index < self.joiner.len());
141 let start = if self.key0_index == 0 {
142 0
143 } else {
144 #[allow(clippy::unwrap_used)] self.joiner.get(self.key0_index - 1).unwrap()
146 };
147 #[allow(clippy::unwrap_used)] let limit = self.joiner.get(self.key0_index).unwrap();
149 debug_assert!(start < limit);
151 debug_assert!((limit as usize) <= self.values.zvl_len());
152 (start as usize)..(limit as usize)
153 }
154}
155
156impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
157where
158 K0: ZeroMapKV<'a>,
159 K1: ZeroMapKV<'a>,
160 V: ZeroMapKV<'a>,
161 K0: ?Sized,
162 K1: ?Sized,
163 V: Copy,
164{
165 pub fn iter1_copied(
190 &self,
191 ) -> impl DoubleEndedIterator<Item = (&'l <K1 as ZeroMapKV<'a>>::GetType, V)> + ExactSizeIterator + '_
192 {
193 let range = self.get_range();
194 #[allow(clippy::unwrap_used)] range.map(move |idx| {
196 (
197 self.keys1.zvl_get(idx).unwrap(),
198 self.get1_copied_at(idx).unwrap(),
199 )
200 })
201 }
202 pub fn into_iter1_copied(
227 self,
228 ) -> impl DoubleEndedIterator<Item = (&'l <K1 as ZeroMapKV<'a>>::GetType, V)> + ExactSizeIterator
229 {
230 let range = self.get_range();
231 #[allow(clippy::unwrap_used)] range.map(move |idx| {
233 (
234 self.keys1.zvl_get(idx).unwrap(),
235 self.get1_copied_at(idx).unwrap(),
236 )
237 })
238 }
239
240 fn get1_copied_at(&self, index: usize) -> Option<V> {
241 let ule = self.values.zvl_get(index)?;
242 let mut result = Option::<V>::None;
243 V::Container::zvl_get_as_t(ule, |v| result.replace(*v));
244 #[allow(clippy::unwrap_used)] Some(result.unwrap())
246 }
247}
248
249impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
250where
251 K0: ZeroMapKV<'a>,
252 K1: ZeroMapKV<'a> + Ord,
253 V: ZeroMapKV<'a>,
254 K0: ?Sized,
255 K1: ?Sized,
256 V: ?Sized,
257{
258 pub fn get1(&self, key1: &K1) -> Option<&'l V::GetType> {
269 let key1_index = self.get_key1_index(key1)?;
270 #[allow(clippy::unwrap_used)] Some(self.values.zvl_get(key1_index).unwrap())
272 }
273
274 pub fn get1_by(&self, predicate: impl FnMut(&K1) -> Ordering) -> Option<&'l V::GetType> {
285 let key1_index = self.get_key1_index_by(predicate)?;
286 #[allow(clippy::unwrap_used)] Some(self.values.zvl_get(key1_index).unwrap())
288 }
289
290 fn get_key1_index_by(&self, predicate: impl FnMut(&K1) -> Ordering) -> Option<usize> {
292 let range = self.get_range();
293 debug_assert!(range.start < range.end); debug_assert!(range.end <= self.keys1.zvl_len());
295 let start = range.start;
296 #[allow(clippy::expect_used)] let binary_search_result = self
298 .keys1
299 .zvl_binary_search_in_range_by(predicate, range)
300 .expect("in-bounds range");
301 binary_search_result.ok().map(move |s| s + start)
302 }
303
304 fn get_key1_index(&self, key1: &K1) -> Option<usize> {
306 let range = self.get_range();
307 debug_assert!(range.start < range.end); debug_assert!(range.end <= self.keys1.zvl_len());
309 let start = range.start;
310 #[allow(clippy::expect_used)] let binary_search_result = self
312 .keys1
313 .zvl_binary_search_in_range(key1, range)
314 .expect("in-bounds range");
315 binary_search_result.ok().map(move |s| s + start)
316 }
317}
318
319impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
320where
321 K0: ZeroMapKV<'a>,
322 K1: ZeroMapKV<'a> + Ord,
323 V: ZeroMapKV<'a>,
324 V: Copy,
325 K0: ?Sized,
326 K1: ?Sized,
327{
328 #[inline]
341 pub fn get1_copied(&self, key1: &K1) -> Option<V> {
342 let key1_index = self.get_key1_index(key1)?;
343 self.get1_copied_at(key1_index)
344 }
345
346 #[inline]
348 pub fn get1_copied_by(&self, predicate: impl FnMut(&K1) -> Ordering) -> Option<V> {
349 let key1_index = self.get_key1_index_by(predicate)?;
350 self.get1_copied_at(key1_index)
351 }
352}
353
354impl<'m, 'n, 'a, 'b, K0, K1, V> PartialEq<ZeroMap2dCursor<'n, 'b, K0, K1, V>>
358 for ZeroMap2dCursor<'m, 'a, K0, K1, V>
359where
360 K0: for<'c> ZeroMapKV<'c> + ?Sized,
361 K1: for<'c> ZeroMapKV<'c> + ?Sized,
362 V: for<'c> ZeroMapKV<'c> + ?Sized,
363 <K0 as ZeroMapKV<'a>>::Slice: PartialEq<<K0 as ZeroMapKV<'b>>::Slice>,
364 <K1 as ZeroMapKV<'a>>::Slice: PartialEq<<K1 as ZeroMapKV<'b>>::Slice>,
365 <V as ZeroMapKV<'a>>::Slice: PartialEq<<V as ZeroMapKV<'b>>::Slice>,
366{
367 fn eq(&self, other: &ZeroMap2dCursor<'n, 'b, K0, K1, V>) -> bool {
368 self.keys0.eq(other.keys0)
369 && self.joiner.eq(other.joiner)
370 && self.keys1.eq(other.keys1)
371 && self.values.eq(other.values)
372 && self.key0_index.eq(&other.key0_index)
373 }
374}
375
376impl<'l, 'a, K0, K1, V> fmt::Debug for ZeroMap2dCursor<'l, 'a, K0, K1, V>
377where
378 K0: ZeroMapKV<'a> + ?Sized,
379 K1: ZeroMapKV<'a> + ?Sized,
380 V: ZeroMapKV<'a> + ?Sized,
381 K0::Slice: fmt::Debug,
382 K1::Slice: fmt::Debug,
383 V::Slice: fmt::Debug,
384{
385 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
386 f.debug_struct("ZeroMap2d")
387 .field("keys0", &self.keys0)
388 .field("joiner", &self.joiner)
389 .field("keys1", &self.keys1)
390 .field("values", &self.values)
391 .field("key0_index", &self.key0_index)
392 .finish()
393 }
394}