Skip to main content

o3/buffer/bytes/scope/
view.rs

1use std::{marker, num, ops};
2
3use crate::buffer::{bytes::scope, is_within, storage::range, write::consume};
4
5/// A real source borrow carrying its immutable owner's identity.
6#[derive(Clone, Copy)]
7pub struct View<'a, 'id> {
8    pub(in crate::buffer::bytes::scope) bytes: &'a [u8],
9    pub(in crate::buffer::bytes::scope) brand: marker::PhantomData<*mut &'id ()>,
10}
11
12impl<'a, 'id> View<'a, 'id> {
13    pub const fn as_slice(&self) -> &'a [u8] {
14        self.bytes
15    }
16
17    /// Projects an admitted selection from this same immutable source identity.
18    pub fn get<P: scope::raw::Select<'id>>(self, proof: P) -> (&'a [u8], scope::Range<'id>) {
19        let bounds = proof.bounds();
20        // SAFETY: the selection retains this identity's immutable original
21        // extent and its admitted range throughout this operation.
22        let bytes = unsafe { self.bytes.get_unchecked(bounds.clone()) };
23        (bytes, scope::Range::new(self, bounds))
24    }
25
26    pub fn try_get(self, bounds: ops::Range<usize>) -> Result<scope::Range<'id>, range::Error> {
27        if !is_within(&bounds, self.bytes.len()) {
28            return Err(range::Error::new(bounds, self.bytes.len()));
29        }
30        Ok(scope::Range::new(self, bounds))
31    }
32
33    pub fn try_rsplit<const N: usize>(
34        self,
35    ) -> Result<(&'a [u8; N], scope::Range<'id>), consume::Error> {
36        let Some((prefix, tail)) = self.bytes.split_last_chunk::<N>() else {
37            return Err(consume::Error::new(
38                num::NonZero::<usize>::MIN.saturating_add(N.saturating_sub(1)),
39                self.bytes.len(),
40            ));
41        };
42        Ok((tail, scope::Range::new(self, 0..prefix.len())))
43    }
44}
45
46impl<'id> scope::Source for View<'_, 'id> {
47    type Selection = scope::Range<'id>;
48
49    fn select(self, bytes: &[u8]) -> Option<Self::Selection> {
50        Some(scope::Range::new(
51            self,
52            self.bytes.subslice_range(bytes)?.into(),
53        ))
54    }
55}
56
57const _: () = assert!(size_of::<View<'static, 'static>>() == 2 * size_of::<usize>());