#[cfg(feature = "doc")]
use crate::{scope, scope_ref};
use {
crate::{
index::{Index, IndexError, Range},
proof::{Id, NonEmpty, Unknown},
traits::{Idx, TrustedContainer, TrustedItem},
},
core::{fmt, ops},
};
#[repr(transparent)]
pub struct Container<'id, Array: TrustedContainer + ?Sized> {
#[allow(unused)]
id: Id<'id>,
array: Array,
}
impl<'id, Array: TrustedContainer> Container<'id, Array> {
pub(crate) unsafe fn new(array: Array) -> Self {
Container {
id: Id::default(),
array,
}
}
}
impl<'id, Array: TrustedContainer + ?Sized> Container<'id, &Array> {
pub fn project(&self) -> &Container<'id, Array> {
unsafe { &*(self.array as *const Array as *const Container<'id, Array>) }
}
}
impl<'id, Array: TrustedContainer + ?Sized> Container<'id, Array> {
pub fn untrusted(&self) -> &Array {
&self.array
}
pub fn unit_len(&self) -> usize {
self.array.unit_len()
}
pub fn start<I: Idx>(&self) -> Index<'id, I, Unknown> {
unsafe { Index::new(I::zero()) }
}
pub fn end<I: Idx>(&self) -> Index<'id, I, Unknown> {
let len = I::from_usize(self.unit_len()).expect("len");
unsafe { Index::new(len) }
}
pub fn empty_range<I: Idx>(&self) -> Range<'id, I, Unknown> {
Range::from(self.start(), self.start())
}
pub fn range<I: Idx>(&self) -> Range<'id, I, Unknown> {
Range::from(self.start(), self.end())
}
pub fn vet<I: Idx>(&self, idx: I) -> Result<Index<'id, I, NonEmpty>, IndexError> {
let item = TrustedItem::vet(idx, self)?;
if item < self.end() {
unsafe { Ok(Index::new_nonempty(item.untrusted())) }
} else {
Err(IndexError::OutOfBounds)
}
}
pub fn vet_range<I: Idx>(
&self,
r: ops::Range<I>,
) -> Result<Range<'id, I, Unknown>, IndexError> {
Ok(Range::from(
TrustedItem::vet(r.start, self)?,
TrustedItem::vet(r.end, self)?,
))
}
pub fn split_at<I: Idx, P>(
&self,
idx: Index<'id, I, P>,
) -> (Range<'id, I, Unknown>, Range<'id, I, P>) {
(Range::from(self.start(), idx), unsafe {
Range::new_any(idx.untrusted(), self.end().untrusted())
})
}
pub fn split_after<I: Idx>(
&self,
idx: Index<'id, I, NonEmpty>,
) -> (Range<'id, I, NonEmpty>, Range<'id, I, Unknown>) {
let mid = TrustedItem::after(idx, self);
(
unsafe { Range::new_nonempty(I::zero(), mid.untrusted()) },
Range::from(mid, self.end()),
)
}
pub fn split_around<I: Idx, P>(
&self,
r: Range<'id, I, P>,
) -> (Range<'id, I, Unknown>, Range<'id, I, Unknown>) {
(
Range::from(self.start(), r.start()),
Range::from(r.end(), self.end()),
)
}
pub fn before<I: Idx, P>(&self, idx: Index<'id, I, P>) -> Range<'id, I, Unknown> {
Range::from(self.start(), idx)
}
pub fn after<I: Idx>(&self, idx: Index<'id, I, NonEmpty>) -> Range<'id, I, Unknown> {
let after = TrustedItem::after(idx, self);
Range::from(after, self.end())
}
pub fn advance<I: Idx>(&self, idx: Index<'id, I, NonEmpty>) -> Option<Index<'id, I, NonEmpty>> {
TrustedItem::advance(idx, self)
}
pub fn advance_by<I: Idx, P>(
&self,
idx: Index<'id, I, P>,
offset: usize,
) -> Result<Index<'id, I, NonEmpty>, IndexError> {
self.vet(idx.untrusted().add(offset))
}
pub fn decrease_by<I: Idx, P>(
&self,
idx: Index<'id, I, P>,
offset: usize,
) -> Result<Index<'id, I, NonEmpty>, IndexError> {
if idx.untrusted().as_usize() >= offset {
self.vet(idx.untrusted().sub(offset))
} else {
Err(IndexError::OutOfBounds)
}
}
}
impl<'id, Array: TrustedContainer + ?Sized, I: Idx> ops::Index<Index<'id, I, NonEmpty>>
for Container<'id, Array>
{
type Output = Array::Item;
fn index(&self, index: Index<'id, I, NonEmpty>) -> &Self::Output {
unsafe { self.array.get_unchecked(index.untrusted().as_usize()) }
}
}
impl<'id, Array: TrustedContainer + ?Sized, I: Idx, P> ops::Index<Range<'id, I, P>>
for Container<'id, Array>
{
type Output = Array::Slice;
fn index(&self, r: Range<'id, I, P>) -> &Self::Output {
unsafe {
self.array
.slice_unchecked(r.start().untrusted().as_usize()..r.end().untrusted().as_usize())
}
}
}
impl<'id, Array: TrustedContainer + ?Sized, I: Idx, P> ops::Index<ops::RangeFrom<Index<'id, I, P>>>
for Container<'id, Array>
{
type Output = Array::Slice;
fn index(&self, r: ops::RangeFrom<Index<'id, I, P>>) -> &Self::Output {
&self[Range::from(r.start, self.end())]
}
}
impl<'id, Array: TrustedContainer + ?Sized, I: Idx, P> ops::Index<ops::RangeTo<Index<'id, I, P>>>
for Container<'id, Array>
{
type Output = Array::Slice;
fn index(&self, r: ops::RangeTo<Index<'id, I, P>>) -> &Self::Output {
&self[Range::from(self.start(), r.end)]
}
}
impl<'id, Array: TrustedContainer + ?Sized> ops::Index<ops::RangeFull> for Container<'id, Array> {
type Output = Array::Slice;
fn index(&self, _: ops::RangeFull) -> &Self::Output {
&self[Range::<usize, _>::from(self.start(), self.end())]
}
}
impl<'id, Array: TrustedContainer + Copy> Copy for Container<'id, Array> {}
impl<'id, Array: TrustedContainer + Clone> Clone for Container<'id, Array> {
fn clone(&self) -> Self {
unsafe { Container::new(self.array.clone()) }
}
}
impl<'id, Array: TrustedContainer + fmt::Debug + ?Sized> fmt::Debug for Container<'id, Array> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Container<'id>").field(&&self.array).finish()
}
}