use alloc::{
collections::{BTreeMap, VecDeque},
vec::Vec,
};
#[cfg(doc)]
use core::ops::IndexMut;
use core::{
borrow::Borrow,
mem,
ops::{Deref, DerefMut, Index, Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive},
};
#[cfg(feature = "std")]
use std::{collections::HashMap, hash::BuildHasher, hash::Hash};
#[cfg(doc)]
use crate::Gc;
#[non_exhaustive]
#[repr(transparent)]
pub struct Write<T: ?Sized> {
#[doc(hidden)]
pub __inner: T,
}
impl<T: ?Sized> Deref for Write<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.__inner
}
}
impl<T: ?Sized> DerefMut for Write<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.__inner
}
}
impl<T: IndexWrite<I> + ?Sized, I> Index<I> for Write<T> {
type Output = Write<T::Output>;
#[inline]
fn index(&self, index: I) -> &Self::Output {
unsafe { Write::assume(&self.__inner[index]) }
}
}
impl<T: ?Sized> Write<T> {
#[inline(always)]
pub unsafe fn assume(v: &T) -> &Self {
unsafe { mem::transmute(v) }
}
#[inline]
pub fn from_static(v: &T) -> &Self
where
T: 'static,
{
unsafe { mem::transmute(v) }
}
#[inline]
pub fn from_mut(v: &mut T) -> &mut Self {
unsafe { mem::transmute(v) }
}
#[inline(always)]
#[doc(hidden)]
pub unsafe fn __from_ref_and_ptr(v: &T, _: *const T) -> &Self {
unsafe {
mem::transmute(v)
}
}
#[inline]
pub fn unlock(&self) -> &T::Unlocked
where
T: Unlock,
{
unsafe { self.__inner.unlock_unchecked() }
}
#[inline(always)]
pub fn as_deref(&self) -> &Write<T::Target>
where
T: DerefWrite,
{
unsafe { Write::assume(&*self) }
}
}
impl<T> Write<Option<T>> {
#[inline(always)]
pub fn as_write(&self) -> Option<&Write<T>> {
unsafe {
match &self.__inner {
None => None,
Some(v) => Some(Write::assume(v)),
}
}
}
}
impl<T, E> Write<Result<T, E>> {
#[inline(always)]
pub fn as_write(&self) -> Result<&Write<T>, &Write<E>> {
unsafe {
match &self.__inner {
Ok(v) => Ok(Write::assume(v)),
Err(e) => Err(Write::assume(e)),
}
}
}
}
pub unsafe trait DerefWrite: Deref {}
unsafe impl<T: ?Sized> DerefWrite for &T {}
unsafe impl<T: ?Sized> DerefWrite for alloc::boxed::Box<T> {}
unsafe impl<T> DerefWrite for Vec<T> {}
unsafe impl<T: ?Sized> DerefWrite for alloc::rc::Rc<T> {}
#[cfg(target_has_atomic = "ptr")]
unsafe impl<T: ?Sized> DerefWrite for alloc::sync::Arc<T> {}
pub unsafe trait IndexWrite<I: ?Sized>: Index<I> {}
unsafe impl<T> IndexWrite<usize> for [T] {}
unsafe impl<T> IndexWrite<Range<usize>> for [T] {}
unsafe impl<T> IndexWrite<RangeFrom<usize>> for [T] {}
unsafe impl<T> IndexWrite<RangeInclusive<usize>> for [T] {}
unsafe impl<T> IndexWrite<RangeTo<usize>> for [T] {}
unsafe impl<T> IndexWrite<RangeToInclusive<usize>> for [T] {}
unsafe impl<T, I, const N: usize> IndexWrite<I> for [T; N] where [T]: IndexWrite<I> {}
unsafe impl<T, I> IndexWrite<I> for Vec<T>
where
[T]: IndexWrite<I>,
Self: Index<I>,
{
}
unsafe impl<T> IndexWrite<usize> for VecDeque<T> {}
unsafe impl<K, V, Q> IndexWrite<&Q> for BTreeMap<K, V>
where
K: Borrow<Q> + Ord,
Q: Ord + ?Sized,
{
}
#[cfg(feature = "std")]
unsafe impl<K, V, S, Q> IndexWrite<&Q> for HashMap<K, V, S>
where
K: Eq + Hash + Borrow<Q>,
Q: Eq + Hash + ?Sized,
S: BuildHasher,
{
}
pub trait Unlock {
type Unlocked: ?Sized;
unsafe fn unlock_unchecked(&self) -> &Self::Unlocked;
}
#[doc(inline)]
pub use crate::__field as field;
#[macro_export]
#[doc(hidden)]
macro_rules! __field {
($value:expr, $type:path, $field:ident) => {
match $value {
&$crate::barrier::Write {
__inner: $type { ref $field, .. },
..
} => unsafe { $crate::barrier::Write::__from_ref_and_ptr($field, $field as *const _) },
}
};
}
#[doc(inline)]
pub use crate::__unlock as unlock;
#[macro_export]
#[doc(hidden)]
macro_rules! __unlock {
($value:expr, $type:path, $field:ident) => {
$crate::barrier::field!($value, $type, $field).unlock()
};
}