use super::*;
use std::ops::RangeBounds;
#[derive(Clone)]
pub struct VecRef<'a, T: ?Sized> {
borrows: VecRefBorrow<'a>,
value: &'a T,
}
impl<'a, T: ?Sized> VecRef<'a, T> {
pub(crate) fn new(vec: &'a VecCell<T>, index: usize) -> Option<Self>
where
T: Sized
{
if vec.mut_borrow.get() == Some(index) {
return None
}
if index >= vec.len() {
return None
}
Some(Self {
borrows: VecRefBorrow::new(&vec.borrows)?,
value: unsafe {
vec.get_unchecked(index)
}
})
}
pub(crate) fn from_range<R: RangeBounds<usize>>(vec: &'a VecCell<T>, range: R) -> Option<VecRef<'a, [T]>>
where
T: Sized
{
use std::mem::{size_of, align_of};
match vec.mut_borrow() {
Some(index) => {
if range.contains(&index) {
return None;
}
},
None => {}
}
let low = range.start_bound().cloned();
let high = range.end_bound().cloned();
let range: &[UnsafeCell<T>] = &vec.inner[(low, high)];
let range: &[T] = unsafe {
let ptr: *const UnsafeCell<T> = range.as_ptr();
let len = range.len();
assert!(ptr as *const () == UnsafeCell::raw_get(ptr) as *const ());
assert!(size_of::<UnsafeCell<T>>() == size_of::<T>());
assert!(align_of::<UnsafeCell<T>>() == align_of::<T>());
let ptr: *mut T = UnsafeCell::raw_get(ptr);
let ptr = ptr as *const T;
let slice: &[T] = std::slice::from_raw_parts(ptr, len);
slice
};
Some(VecRef {
borrows: VecRefBorrow::new(&vec.borrows)?,
value: range,
})
}
fn from(value: &'a T, borrows: VecRefBorrow<'a>) -> Self {
Self {
borrows,
value
}
}
pub fn map<'b, U: ?Sized, F>(original: VecRef<'b, T>, f: F) -> VecRef<'b, U>
where
F: FnOnce(&T) -> &U
{
VecRef::from(f(original.value), original.borrows.clone())
}
pub fn try_map<'b, U: ?Sized, F, E>(original: VecRef<'b, T>, f: F) -> Result<VecRef<'b, U>, E>
where
F: FnOnce(&T) -> Result<&U, E>
{
Ok(VecRef::from(f(original.value)?, original.borrows.clone()))
}
}
impl<'a, T: Sized> VecRef<'a, [T]> {
pub fn borrow(&self, index: usize) -> Option<VecRef<'a, T>> {
Some(VecRef::from(self.value.get(index)?, self.borrows.clone()))
}
}
impl<'a, T: ?Sized> Deref for VecRef<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'a, T: Debug + ?Sized> Debug for VecRef<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VecRef")
.field(&self.value)
.finish()
}
}
impl<'a, T: Display + ?Sized> Display for VecRef<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as Display>::fmt(&self.value, f)
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq for VecRef<'a, T> {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq<T> for VecRef<'a, T> {
fn eq(&self, other: &T) -> bool {
self.value == other
}
}
struct VecRefBorrow<'a>(&'a Cell<usize>);
impl<'a> VecRefBorrow<'a> {
fn new(cell: &'a Cell<usize>) -> Option<Self> {
cell.set(cell.get().checked_add(1)?);
Some(Self(cell))
}
}
impl<'a> Clone for VecRefBorrow<'a> {
fn clone(&self) -> Self {
VecRefBorrow::new(&self.0).expect("Error creating a new VecRef: integer overflow")
}
}
impl<'a> Drop for VecRefBorrow<'a> {
#[inline]
fn drop(&mut self) {
debug_assert!(self.0.get() > 0, "Borrow count was null yet there was still a borrow!");
self.0.set(self.0.get() - 1);
}
}