o3/buffer/storage/owned/
exact.rs1use crate::{
2 buffer,
3 buffer::{
4 storage,
5 storage::regions,
6 write::{SpareExt as _, spans},
7 },
8};
9
10#[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 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
85unsafe impl buffer::raw::Source for Exact {}