Skip to main content

protocache_core/
access.rs

1//! Access surface matching `access.h`.
2
3use core::marker::PhantomData;
4
5use crate::perfect_hash::PerfectHashView;
6use crate::utils::{Scalar, word_size};
7
8pub trait MapKey {
9    fn as_key_bytes(&self) -> Vec<u8>;
10}
11
12pub trait FieldDecode<'a>: Sized {
13    fn decode(field: FieldView<'a>) -> Option<Self>;
14}
15
16impl<'a, T: Scalar> FieldDecode<'a> for T {
17    fn decode(field: FieldView<'a>) -> Option<Self> {
18        field.scalar::<T>()
19    }
20}
21
22macro_rules! impl_map_key {
23    ($($ty:ty),* $(,)?) => {
24        $(
25            impl MapKey for $ty {
26                fn as_key_bytes(&self) -> Vec<u8> {
27                    self.to_le_bytes().to_vec()
28                }
29            }
30        )*
31    };
32}
33
34impl_map_key!(i32, u32, i64, u64);
35
36#[derive(Clone, Copy, Debug)]
37pub struct StringView<'a> {
38    bytes: &'a [u8],
39}
40
41impl<'a> StringView<'a> {
42    #[inline(always)]
43    pub fn new(words: &'a [u32]) -> Option<Self> {
44        let raw = bytes_of_words(words);
45        let first = *raw.first()?;
46        if (first & 3) != 0 {
47            return None;
48        }
49
50        let mut mark = 0usize;
51        let mut shift = 0usize;
52        let mut used = 0usize;
53        while shift < 32 {
54            let byte = *raw.get(used)?;
55            used += 1;
56            if (byte & 0x80) != 0 {
57                mark |= ((byte & 0x7f) as usize) << shift;
58            } else {
59                mark |= (byte as usize) << shift;
60                let byte_len = mark >> 2;
61                let end = used.checked_add(byte_len)?;
62                return Some(Self {
63                    bytes: raw.get(used..end)?,
64                });
65            }
66            shift += 7;
67        }
68        None
69    }
70
71    #[inline(always)]
72    pub fn detect_len(words: &'a [u32]) -> Option<usize> {
73        let raw = bytes_of_words(words);
74        let first = *raw.first()?;
75        if (first & 3) != 0 {
76            return None;
77        }
78
79        let mut mark = 0usize;
80        let mut shift = 0usize;
81        let mut used = 0usize;
82        while shift < 32 {
83            let byte = *raw.get(used)?;
84            used += 1;
85            if (byte & 0x80) != 0 {
86                mark |= ((byte & 0x7f) as usize) << shift;
87            } else {
88                mark |= (byte as usize) << shift;
89                let total = used.checked_add(mark >> 2)?;
90                return Some(word_size(total));
91            }
92            shift += 7;
93        }
94        None
95    }
96
97    #[inline(always)]
98    pub fn detect(words: &'a [u32]) -> Option<&'a [u32]> {
99        words.get(..Self::detect_len(words)?)
100    }
101
102    #[inline(always)]
103    pub fn as_bytes(self) -> &'a [u8] {
104        self.bytes
105    }
106
107    #[inline(always)]
108    pub fn as_str(self) -> Option<&'a str> {
109        core::str::from_utf8(self.bytes).ok()
110    }
111
112    #[inline(always)]
113    pub fn as_bool_array(self) -> BoolArray<'a> {
114        BoolArray { bytes: self.bytes }
115    }
116}
117
118impl AsRef<[u8]> for StringView<'_> {
119    fn as_ref(&self) -> &[u8] {
120        self.bytes
121    }
122}
123
124impl<'a> core::fmt::Display for StringView<'a> {
125    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
126        match self.as_str() {
127            Some(value) => f.write_str(value),
128            None => write!(f, "{:?}", self.bytes),
129        }
130    }
131}
132
133#[derive(Clone, Copy, Debug)]
134pub struct BoolArray<'a> {
135    bytes: &'a [u8],
136}
137
138impl<'a> BoolArray<'a> {
139    #[inline(always)]
140    pub fn len(&self) -> usize {
141        self.bytes.len()
142    }
143
144    #[inline(always)]
145    pub fn is_empty(&self) -> bool {
146        self.bytes.is_empty()
147    }
148
149    #[inline(always)]
150    pub fn get(&self, index: usize) -> Option<bool> {
151        Some(*self.bytes.get(index)? != 0)
152    }
153
154    #[inline(always)]
155    pub fn iter(&self) -> impl Iterator<Item = bool> + 'a {
156        self.bytes.iter().copied().map(|v| v != 0)
157    }
158}
159
160#[derive(Clone, Copy, Debug)]
161pub struct FieldView<'a> {
162    tail: &'a [u32],
163    width: usize,
164}
165
166impl<'a> FieldView<'a> {
167    #[inline(always)]
168    pub fn raw_words(self) -> Option<&'a [u32]> {
169        self.tail.get(..self.width)
170    }
171
172    #[inline(always)]
173    pub fn expect_raw_words(self) -> &'a [u32] {
174        &self.tail[..self.width]
175    }
176
177    #[inline(always)]
178    pub fn object_words(self) -> Option<&'a [u32]> {
179        let first = *self.tail.first()?;
180        if (first & 3) == 3 {
181            self.tail.get((first >> 2) as usize..)
182        } else {
183            Some(self.tail)
184        }
185    }
186
187    #[inline(always)]
188    pub fn expect_object_words(self) -> &'a [u32] {
189        let first = self.tail[0];
190        if (first & 3) == 3 {
191            &self.tail[(first >> 2) as usize..]
192        } else {
193            self.tail
194        }
195    }
196
197    #[inline(always)]
198    pub fn scalar<T: Scalar>(self) -> Option<T> {
199        T::from_words(self.raw_words()?)
200    }
201
202    #[inline(always)]
203    pub fn expect_scalar<T: Scalar>(self) -> T {
204        T::from_words(self.expect_raw_words()).expect("invalid scalar field")
205    }
206
207    #[inline(always)]
208    pub fn detect_scalar(self) -> Option<&'a [u32]> {
209        self.raw_words()
210    }
211
212    #[inline(always)]
213    pub fn string(self) -> Option<StringView<'a>> {
214        StringView::new(self.object_words()?)
215    }
216
217    #[inline(always)]
218    pub fn expect_string(self) -> StringView<'a> {
219        StringView::new(self.expect_object_words()).expect("invalid string field")
220    }
221
222    #[inline(always)]
223    pub fn detect_string(self) -> Option<&'a [u32]> {
224        StringView::detect(self.object_words()?)
225    }
226
227    #[inline(always)]
228    pub fn message(self) -> Option<MessageView<'a>> {
229        MessageView::new(self.object_words()?)
230    }
231
232    #[inline(always)]
233    pub fn expect_message(self) -> MessageView<'a> {
234        MessageView::new(self.expect_object_words()).expect("invalid message field")
235    }
236
237    #[inline(always)]
238    pub fn detect_message(self) -> Option<&'a [u32]> {
239        MessageView::detect(self.object_words()?)
240    }
241
242    #[inline(always)]
243    pub fn array(self) -> Option<ArrayView<'a>> {
244        ArrayView::new(self.object_words()?)
245    }
246
247    #[inline(always)]
248    pub fn expect_array(self) -> ArrayView<'a> {
249        ArrayView::new(self.expect_object_words()).expect("invalid array field")
250    }
251
252    #[inline(always)]
253    pub fn detect_array(self) -> Option<&'a [u32]> {
254        ArrayView::detect(self.object_words()?)
255    }
256
257    #[inline(always)]
258    pub fn map(self) -> Option<MapView<'a>> {
259        MapView::new(self.object_words()?)
260    }
261
262    #[inline(always)]
263    pub fn expect_map(self) -> MapView<'a> {
264        MapView::new(self.expect_object_words()).expect("invalid map field")
265    }
266
267    #[inline(always)]
268    pub fn detect_map(self) -> Option<&'a [u32]> {
269        MapView::detect(self.object_words()?)
270    }
271}
272
273#[derive(Clone, Copy, Debug)]
274pub struct MessageView<'a> {
275    head: u32,
276    words: &'a [u32],
277    body: &'a [u32],
278    section: usize,
279}
280
281#[derive(Clone, Copy, Debug)]
282pub(crate) struct MessageLayout {
283    head: u32,
284    body_offset: usize,
285    section: usize,
286}
287
288impl<'a> MessageView<'a> {
289    #[inline(always)]
290    pub fn new(words: &'a [u32]) -> Option<Self> {
291        let layout = Self::layout(words)?;
292        let body = words.get(layout.body_offset..)?;
293        Some(Self {
294            head: layout.head,
295            words,
296            body,
297            section: layout.section,
298        })
299    }
300
301    #[inline(always)]
302    pub fn from_words(words: &'a [u32]) -> Option<Self> {
303        Self::new(words)
304    }
305
306    #[inline(always)]
307    pub fn raw_words(self) -> &'a [u32] {
308        self.words
309    }
310
311    #[inline(always)]
312    pub fn detect_len(words: &'a [u32]) -> Option<usize> {
313        let head = *words.first()?;
314        let section = (head & 0xff) as usize;
315        let mut tail = 1usize.checked_add(section.checked_mul(2)?)?;
316        if section == 0 {
317            tail = tail.checked_add(count32(head))?;
318        } else {
319            let sec_words = words.get(tail - 2..tail)?;
320            let raw = bytes_of_words(sec_words);
321            let sec = u64::from_le_bytes(raw.try_into().ok()?);
322            tail = tail.checked_add(count64(sec << 14))?;
323            tail = tail.checked_add((sec >> 50) as usize)?;
324        }
325        words.get(..tail)?;
326        Some(tail)
327    }
328
329    #[inline(always)]
330    pub fn detect(words: &'a [u32]) -> Option<&'a [u32]> {
331        words.get(..Self::detect_len(words)?)
332    }
333
334    #[inline(always)]
335    pub fn has_field(self, id: usize) -> bool {
336        self.field(id).is_some()
337    }
338
339    #[inline(always)]
340    pub fn field(self, id: usize) -> Option<FieldView<'a>> {
341        Self::field_in(
342            self.words,
343            &MessageLayout {
344                head: self.head,
345                body_offset: self.words.len() - self.body.len(),
346                section: self.section,
347            },
348            id,
349        )
350    }
351
352    #[inline(always)]
353    pub fn expect_field(self, id: usize) -> FieldView<'a> {
354        self.field(id).expect("missing message field")
355    }
356
357    #[inline(always)]
358    pub fn scalar<T: Scalar>(self, id: usize) -> Option<T> {
359        self.field(id)?.scalar::<T>()
360    }
361
362    #[inline(always)]
363    pub fn string(self, id: usize) -> Option<StringView<'a>> {
364        self.field(id)?.string()
365    }
366
367    #[inline(always)]
368    pub fn bytes(self, id: usize) -> Option<&'a [u8]> {
369        Some(self.string(id)?.as_bytes())
370    }
371
372    #[inline(always)]
373    pub fn bools(self, id: usize) -> Option<BoolArray<'a>> {
374        Some(self.string(id)?.as_bool_array())
375    }
376
377    #[inline(always)]
378    pub fn message(self, id: usize) -> Option<MessageView<'a>> {
379        self.field(id)?.message()
380    }
381
382    #[inline(always)]
383    pub fn array(self, id: usize) -> Option<ArrayView<'a>> {
384        self.field(id)?.array()
385    }
386
387    #[inline(always)]
388    pub fn map(self, id: usize) -> Option<MapView<'a>> {
389        self.field(id)?.map()
390    }
391
392    #[inline(always)]
393    pub(crate) fn layout(words: &[u32]) -> Option<MessageLayout> {
394        let head = *words.first()?;
395        let section = (head & 0xff) as usize;
396        let body_offset = 1usize.checked_add(section.checked_mul(2)?)?;
397        words.get(body_offset..)?;
398        Some(MessageLayout {
399            head,
400            body_offset,
401            section,
402        })
403    }
404
405    #[inline(always)]
406    pub(crate) fn field_in<'b>(
407        words: &'b [u32],
408        layout: &MessageLayout,
409        id: usize,
410    ) -> Option<FieldView<'b>> {
411        let (width, off) = if id < 12 {
412            let mut v = layout.head >> 8;
413            let width = ((v >> (id * 2)) & 3) as usize;
414            if width == 0 {
415                return None;
416            }
417            v &= !(u32::MAX << (id * 2));
418            (width, count32(v))
419        } else {
420            let section_index = (id - 12) / 25;
421            let bit_index = (id - 12) % 25;
422            if section_index >= layout.section {
423                return None;
424            }
425            let sec_words = words.get(1 + section_index * 2..1 + section_index * 2 + 2)?;
426            let raw = bytes_of_words(sec_words);
427            let vec = u64::from_le_bytes(raw.try_into().ok()?);
428            let width = ((vec >> (bit_index * 2)) & 3) as usize;
429            if width == 0 {
430                return None;
431            }
432            let mask = if bit_index == 0 {
433                0
434            } else {
435                (1u64 << (bit_index * 2)) - 1
436            };
437            (width, count64(vec & mask) + (vec >> 50) as usize)
438        };
439
440        let body = words.get(layout.body_offset..)?;
441        Some(FieldView {
442            tail: body.get(off..)?,
443            width,
444        })
445    }
446}
447
448#[derive(Clone, Copy, Debug)]
449pub struct ArrayView<'a> {
450    body: &'a [u32],
451    len: usize,
452    width: usize,
453}
454
455impl<'a> ArrayView<'a> {
456    #[inline(always)]
457    pub fn new(words: &'a [u32]) -> Option<Self> {
458        let head = *words.first()?;
459        let len = (head >> 2) as usize;
460        let width = (head & 3) as usize;
461        if width == 0 {
462            return None;
463        }
464        let body = words.get(1..)?;
465        body.get(..len.checked_mul(width)?)?;
466        Some(Self { body, len, width })
467    }
468
469    #[inline(always)]
470    pub fn detect_len(words: &'a [u32]) -> Option<usize> {
471        let head = *words.first()?;
472        let len = (head >> 2) as usize;
473        let width = (head & 3) as usize;
474        if width == 0 {
475            return None;
476        }
477        1usize.checked_add(len.checked_mul(width)?)
478    }
479
480    #[inline(always)]
481    pub fn detect(words: &'a [u32]) -> Option<&'a [u32]> {
482        words.get(..Self::detect_len(words)?)
483    }
484
485    #[inline(always)]
486    pub fn len(self) -> usize {
487        self.len
488    }
489
490    #[inline(always)]
491    pub fn is_empty(self) -> bool {
492        self.len == 0
493    }
494
495    #[inline(always)]
496    pub fn width(self) -> usize {
497        self.width
498    }
499
500    #[inline(always)]
501    pub(crate) fn total_words(self) -> usize {
502        1 + self.len * self.width
503    }
504
505    #[inline(always)]
506    pub fn field(self, index: usize) -> Option<FieldView<'a>> {
507        if index >= self.len {
508            return None;
509        }
510        let start = index.checked_mul(self.width)?;
511        Some(FieldView {
512            tail: self.body.get(start..)?,
513            width: self.width,
514        })
515    }
516
517    #[inline(always)]
518    pub fn expect_field(self, index: usize) -> FieldView<'a> {
519        let start = index * self.width;
520        FieldView {
521            tail: &self.body[start..],
522            width: self.width,
523        }
524    }
525
526    #[inline(always)]
527    pub fn scalars<T: Scalar>(self) -> Option<ScalarArray<'a, T>> {
528        if self.width != T::WIDTH {
529            return None;
530        }
531        Some(ScalarArray {
532            words: self.body.get(..self.len * self.width)?,
533            len: self.len,
534            _marker: PhantomData,
535        })
536    }
537
538    #[inline(always)]
539    pub fn expect_scalars<T: Scalar>(self) -> ScalarArray<'a, T> {
540        assert_eq!(self.width, T::WIDTH);
541        ScalarArray {
542            words: &self.body[..self.len * self.width],
543            len: self.len,
544            _marker: PhantomData,
545        }
546    }
547
548    #[inline(always)]
549    pub fn iter(self) -> ArrayIter<'a> {
550        ArrayIter {
551            array: self,
552            index: 0,
553        }
554    }
555}
556
557pub struct ArrayIter<'a> {
558    array: ArrayView<'a>,
559    index: usize,
560}
561
562impl<'a> Iterator for ArrayIter<'a> {
563    type Item = FieldView<'a>;
564
565    #[inline(always)]
566    fn next(&mut self) -> Option<Self::Item> {
567        let item = self.array.field(self.index)?;
568        self.index += 1;
569        Some(item)
570    }
571
572    #[inline(always)]
573    fn size_hint(&self) -> (usize, Option<usize>) {
574        let remaining = self.array.len.saturating_sub(self.index);
575        (remaining, Some(remaining))
576    }
577}
578
579impl ExactSizeIterator for ArrayIter<'_> {}
580impl core::iter::FusedIterator for ArrayIter<'_> {}
581
582pub struct ViewArray<'a, T> {
583    array: ArrayView<'a>,
584    _marker: PhantomData<T>,
585}
586
587impl<'a, T> Copy for ViewArray<'a, T> {}
588
589impl<'a, T> Clone for ViewArray<'a, T> {
590    fn clone(&self) -> Self {
591        *self
592    }
593}
594
595impl<'a, T: FieldDecode<'a>> ViewArray<'a, T> {
596    #[inline(always)]
597    pub fn new(array: ArrayView<'a>) -> Self {
598        Self {
599            array,
600            _marker: PhantomData,
601        }
602    }
603
604    #[inline(always)]
605    pub fn len(&self) -> usize {
606        self.array.len()
607    }
608
609    #[inline(always)]
610    pub fn is_empty(&self) -> bool {
611        self.array.is_empty()
612    }
613
614    #[inline(always)]
615    pub fn get(&self, index: usize) -> Option<T> {
616        T::decode(self.array.field(index)?)
617    }
618
619    #[inline(always)]
620    pub fn iter(&self) -> ViewArrayIter<'a, T> {
621        ViewArrayIter {
622            array: *self,
623            index: 0,
624        }
625    }
626
627    #[inline(always)]
628    pub fn raw(&self) -> ArrayView<'a> {
629        self.array
630    }
631}
632
633pub struct ViewArrayIter<'a, T> {
634    array: ViewArray<'a, T>,
635    index: usize,
636}
637
638impl<'a, T: FieldDecode<'a>> Iterator for ViewArrayIter<'a, T> {
639    type Item = T;
640
641    #[inline(always)]
642    fn next(&mut self) -> Option<Self::Item> {
643        let value = self.array.get(self.index)?;
644        self.index += 1;
645        Some(value)
646    }
647
648    #[inline(always)]
649    fn size_hint(&self) -> (usize, Option<usize>) {
650        let remaining = self.array.len().saturating_sub(self.index);
651        (remaining, Some(remaining))
652    }
653}
654
655impl<'a, T: FieldDecode<'a>> ExactSizeIterator for ViewArrayIter<'a, T> {}
656impl<'a, T: FieldDecode<'a>> core::iter::FusedIterator for ViewArrayIter<'a, T> {}
657
658pub struct ScalarArray<'a, T> {
659    words: &'a [u32],
660    len: usize,
661    _marker: PhantomData<T>,
662}
663
664impl<'a, T> Copy for ScalarArray<'a, T> {}
665
666impl<'a, T> Clone for ScalarArray<'a, T> {
667    fn clone(&self) -> Self {
668        *self
669    }
670}
671
672impl<'a, T: Scalar> ScalarArray<'a, T> {
673    #[inline(always)]
674    pub fn len(&self) -> usize {
675        self.len
676    }
677
678    #[inline(always)]
679    pub fn is_empty(&self) -> bool {
680        self.len == 0
681    }
682
683    #[inline(always)]
684    pub fn get(&self, index: usize) -> Option<T> {
685        if index >= self.len {
686            return None;
687        }
688        let start = index.checked_mul(T::WIDTH)?;
689        T::from_words(self.words.get(start..start + T::WIDTH)?)
690    }
691
692    #[inline(always)]
693    pub fn iter(&self) -> ScalarArrayIter<'a, T> {
694        ScalarArrayIter {
695            array: *self,
696            index: 0,
697        }
698    }
699}
700
701pub struct ScalarArrayIter<'a, T> {
702    array: ScalarArray<'a, T>,
703    index: usize,
704}
705
706impl<'a, T: Scalar> Iterator for ScalarArrayIter<'a, T> {
707    type Item = T;
708
709    #[inline(always)]
710    fn next(&mut self) -> Option<Self::Item> {
711        let value = self.array.get(self.index)?;
712        self.index += 1;
713        Some(value)
714    }
715
716    #[inline(always)]
717    fn size_hint(&self) -> (usize, Option<usize>) {
718        let remaining = self.array.len().saturating_sub(self.index);
719        (remaining, Some(remaining))
720    }
721}
722
723impl<T: Scalar> ExactSizeIterator for ScalarArrayIter<'_, T> {}
724impl<T: Scalar> core::iter::FusedIterator for ScalarArrayIter<'_, T> {}
725
726#[derive(Clone, Copy, Debug)]
727pub struct PairView<'a> {
728    tail: &'a [u32],
729    key_width: usize,
730    value_width: usize,
731}
732
733impl<'a> PairView<'a> {
734    #[inline(always)]
735    pub fn key(self) -> FieldView<'a> {
736        FieldView {
737            tail: self.tail,
738            width: self.key_width,
739        }
740    }
741
742    #[inline(always)]
743    pub fn value(self) -> FieldView<'a> {
744        FieldView {
745            tail: &self.tail[self.key_width..],
746            width: self.value_width,
747        }
748    }
749}
750
751#[derive(Clone, Copy, Debug)]
752pub struct MapView<'a> {
753    index: PerfectHashView<'a>,
754    body: &'a [u32],
755    len: usize,
756    key_width: usize,
757    value_width: usize,
758    total_words: usize,
759}
760
761impl<'a> MapView<'a> {
762    #[inline(always)]
763    pub fn new(words: &'a [u32]) -> Option<Self> {
764        let head = *words.first()?;
765        let key_width = ((head >> 30) & 3) as usize;
766        let value_width = ((head >> 28) & 3) as usize;
767        if key_width == 0 || value_width == 0 {
768            return None;
769        }
770
771        let index = PerfectHashView::new(bytes_of_words(words)).ok()?;
772        let body_offset = word_size(index.data_size());
773        let body = words.get(body_offset..)?;
774        let pair_words = index.len().checked_mul(key_width + value_width)?;
775        body.get(..pair_words)?;
776        Some(Self {
777            index,
778            body,
779            len: index.len(),
780            key_width,
781            value_width,
782            total_words: body_offset.checked_add(pair_words)?,
783        })
784    }
785
786    #[inline(always)]
787    pub fn detect_len(words: &'a [u32]) -> Option<usize> {
788        let head = *words.first()?;
789        let key_width = ((head >> 30) & 3) as usize;
790        let value_width = ((head >> 28) & 3) as usize;
791        if key_width == 0 || value_width == 0 {
792            return None;
793        }
794        let index = PerfectHashView::new(bytes_of_words(words)).ok()?;
795        word_size(index.data_size()).checked_add(index.len().checked_mul(key_width + value_width)?)
796    }
797
798    #[inline(always)]
799    pub fn detect(words: &'a [u32]) -> Option<&'a [u32]> {
800        words.get(..Self::detect_len(words)?)
801    }
802
803    #[inline(always)]
804    pub fn len(self) -> usize {
805        self.len
806    }
807
808    #[inline(always)]
809    pub fn is_empty(self) -> bool {
810        self.len == 0
811    }
812
813    #[inline(always)]
814    pub(crate) fn total_words(self) -> usize {
815        self.total_words
816    }
817
818    #[inline(always)]
819    pub fn pair(self, index: usize) -> Option<PairView<'a>> {
820        if index >= self.len {
821            return None;
822        }
823        let width = self.key_width + self.value_width;
824        let start = index.checked_mul(width)?;
825        Some(PairView {
826            tail: self.body.get(start..)?,
827            key_width: self.key_width,
828            value_width: self.value_width,
829        })
830    }
831
832    #[inline(always)]
833    pub fn expect_pair(self, index: usize) -> PairView<'a> {
834        let width = self.key_width + self.value_width;
835        let start = index * width;
836        PairView {
837            tail: &self.body[start..],
838            key_width: self.key_width,
839            value_width: self.value_width,
840        }
841    }
842
843    #[inline(always)]
844    pub fn iter(self) -> MapIter<'a> {
845        MapIter {
846            map: self,
847            index: 0,
848        }
849    }
850
851    #[inline(always)]
852    pub fn find_bytes(self, key: &[u8]) -> Option<PairView<'a>> {
853        let pos = self.index.locate(key)?;
854        let pair = self.pair(pos)?;
855        if pair.key().string()?.as_bytes() == key {
856            Some(pair)
857        } else {
858            None
859        }
860    }
861
862    #[inline(always)]
863    pub fn find_str(self, key: &str) -> Option<PairView<'a>> {
864        self.find_bytes(key.as_bytes())
865    }
866
867    #[inline(always)]
868    pub fn find_scalar<K: MapKey + Scalar + PartialEq>(self, key: K) -> Option<PairView<'a>> {
869        let key_bytes = key.as_key_bytes();
870        let pos = self.index.locate(&key_bytes)?;
871        let pair = self.pair(pos)?;
872        if pair.key().scalar::<K>()? == key {
873            Some(pair)
874        } else {
875            None
876        }
877    }
878}
879
880pub struct MapIter<'a> {
881    map: MapView<'a>,
882    index: usize,
883}
884
885impl<'a> Iterator for MapIter<'a> {
886    type Item = PairView<'a>;
887
888    #[inline(always)]
889    fn next(&mut self) -> Option<Self::Item> {
890        let item = self.map.pair(self.index)?;
891        self.index += 1;
892        Some(item)
893    }
894
895    #[inline(always)]
896    fn size_hint(&self) -> (usize, Option<usize>) {
897        let remaining = self.map.len.saturating_sub(self.index);
898        (remaining, Some(remaining))
899    }
900}
901
902impl ExactSizeIterator for MapIter<'_> {}
903impl core::iter::FusedIterator for MapIter<'_> {}
904
905pub struct ViewMap<'a, K, V> {
906    map: MapView<'a>,
907    _key: PhantomData<K>,
908    _value: PhantomData<V>,
909}
910
911impl<'a, K, V> Copy for ViewMap<'a, K, V> {}
912
913impl<'a, K, V> Clone for ViewMap<'a, K, V> {
914    fn clone(&self) -> Self {
915        *self
916    }
917}
918
919impl<'a, K: FieldDecode<'a>, V: FieldDecode<'a>> ViewMap<'a, K, V> {
920    #[inline(always)]
921    pub fn new(map: MapView<'a>) -> Self {
922        Self {
923            map,
924            _key: PhantomData,
925            _value: PhantomData,
926        }
927    }
928
929    #[inline(always)]
930    pub fn len(&self) -> usize {
931        self.map.len()
932    }
933
934    #[inline(always)]
935    pub fn is_empty(&self) -> bool {
936        self.map.is_empty()
937    }
938
939    #[inline(always)]
940    pub fn get(&self, index: usize) -> Option<(K, V)> {
941        let pair = self.map.pair(index)?;
942        Some((K::decode(pair.key())?, V::decode(pair.value())?))
943    }
944
945    #[inline(always)]
946    pub fn iter(&self) -> ViewMapIter<'a, K, V> {
947        ViewMapIter {
948            map: *self,
949            index: 0,
950        }
951    }
952
953    #[inline(always)]
954    pub fn raw(&self) -> MapView<'a> {
955        self.map
956    }
957}
958
959impl<'a, V: FieldDecode<'a>> ViewMap<'a, StringView<'a>, V> {
960    #[inline(always)]
961    pub fn find_str(&self, key: &str) -> Option<(StringView<'a>, V)> {
962        let pair = self.map.find_str(key)?;
963        Some((StringView::decode(pair.key())?, V::decode(pair.value())?))
964    }
965}
966
967impl<'a, K: FieldDecode<'a> + MapKey + Scalar + PartialEq, V: FieldDecode<'a>> ViewMap<'a, K, V> {
968    #[inline(always)]
969    pub fn find_scalar(&self, key: K) -> Option<(K, V)> {
970        let pair = self.map.find_scalar(key)?;
971        Some((K::decode(pair.key())?, V::decode(pair.value())?))
972    }
973}
974
975pub struct ViewMapIter<'a, K, V> {
976    map: ViewMap<'a, K, V>,
977    index: usize,
978}
979
980impl<'a, K: FieldDecode<'a>, V: FieldDecode<'a>> Iterator for ViewMapIter<'a, K, V> {
981    type Item = (K, V);
982
983    #[inline(always)]
984    fn next(&mut self) -> Option<Self::Item> {
985        let value = self.map.get(self.index)?;
986        self.index += 1;
987        Some(value)
988    }
989
990    #[inline(always)]
991    fn size_hint(&self) -> (usize, Option<usize>) {
992        let remaining = self.map.len().saturating_sub(self.index);
993        (remaining, Some(remaining))
994    }
995}
996
997impl<'a, K: FieldDecode<'a>, V: FieldDecode<'a>> ExactSizeIterator for ViewMapIter<'a, K, V> {}
998impl<'a, K: FieldDecode<'a>, V: FieldDecode<'a>> core::iter::FusedIterator
999    for ViewMapIter<'a, K, V>
1000{
1001}
1002
1003impl<'a> IntoIterator for BoolArray<'a> {
1004    type Item = bool;
1005    type IntoIter = core::iter::Map<core::iter::Copied<core::slice::Iter<'a, u8>>, fn(u8) -> bool>;
1006
1007    #[inline(always)]
1008    fn into_iter(self) -> Self::IntoIter {
1009        fn as_bool(value: u8) -> bool {
1010            value != 0
1011        }
1012
1013        self.bytes.iter().copied().map(as_bool)
1014    }
1015}
1016
1017impl<'a, T: Scalar> IntoIterator for ScalarArray<'a, T> {
1018    type Item = T;
1019    type IntoIter = ScalarArrayIter<'a, T>;
1020
1021    #[inline(always)]
1022    fn into_iter(self) -> Self::IntoIter {
1023        self.iter()
1024    }
1025}
1026
1027impl<'a, T: FieldDecode<'a>> IntoIterator for ViewArray<'a, T> {
1028    type Item = T;
1029    type IntoIter = ViewArrayIter<'a, T>;
1030
1031    #[inline(always)]
1032    fn into_iter(self) -> Self::IntoIter {
1033        self.iter()
1034    }
1035}
1036
1037impl<'a, K: FieldDecode<'a>, V: FieldDecode<'a>> IntoIterator for ViewMap<'a, K, V> {
1038    type Item = (K, V);
1039    type IntoIter = ViewMapIter<'a, K, V>;
1040
1041    #[inline(always)]
1042    fn into_iter(self) -> Self::IntoIter {
1043        self.iter()
1044    }
1045}
1046
1047impl<'a> FieldDecode<'a> for StringView<'a> {
1048    fn decode(field: FieldView<'a>) -> Option<Self> {
1049        field.string()
1050    }
1051}
1052
1053impl<'a> FieldDecode<'a> for MessageView<'a> {
1054    fn decode(field: FieldView<'a>) -> Option<Self> {
1055        field.message()
1056    }
1057}
1058
1059impl<'a> FieldDecode<'a> for ArrayView<'a> {
1060    fn decode(field: FieldView<'a>) -> Option<Self> {
1061        field.array()
1062    }
1063}
1064
1065impl<'a> FieldDecode<'a> for MapView<'a> {
1066    fn decode(field: FieldView<'a>) -> Option<Self> {
1067        field.map()
1068    }
1069}
1070
1071#[inline(always)]
1072pub fn detect_slice_end(words: &[u32], detected: &[u32], end: &mut usize) -> Option<()> {
1073    *end = (*end).max(checked_slice_end(words, detected)?);
1074    Some(())
1075}
1076
1077#[inline(always)]
1078pub(crate) fn checked_slice_end(words: &[u32], detected: &[u32]) -> Option<usize> {
1079    let word_size = core::mem::size_of::<u32>();
1080    let words_start = words.as_ptr().addr();
1081    let words_end = words_start.checked_add(words.len().checked_mul(word_size)?)?;
1082    let detected_start = detected.as_ptr().addr();
1083    let detected_end = detected_start.checked_add(detected.len().checked_mul(word_size)?)?;
1084
1085    if detected_start < words_start || detected_end > words_end {
1086        return None;
1087    }
1088
1089    let byte_offset = detected_start.checked_sub(words_start)?;
1090    if !byte_offset.is_multiple_of(word_size) {
1091        return None;
1092    }
1093    byte_offset
1094        .checked_div(word_size)?
1095        .checked_add(detected.len())
1096}
1097
1098#[inline(always)]
1099pub fn detect_array_with<'a>(
1100    words: &'a [u32],
1101    mut detect: impl FnMut(FieldView<'a>) -> Option<&'a [u32]>,
1102) -> Option<&'a [u32]> {
1103    let array = ArrayView::new(words)?;
1104    let end = array.total_words();
1105    for index in (0..array.len()).rev() {
1106        let detected = detect(array.expect_field(index))?;
1107        let detected_end = checked_slice_end(words, detected)?;
1108        if detected_end > end {
1109            return words.get(..detected_end);
1110        }
1111    }
1112    words.get(..end)
1113}
1114
1115#[inline(always)]
1116pub fn detect_map_with<'a>(
1117    words: &'a [u32],
1118    mut detect_key: impl FnMut(FieldView<'a>) -> Option<&'a [u32]>,
1119    mut detect_value: impl FnMut(FieldView<'a>) -> Option<&'a [u32]>,
1120) -> Option<&'a [u32]> {
1121    let map = MapView::new(words)?;
1122    let end = map.total_words();
1123    for index in (0..map.len()).rev() {
1124        let pair = map.expect_pair(index);
1125        let detected = detect_value(pair.value())?;
1126        let detected_end = checked_slice_end(words, detected)?;
1127        if detected_end > end {
1128            return words.get(..detected_end);
1129        }
1130
1131        let detected = detect_key(pair.key())?;
1132        let detected_end = checked_slice_end(words, detected)?;
1133        if detected_end > end {
1134            return words.get(..detected_end);
1135        }
1136    }
1137    words.get(..end)
1138}
1139
1140#[inline(always)]
1141fn bytes_of_words(words: &[u32]) -> &[u8] {
1142    // u8 alignment is 1, so viewing the word buffer as bytes is safe.
1143    unsafe { core::slice::from_raw_parts(words.as_ptr().cast::<u8>(), words.len() * 4) }
1144}
1145
1146#[inline(always)]
1147fn count32(v: u32) -> usize {
1148    ((v & 0xaaaa_aaaa).count_ones() + v.count_ones()) as usize
1149}
1150
1151#[inline(always)]
1152fn count64(v: u64) -> usize {
1153    ((v & 0xaaaa_aaaa_aaaa_aaaa).count_ones() + v.count_ones()) as usize
1154}