use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use servo_arc::ThinArc;
use std::ops::Deref;
use std::ptr::NonNull;
use std::{iter, mem, hash::{Hash, Hasher}};
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf};
const ARC_SLICE_CANARY: u64 = 0xf3f3f3f3f3f3f3f3;
#[repr(C)]
#[derive(Debug, Eq, PartialEq, ToShmem)]
pub struct ArcSlice<T>(#[shmem(field_bound)] ThinArc<u64, T>);
impl<T> Deref for ArcSlice<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &Self::Target {
debug_assert_eq!(self.0.header, ARC_SLICE_CANARY);
self.0.slice()
}
}
impl<T> Clone for ArcSlice<T> {
fn clone(&self) -> Self {
ArcSlice(self.0.clone())
}
}
lazy_static! {
static ref EMPTY_ARC_SLICE: ArcSlice<u64> = {
ArcSlice::from_iter_leaked(iter::empty())
};
}
impl<T> Default for ArcSlice<T> {
#[allow(unsafe_code)]
fn default() -> Self {
debug_assert!(
mem::align_of::<T>() <= mem::align_of::<u64>(),
"Need to increase the alignment of EMPTY_ARC_SLICE"
);
unsafe {
let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone();
let empty: Self = mem::transmute(empty);
debug_assert_eq!(empty.len(), 0);
empty
}
}
}
impl<T: Serialize> Serialize for ArcSlice<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.deref().serialize(serializer)
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for ArcSlice<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let r = Vec::deserialize(deserializer)?;
Ok(ArcSlice::from_iter(r.into_iter()))
}
}
impl<T> ArcSlice<T> {
#[inline]
pub fn from_iter<I>(items: I) -> Self
where
I: Iterator<Item = T> + ExactSizeIterator,
{
if items.len() == 0 {
return Self::default();
}
ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items))
}
#[inline]
pub fn from_iter_leaked<I>(items: I) -> Self
where
I: Iterator<Item = T> + ExactSizeIterator,
{
let arc = ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items);
arc.mark_as_intentionally_leaked();
ArcSlice(arc)
}
#[inline]
pub fn forget(self) -> ForgottenArcSlicePtr<T> {
let ret = ForgottenArcSlicePtr(self.0.raw_ptr().cast());
mem::forget(self);
ret
}
#[inline]
pub fn leaked_empty_ptr() -> *mut std::os::raw::c_void {
let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone();
let ptr = empty.0.raw_ptr();
std::mem::forget(empty);
ptr.cast().as_ptr()
}
pub fn is_unique(&self) -> bool {
self.0.is_unique()
}
}
impl<T: MallocSizeOf> MallocUnconditionalSizeOf for ArcSlice<T> {
#[allow(unsafe_code)]
fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut size = unsafe { ops.malloc_size_of(self.0.heap_ptr()) };
for el in self.iter() {
size += el.size_of(ops);
}
size
}
}
impl<T: Hash> Hash for ArcSlice<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
T::hash_slice(&**self, state)
}
}
#[repr(C)]
pub struct ForgottenArcSlicePtr<T>(NonNull<T>);