Skip to main content

o3/buffer/storage/owned/
exact.rs

1use crate::{
2    buffer,
3    buffer::{
4        storage,
5        storage::regions,
6        write::{SpareExt as _, spans},
7    },
8};
9
10/// Lifetime-independent one-word exact allocation owner.
11#[derive(Debug, Default)]
12#[repr(transparent)]
13pub struct Exact {
14    pub(in crate::buffer) inner: Option<regions::Init>,
15}
16
17impl Exact {
18    #[must_use]
19    pub const fn new() -> Self {
20        Self { inner: None }
21    }
22
23    pub fn try_build<E>(
24        capacity: usize,
25        build: impl FnOnce(&mut spans::Writer<'_, '_>) -> Result<(), E>,
26    ) -> Result<Self, storage::BuildError<E>> {
27        use storage::BuildError;
28
29        let mut owned = storage::Owned::try_with(capacity)?;
30        let mut spare = owned.spare();
31        let mut writer = spare.bounded();
32        build(&mut writer).map_err(BuildError::Build)?;
33        writer.commit();
34        spare
35            .try_complete()
36            .map_err(|error| BuildError::Length(error.into()))?;
37        let Some(heap) = owned.allocation else {
38            return Ok(Self::new());
39        };
40        // SAFETY: the original spare completed this owner's entire uninitialized suffix.
41        Ok(Self {
42            inner: Some(unsafe { regions::Init::new(heap) }),
43        })
44    }
45
46    pub fn try_copy(bytes: &[u8]) -> Result<Self, storage::AllocError> {
47        use storage::AllocError;
48
49        let Some(slices) = buffer::raw::Slices::try_new([bytes]).map_err(AllocError::Capacity)?
50        else {
51            return Ok(Self::new());
52        };
53        slices.try_owned().map_err(AllocError::Exhausted)
54    }
55
56    #[must_use]
57    pub fn into_shared(self) -> storage::Shared {
58        match self.inner {
59            Some(inner) => inner.into_buf().into(),
60            None => storage::Shared::new(),
61        }
62    }
63
64    pub fn as_slice(&self) -> &[u8] {
65        self.inner.as_ref().map_or(&[], regions::Init::as_slice)
66    }
67}
68
69impl AsRef<[u8]> for Exact {
70    fn as_ref(&self) -> &[u8] {
71        self.as_slice()
72    }
73}
74
75impl buffer::Residency for Exact {
76    fn resident(&self) -> usize {
77        self.inner
78            .as_ref()
79            .map_or(0, |inner| inner.capacity().get() as usize)
80    }
81}
82
83const _: () = assert!(size_of::<Exact>() == size_of::<usize>());
84
85// SAFETY: the exact owner exposes its complete initialized allocation immutably.
86unsafe impl buffer::raw::Source for Exact {}