use std::{mem::MaybeUninit, num::NonZero, ops};
use provided::account;
use crate::{
base::num::bounded::U32,
buffer,
buffer::{
bytes::bounded,
hold, resident, storage,
storage::{provided, range},
write::consume,
},
mem::rc,
};
#[derive(Debug)]
#[repr(transparent)]
pub struct Value<T>(pub(in crate::buffer) T);
impl<const N: usize> Value<[u8; N]> {
pub const fn new(value: [u8; N]) -> Self {
const { assert!(N <= bounded::MAX) };
Self(value)
}
}
impl<T: buffer::raw::Source> Value<T> {
pub fn try_new(value: T) -> Result<Self, bounded::Rejected<T>> {
if U32::<0, { bounded::MAX as u32 }>::try_usize(value.as_ref().len()).is_err() {
return Err(bounded::Rejected::new(value));
}
Ok(Self(value))
}
}
impl<'a> TryFrom<&'a mut [MaybeUninit<u8>]> for Value<&'a mut [MaybeUninit<u8>]> {
type Error = bounded::Overflow;
fn try_from(value: &'a mut [MaybeUninit<u8>]) -> Result<Self, Self::Error> {
U32::<0, { bounded::MAX as u32 }>::try_usize(value.len())?;
Ok(Self(value))
}
}
impl<'d> Value<provided::Unique<'d>> {
pub fn try_take(
&mut self,
amount: NonZero<usize>,
) -> Result<Value<provided::Prefix<'_, 'd>>, consume::Error> {
Ok(Value(self.0.try_take(amount)?))
}
}
impl<T: buffer::raw::Mutable> AsMut<[u8]> for Value<T> {
fn as_mut(&mut self) -> &mut [u8] {
self.0.as_mut()
}
}
impl<'d> From<Value<provided::Unique<'d>>> for Value<storage::Shared<provided::Owner<'d>>> {
fn from(bytes: Value<provided::Unique<'d>>) -> Self {
Value(bytes.0.into_shared())
}
}
impl<T> Value<T> {
pub fn into_storage<U>(self) -> Value<U>
where
T: buffer::raw::Convert<U>,
{
Value(buffer::raw::Convert::into(self.0))
}
pub fn from_raw(proof: bounded::raw::Input<T>) -> Self {
Self(proof.into_inner())
}
#[must_use]
pub fn into_inner(self) -> T {
self.0
}
}
const _: () = assert!(size_of::<Value<[u8; 1]>>() == 1);
impl<T: AsRef<[u8]>> AsRef<[u8]> for Value<T> {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl<T: AsRef<[u8]>> From<&Value<T>> for U32<0, { bounded::MAX as u32 }> {
fn from(bytes: &Value<T>) -> Self {
bounded::raw::Input::count(bytes)
}
}
impl<T: buffer::Residency> buffer::Residency for Value<T> {
fn resident(&self) -> usize {
self.0.resident()
}
}
impl<'d> provided::Frozen<'d> for Value<storage::Shared<provided::Owner<'d>>> {
type Account = Value<storage::Shared<Option<provided::Account<'d>>>>;
fn try_account(&self, budget: &resident::Budget<'d>) -> Result<Self::Account, account::Cause> {
Ok(Value(self.0.try_account(budget)?))
}
}
impl<'d> Value<storage::Shared<provided::Owner<'d>>> {
pub fn try_get(
&self,
range: ops::Range<usize>,
budget: &resident::Budget<'d>,
) -> Result<Value<storage::Shared<Option<provided::Account<'d>>>>, account::Error> {
Ok(Value(self.0.try_get(range, budget)?))
}
}
impl<'a, T: buffer::Read<'a>> buffer::Read<'a> for Value<T>
where
Self: bounded::Source,
{
fn as_slice(&self) -> &'a [u8] {
self.0.as_slice()
}
fn try_split<const N: usize>(self) -> Result<(&'a [u8; N], Self), consume::Error> {
let (head, tail) = self.0.try_split()?;
Ok((head, Self(tail)))
}
}
impl<T: buffer::raw::Store + buffer::raw::Source> consume::Consume for Value<T> {
fn remaining(&self) -> usize {
self.0.as_ref().len()
}
fn try_consume(&mut self, amount: usize) -> Result<(), consume::Error> {
buffer::raw::Selection::try_new(&mut self.0, amount).map(buffer::raw::Selection::consume)
}
fn consume_max(&mut self, max: usize) -> usize {
buffer::raw::Store::advance_max(&mut self.0, max)
}
}
impl Default for Value<storage::Shared<Option<provided::Account<'_>>>> {
fn default() -> Self {
Value(storage::Shared::<Option<provided::Account<'_>>>::new())
}
}
impl<'d> Value<storage::Shared<Option<provided::Account<'d>>>> {
pub fn try_clone(&self) -> Result<Self, rc::Error> {
Ok(Value(self.0.try_clone()?))
}
pub fn project(
self,
range: ops::Range<usize>,
) -> Result<Self, crate::mem::Rejected<Self, range::Error>> {
match self.0.project(range) {
Ok(value) => Ok(Value(value)),
Err(error) => Err(error.map(Value)),
}
}
}
impl Value<&[u8]> {
pub fn try_get(&self, range: ops::Range<usize>) -> Result<Self, range::Error> {
use buffer::Cursor as _;
Ok(Value(self.0.try_get(range)?))
}
}
impl bounded::Source for Value<&[u8]> {}
const _: () = {
assert!(size_of::<Value<&[u8]>>() == 2 * size_of::<usize>());
assert!(
size_of::<Value<storage::Shared<Option<provided::Account<'static>>>>>()
== 3 * size_of::<usize>()
);
assert!(
size_of::<Option<Value<storage::Shared<Option<provided::Account<'static>>>>>>()
== 3 * size_of::<usize>()
);
};
impl<O: Unpin> buffer::Source for Value<storage::Shared<O>> {
type View<'input>
= Value<buffer::View<'input, storage::Shared<O>>>
where
Self: 'input;
fn remaining(&self) -> usize {
self.0.as_ref().len()
}
}
unsafe impl<'d> hold::raw::Retain<'d> for Value<storage::Shared<provided::Owner<'d>>> {
fn charge<'a>(plan: &Self::View<'a>) -> hold::Charge
where
Self: 'a,
{
<storage::Shared<provided::Owner<'d>> as hold::raw::Retain<'d>>::charge(&plan.0)
}
fn try_copy<'a>(
plan: &Self::View<'a>,
budget: &resident::Budget<'d>,
) -> Result<storage::Owned<resident::Budget<'d>>, hold::Error>
where
Self: 'a,
{
Ok(storage::Owned::try_copy(plan, budget)?)
}
fn try_retain<'a>(
plan: &Self::View<'a>,
budget: &resident::Budget<'d>,
) -> Result<hold::Retained<'d>, hold::Error>
where
Self: 'a,
{
<storage::Shared<provided::Owner<'d>> as hold::raw::Retain<'d>>::try_retain(&plan.0, budget)
}
}
impl<'a, 'd> provided::Mutable<'d> for Value<provided::Prefix<'a, 'd>> {
type Account = Value<storage::Shared<Option<provided::Account<'d>>>>;
type Frozen = Value<provided::Prefix<'a, 'd, &'a [u8]>>;
type Prefix<'b>
= Value<provided::Prefix<'a, 'd>>
where
Self: 'b;
fn try_take(&mut self, amount: NonZero<usize>) -> Result<Self::Prefix<'_>, consume::Error> {
Ok(Self(self.0.try_take(amount)?))
}
}
impl<'a, 'd> provided::Frozen<'d> for Value<provided::Prefix<'a, 'd, &'a [u8]>> {
type Account = Value<storage::Shared<Option<provided::Account<'d>>>>;
fn try_account(
&self,
budget: &resident::Budget<'d>,
) -> Result<bounded::Value<storage::Shared<Option<provided::Account<'d>>>>, account::Cause>
{
Ok(bounded::Value(self.0.try_account(budget)?))
}
}
const _: () = {
assert!(size_of::<Value<provided::Prefix<'static, 'static>>>() == 3 * size_of::<usize>());
assert!(
size_of::<Option<Value<provided::Prefix<'static, 'static>>>>() == 3 * size_of::<usize>()
);
assert!(
size_of::<Value<provided::Prefix<'static, 'static, &[u8]>>>() == 3 * size_of::<usize>()
);
assert!(
size_of::<Result<Value<provided::Prefix<'static, 'static>>, consume::Error>>()
== 3 * size_of::<usize>()
);
};
impl<'a, 'd> From<Value<provided::Prefix<'a, 'd>>> for Value<provided::Prefix<'a, 'd, &'a [u8]>> {
fn from(prefix: Value<provided::Prefix<'a, 'd>>) -> Self {
Value(prefix.0.into())
}
}
impl<'a, S: ?Sized> Value<buffer::View<'a, S>> {
pub fn try_get(&self, range: ops::Range<usize>) -> Result<Self, range::Error> {
Ok(Self(self.0.try_get(range)?))
}
}
impl<S: ?Sized> bounded::Source for Value<buffer::View<'_, S>> {}
impl<S: ?Sized> Clone for Value<buffer::View<'_, S>> {
fn clone(&self) -> Self {
Self(self.0)
}
}
impl<'d> Value<buffer::View<'_, storage::Shared<Option<provided::Account<'d>>>>> {
pub fn try_retain(
self,
) -> Result<bounded::Value<storage::Shared<Option<provided::Account<'d>>>>, rc::Error> {
Ok(bounded::Value(self.0.try_retain()?))
}
}
const _: () = {
assert!(
size_of::<Value<buffer::View<'static, storage::Shared<provided::Owner<'static>>>>>()
== 3 * size_of::<usize>()
);
assert!(
size_of::<Option<Value<buffer::View<'static, storage::Shared<provided::Owner<'static>>>>>>(
) == 3 * size_of::<usize>()
);
};
impl<'d> buffer::Source for Value<provided::Unique<'d>> {
type View<'input>
= Value<&'input [u8]>
where
Self: 'input;
fn remaining(&self) -> usize {
self.0.as_ref().len()
}
}
impl<'d> buffer::Cursor for Value<provided::Unique<'d>> {
fn try_get<'input>(
&'input self,
range: ops::Range<usize>,
) -> Result<Self::View<'input>, range::Error> {
Ok(Value(buffer::Cursor::try_get(self.0.as_ref(), range)?))
}
}
impl<'d> buffer::Complete for Value<provided::Unique<'d>> {
fn view(&self) -> Self::View<'_> {
Value(self.0.as_ref())
}
}
impl<O: Unpin> buffer::Cursor for Value<storage::Shared<O>> {
fn try_get<'input>(
&'input self,
range: ops::Range<usize>,
) -> Result<Self::View<'input>, range::Error> {
Ok(Value(buffer::View::new(&self.0).try_get(range)?))
}
}
impl<O: Unpin> buffer::Complete for Value<storage::Shared<O>> {
fn view(&self) -> Self::View<'_> {
Value(buffer::View::new(&self.0))
}
}
unsafe impl<T: buffer::raw::Consume> buffer::raw::Consume for Value<T> {
fn consume<const MAX: u32>(prefix: buffer::raw::Consumed<'_, '_, Self, MAX>) {
prefix.consume::<T>();
}
}
unsafe impl<T: buffer::raw::Store> buffer::raw::Store for Value<T> {
fn empty() -> Option<Self> {
T::empty().map(Self)
}
fn restrict(slice: buffer::raw::Slice<'_, '_, Self>) {
let (target, range) = slice.into_parts();
T::restrict(unsafe { buffer::raw::Slice::from_parts(&mut target.0, range) });
}
}