use regions::Initialize as _;
pub(in crate::buffer::resident) mod exact;
pub(in crate::buffer::resident) mod state;
use std::ops;
use storage::{backing, provided, range, regions};
use crate::{
buffer,
buffer::{
bytes::bounded,
resident,
resident::copy,
storage,
write::{consume, consume::Consume},
},
mem::rc,
};
#[derive(Debug)]
#[repr(C)]
pub struct Shared<'d> {
pub(in crate::buffer) region: regions::Shared<resident::State<'d>>,
}
impl<'d> Default for Shared<'d> {
fn default() -> Self {
Self::new()
}
}
impl<'d> Shared<'d> {
pub const fn new() -> Self {
Self {
region: regions::Shared::empty(resident::State::Slice),
}
}
pub fn try_copy(
source: &impl bounded::Source,
budget: &resident::Budget<'d>,
) -> Result<Self, copy::Error> {
let Some(source) = buffer::raw::Slices::from_source(source) else {
return Ok(Self::new());
};
Ok(source
.try_init::<resident::Budget<'d>>(*budget)?
.into_buf()
.into())
}
pub fn as_slice(&self) -> &[u8] {
self.region.as_slice()
}
pub fn get(&self, range: ops::Range<usize>) -> Option<buffer::View<'_, Self>> {
Some(buffer::View {
source: self,
bytes: self.as_slice().get(range)?,
})
}
#[doc(hidden)]
pub fn backing(&self) -> Option<backing::View<'_, 'd>> {
backing::View::new(&self.region)
}
pub fn clear(&mut self) {
*self = Self::new();
}
pub fn project(
self,
visible: ops::Range<usize>,
) -> Result<Self, crate::mem::Rejected<Self, range::Error>> {
buffer::raw::Slice::try_project(self, visible)
}
pub fn try_detach(self) -> Result<storage::Shared, Self> {
self.region.try_detach().map_err(|region| Self { region })
}
pub fn try_owned(self) -> Result<storage::Shared, Self> {
self.region.try_own().map_err(|region| Self { region })
}
pub fn scope(&self) -> Option<&Self> {
use resident::State;
match self.region.owner() {
State::Owned(_) | State::Borrowed(_) => None,
State::Slice if self.region.is_empty() => None,
State::Slice | State::Resident(_) | State::Accounted(_) | State::Provided(_) => {
Some(self)
}
}
}
pub fn try_clone(&self) -> Result<Self, rc::Error> {
Ok(Self {
region: self.region.try_clone()?,
})
}
pub(in crate::buffer) fn try_share(
view: regions::NonEmpty<'_, '_, Self>,
) -> Result<Self, rc::Error> {
let view = view.view();
Ok(Self {
region: unsafe { view.source.region.try_view(view.as_slice())? },
})
}
}
unsafe impl buffer::raw::Source for Shared<'_> {}
impl buffer::Residency for Shared<'_> {
#[inline]
fn resident(&self) -> usize {
use backing::Owner as _;
self.region.owner().root().map_or(0, backing::Root::bytes)
}
}
impl Consume for Shared<'_> {
fn remaining(&self) -> usize {
self.region.len()
}
fn try_consume(&mut self, amount: usize) -> Result<(), consume::Error> {
buffer::raw::Selection::try_new(self, amount).map(buffer::raw::Selection::consume)
}
fn consume_max(&mut self, max: usize) -> usize {
buffer::raw::Store::advance_max(self, max)
}
}
impl AsRef<[u8]> for Shared<'_> {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl ops::Deref for Shared<'_> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.region
}
}
impl<'d> From<bounded::Value<storage::Shared<Option<provided::Account<'d>>>>> for Shared<'d> {
fn from(bytes: bounded::Value<storage::Shared<Option<provided::Account<'d>>>>) -> Self {
bytes.0.into()
}
}
const _: () = {
assert!(size_of::<Shared<'static>>() == 4 * size_of::<usize>());
assert!(size_of::<Option<Shared<'static>>>() == 4 * size_of::<usize>());
};
const _: () = {
assert!(
size_of::<crate::buffer::raw::Consumed<'static, 'static, Shared<'static>, 8>>()
== 2 * size_of::<usize>()
);
assert!(
size_of::<Option<crate::buffer::raw::Consumed<'static, 'static, Shared<'static>, 8>>>()
== 2 * size_of::<usize>()
);
};
unsafe impl buffer::raw::Store for Shared<'_> {
fn empty() -> Option<Self> {
Some(Self::new())
}
fn restrict(slice: buffer::raw::Slice<'_, '_, Self>) {
let (target, range) = slice.into_parts();
unsafe { target.region.restrict(range.into_inner()) };
}
}