#[doc = crate::_tags!(construction data_structure)]
#[doc = crate::_doc_location!("data/layout")]
#[doc = crate::doclink!(custom devela
"[`BufferAllocExample`]" "data/layout/struct.BufferAllocExample.html")]
#[macro_export]
#[cfg_attr(cargo_primary_package, doc(hidden))]
macro_rules! buffer_linear {
(
// STATIC (array, uninit, option)
$(#[$attr:meta])* $vis:vis struct $name:ident : $(static)? ($($I:tt)+); $($rest:tt)* ) => {
$(#[$attr])*
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
$vis struct $name<T, S> {
storage: S,
len: $crate::MaybeNiche<$($I)+>,
_m: $crate::PhantomData<T>,
}
$crate::buffer_linear!(%impl_common_static $name, $($I)+, $crate::niche_prim![$($I)+]);
$crate::buffer_linear!(%impls_static
$name : $($I)+, $crate::niche_prim![$($I)+] ; $($rest)*);
};
( impl $name:ident : $(static)? ($($I:tt)+) ; $($rest:tt)* ) => {
$crate::buffer_linear!(%impls_static
$name : $($I)+, $crate::niche_prim![$($I)+] ; $($rest)*);
};
(
$(#[$attr:meta])* $vis:vis struct $name:ident : view ($($I:tt)+); $($rest:tt)* ) => {
$(#[$attr])*
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
$vis struct $name<'a, T, S> {
storage: S,
len: $crate::MaybeNiche<$($I)+>,
_m: $crate::PhantomData<&'a T>,
}
$crate::buffer_linear!(%impl_common_view $name, $($I)+, $crate::niche_prim![$($I)+]);
$crate::buffer_linear!(%impls_view
$name : $($I)+, $crate::niche_prim![$($I)+] ; $($rest)*);
};
( impl $name:ident : view ($($I:tt)+) ; $($rest:tt)* ) => {
$crate::buffer_linear!(%impls_view
$name : $($I)+, $crate::niche_prim![$($I)+] ; $($rest)*);
};
(
$(#[$attr:meta])* $vis:vis struct $name:ident : alloc ($($I:tt)+); $($rest:tt)* ) => {
$(#[$attr])*
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
$vis struct $name<T, S> {
storage: S,
_m: $crate::PhantomData<T>,
}
$crate::buffer_linear!(%impl_common_alloc $name, $($I)+, $crate::niche_prim![$($I)+]);
$crate::buffer_linear!(%impls_alloc
$name : $($I)+, $crate::niche_prim![$($I)+] ; $($rest)*);
};
( impl $name:ident : alloc ($($I:tt)+) ; $($rest:tt)* ) => {
$crate::buffer_linear!(%impls_alloc
$name : $($I)+, $crate::niche_prim![$($I)+] ; $($rest)*);
};
(
%impls_static $name:ident : $I:ty, $P:ty ;) => {}; (%impls_static $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* $impl:ident) => { $crate::buffer_linear!(%impl1_static $name : $I, $P ; $impl);
};
(%impls_static $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* array , $($rest:tt)*) => {
$crate::__buffer_linear_impl_array!($(#[$i])* $name, $I, $P);
$crate::buffer_linear!(%impls_static $name : $I, $P ; $($rest)*); };
(%impl1_static $(#[$i:meta])* $name:ident : $I:ty, $P:ty; array) => {
$crate::__buffer_linear_impl_array!($(#[$i])* $name, $I, $P); };
(%impls_static $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* uninit , $($rest:tt)*) => {
$crate::__buffer_linear_impl_uninit!($(#[$i])* $name, $I, $P);
$crate::buffer_linear!(%impls_static $name : $I, $P ; $($rest)*); };
(%impl1_static $(#[$i:meta])* $name:ident : $I:ty, $P:ty; uninit) => {
$crate::__buffer_linear_impl_uninit!($(#[$i])* $name, $I, $P); };
(%impls_static $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* option , $($rest:tt)*) => {
$crate::__buffer_linear_impl_option!($(#[$i])* $name, $I, $P);
$crate::buffer_linear!(%impls_static $name : $I, $P ; $($rest)*); };
(%impl1_static $(#[$i:meta])* $name:ident : $I:ty, $P:ty; option) => {
$crate::__buffer_linear_impl_option!($(#[$i])* $name, $I, $P); };
(%impls_view $name:ident : $I:ty, $P:ty ;) => {}; (%impls_view $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* $impl:ident) => { $crate::buffer_linear!(%impl1_view $name : $I, $P ; $impl);
};
(%impls_view $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* slice_mut , $($rest:tt)*) => {
$crate::__buffer_linear_impl_slice_mut!($(#[$i])* $name, $I, $P);
$crate::buffer_linear!(%impls_view $name : $I, $P ; $($rest)*); };
(%impl1_view $(#[$i:meta])* $name:ident : $I:ty, $P:ty ; slice_mut) => {
$crate::__buffer_linear_impl_slice_mut!($(#[$i])* $name, $I, $P); };
(%impls_view $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* slice , $($rest:tt)*) => {
$crate::__buffer_linear_impl_slice!($(#[$i])* $name, $I, $P);
$crate::buffer_linear!(%impls_view $name : $I, $P ; $($rest)*); };
(%impl1_view $(#[$i:meta])* $name:ident : $I:ty, $P:ty ; slice) => {
$crate::__buffer_linear_impl_slice!($(#[$i])* $name, $I, $P); };
(%impls_alloc $name:ident : $I:ty, $P:ty ;) => {}; (%impls_alloc $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* $impl:ident) => { $crate::buffer_linear!(%impl1_alloc $name : $I, $P ; $impl);
};
(%impls_alloc $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* vec , $($rest:tt)*) => {
$crate::__buffer_linear_impl_vec!($(#[$i])* $name, $I, $P);
$crate::buffer_linear!(%impls_alloc $name : $I, $P ; $($rest)*); };
(%impl1_alloc $(#[$i:meta])* $name:ident : $I:ty, $P:ty; vec) => {
$crate::__buffer_linear_impl_vec!($(#[$i])* $name, $I, $P); };
(%impls_static $name:ident : $_I:ty, $_P:ty ; $(#[$_i:meta])* $impl:ident , $($_r:tt)*) => {
compile_error!(concat!( "buffer_linear!: unknown static impl `", stringify!($impl), "`"));
};
(%impls_view $name:ident : $_I:ty, $_P:ty ; $(#[$_i:meta])* $impl:ident , $($_r:tt)*) => {
compile_error!(concat!( "buffer_linear!: unknown view impl `", stringify!($impl), "`"));
};
(%impls_alloc $name:ident : $_I:ty, $_P:ty ; $(#[$_i:meta])* $impl:ident , $($_r:tt)*) => {
compile_error!(concat!( "buffer_linear!: unknown alloc impl `", stringify!($impl), "`"));
};
(%impl_common_static $name:ident, $I:ty, $P:ty) => {
impl<T, S> $name<T, S> {
$crate::buffer_linear!(%common_tracked $name, $I, $P);
}
};
(%impl_common_view $name:ident, $I:ty, $P:ty) => {
impl<'a, T, S> $name<'a, T, S> {
$crate::buffer_linear!(%common_tracked $name, $I, $P);
}
};
(%impl_common_alloc $name:ident, $I:ty, $P:ty) => {
impl<T, S> $name<T, S> {
$crate::buffer_linear!(%common_delegated $name, $I, $P);
}
};
(%common_tracked $name:ident, $I:ty, $P:ty) => {
#[inline(always)]
const fn _new(storage: S, len: $crate::MaybeNiche<$I>) -> Self {
Self { storage, len, _m: $crate::PhantomData }
}
#[inline(always)]
const fn _idx_zero() -> $crate::MaybeNiche<$I> {
$crate::unwrap![some $crate::MaybeNiche::<$I>::ZERO]
}
#[inline(always)]
const fn _idx_eq(a: $I, b: $I) -> bool {
let (a, b) = ($crate::MaybeNiche(a).prim(), $crate::MaybeNiche(b).prim()); a == b
}
#[inline(always)]
const fn _idx_le(a: $I, b: $I) -> bool {
let (a, b) = ($crate::MaybeNiche(a).prim(), $crate::MaybeNiche(b).prim()); a <= b
}
#[inline(always)]
const fn _idx_ge(a: $I, b: $I) -> bool {
let (a, b) = ($crate::MaybeNiche(a).prim(), $crate::MaybeNiche(b).prim()); a >= b
}
#[inline(always)]
const fn _idx_to_prim(from: $I) -> $P { $crate::MaybeNiche(from).prim() }
#[inline(always)]
const fn _prim_to_idx(from: $P) -> Result<$I, $crate::InvalidValue> {
$crate::unwrap![ok_map? $crate::MaybeNiche::<$I>::try_from_prim(from), |v| v.repr()]
}
#[inline(always)]
const fn _prim_to_idx_lossy(from: $P) -> $I {
$crate::MaybeNiche::<$I>::from_prim_lossy(from).repr()
}
const _IDX_MAX_USIZE: usize = $crate::MaybeNiche(<$I>::MAX).to_usize_saturating();
#[inline(always)]
const fn _len_usize(&self) -> usize { self.len.to_usize_saturating() }
#[inline(always)]
const fn _usize_to_idx_sat(from: usize) -> $crate::MaybeNiche<$I> {
$crate::MaybeNiche::<$I>::from_usize_saturating(from)
}
#[inline(always)]
const fn _usize_to_idx(from: usize) -> $crate::MaybeNiche<$I> {
$crate::unwrap![ok $crate::MaybeNiche::<$I>::try_from_usize(from)]
}
#[inline(always)]
const fn _idx_to_usize(from: $I) -> usize {
$crate::unwrap![ok $crate::MaybeNiche(from).try_to_usize()]
}
#[inline(always)]
const fn _set_len(&mut self, len: $I) {
self.len = $crate::MaybeNiche(len);
}
#[inline(always)]
const fn _len_inc(&self) -> $crate::MaybeNiche<$I> {
$crate::unwrap![ok $crate::MaybeNiche::<$I>::try_from_prim(self.len.prim() + 1)]
}
#[inline(always)]
const fn _len_dec(&self) -> $crate::MaybeNiche<$I> {
$crate::unwrap![ok $crate::MaybeNiche::<$I>::try_from_prim(self.len.prim() - 1)]
}
pub const fn len(&self) -> $I { self.len.repr() }
pub const fn len_prim(&self) -> $P { self.len.prim() }
pub const fn is_empty(&self) -> bool { self.len.prim() == 0 }
};
(%common_delegated $name:ident, $I:ty, $P:ty) => {
#[inline(always)]
const fn _new(storage: S) -> Self {
Self { storage, _m: $crate::PhantomData }
}
#[inline(always)]
const fn _prim_to_idx(from: $P) -> Result<$I, $crate::InvalidValue> {
$crate::unwrap![ok_map? $crate::MaybeNiche::<$I>::try_from_prim(from), |v| v.repr()]
}
#[inline(always)]
const fn _prim_to_idx_lossy(from: $P) -> $I {
$crate::MaybeNiche::<$I>::from_prim_lossy(from).repr()
}
#[inline(always)]
const fn _usize_to_idx_sat(from: usize) -> $crate::MaybeNiche<$I> {
$crate::MaybeNiche::<$I>::from_usize_saturating(from)
}
#[inline(always)]
const fn _usize_to_idx(from: usize) -> $crate::MaybeNiche<$I> {
$crate::unwrap![ok $crate::MaybeNiche::<$I>::try_from_usize(from)]
}
#[inline(always)]
const fn _idx_to_usize(from: $I) -> usize {
$crate::unwrap![ok $crate::MaybeNiche(from).try_to_usize()]
}
};
(%common_static $name:ident, $I:ty, $P:ty) => {
const _CHECK_INVARIANTS: () = {
assert!(!$crate::MaybeNiche::<$I>::HAS_NEGATIVE,
"buffer_linear! index type must be non-negative");
assert!($crate::MaybeNiche::<$I>::ZERO.is_some(),
"buffer_linear! index type cannot represent zero");
assert!($crate::MaybeNiche::<$I>::IS_CONTIGUOUS,
"buffer_linear! index type must be contiguous");
assert!($crate::MaybeNiche::<$I>::try_from_usize(CAP).is_ok(),
"buffer_linear! capacity does not fit in index type");
};
pub const CAP: $I = {
let _ = Self::_CHECK_INVARIANTS; Self::_usize_to_idx(CAP).repr()
};
pub const CAP_PRIM: $P = Self::_idx_to_prim(Self::CAP);
pub const fn capacity(&self) -> $I { Self::CAP }
pub const fn capacity_prim(&self) -> $P { Self::CAP_PRIM }
pub const fn remaining_capacity(&self) -> $I {
$crate::unwrap![ok_guaranteed_or_ub Self::_prim_to_idx(self.remaining_capacity_prim())]
}
pub const fn remaining_capacity_prim(&self) -> $P {
self.capacity_prim() - self.len_prim()
}
pub const fn is_full(&self) -> bool { Self::_idx_eq(self.len(), self.capacity()) }
};
(%common_view $name:ident, $I:ty, $P:ty) => {
const _CHECK_INVARIANTS: () = {
assert!(!$crate::MaybeNiche::<$I>::HAS_NEGATIVE,
"buffer_linear! index type must be non-negative");
assert!($crate::MaybeNiche::<$I>::ZERO.is_some(),
"buffer_linear! index type cannot represent zero");
assert!($crate::MaybeNiche::<$I>::IS_CONTIGUOUS,
"buffer_linear! index type must be contiguous");
};
pub const fn capacity(&self) -> $I { Self::_usize_to_idx(self.storage.len()).repr() }
pub const fn capacity_prim(&self) -> $P {
Self::_usize_to_idx(self.storage.len()).prim()
}
pub const fn remaining_capacity(&self) -> $I {
$crate::unwrap![ok_guaranteed_or_ub Self::_prim_to_idx(self.remaining_capacity_prim())]
}
pub const fn remaining_capacity_prim(&self) -> $P {
self.capacity_prim() - self.len_prim()
}
pub const fn is_full(&self) -> bool { Self::_idx_eq(self.len(), self.capacity()) }
};
(%common_iter_visit $name:ident, $I:ty, $P:ty) => {
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.as_slice().iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.as_mut_slice().iter_mut()
}
pub fn visit_each<F>(&self, f: F) where for<'v> F: Fn(&'v T) {
for x in self.as_slice() { f(x); }
}
pub fn visit_each_mut<F>(&mut self, f: F) where for<'v> F: Fn(&'v mut T) {
for x in self.as_mut_slice() { f(x); }
}
pub fn visit_slice<F, R>(&self, f: F)
-> R where for<'v> F: FnOnce(&'v [T]) -> R { f(self.as_slice())
}
pub fn visit_mut_slice<F, R>(&mut self, f: F)
-> R where for<'v> F: FnOnce(&'v mut [T]) -> R { f(self.as_mut_slice())
}
};
}
#[doc(inline)]
pub use crate::buffer_linear;