style_traits/
arc_slice.rs1use serde::de::{Deserialize, Deserializer};
8use serde::ser::{Serialize, Serializer};
9use servo_arc::ThinArc;
10use std::ops::Deref;
11use std::ptr::NonNull;
12use std::sync::LazyLock;
13use std::{iter, mem, hash::{Hash, Hasher}};
14
15use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf};
16
17const ARC_SLICE_CANARY: u64 = 0xf3f3f3f3f3f3f3f3;
26
27#[repr(C)]
29#[derive(Debug, Eq, PartialEq, ToShmem)]
30pub struct ArcSlice<T>(#[shmem(field_bound)] ThinArc<u64, T>);
31
32impl<T> Deref for ArcSlice<T> {
33 type Target = [T];
34
35 #[inline]
36 fn deref(&self) -> &Self::Target {
37 debug_assert_eq!(self.0.header, ARC_SLICE_CANARY);
38 self.0.slice()
39 }
40}
41
42impl<T> Clone for ArcSlice<T> {
43 fn clone(&self) -> Self {
44 ArcSlice(self.0.clone())
45 }
46}
47
48static EMPTY_ARC_SLICE: LazyLock<ArcSlice<u64>> =
50 LazyLock::new(|| ArcSlice::from_iter_leaked(iter::empty()));
51
52impl<T> Default for ArcSlice<T> {
53 #[allow(unsafe_code)]
54 fn default() -> Self {
55 debug_assert!(
56 mem::align_of::<T>() <= mem::align_of::<u64>(),
57 "Need to increase the alignment of EMPTY_ARC_SLICE"
58 );
59 unsafe {
60 let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone();
61 let empty: Self = mem::transmute(empty);
62 debug_assert_eq!(empty.len(), 0);
63 empty
64 }
65 }
66}
67
68impl<T: Serialize> Serialize for ArcSlice<T> {
69 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70 where
71 S: Serializer,
72 {
73 self.deref().serialize(serializer)
74 }
75}
76
77impl<'de, T: Deserialize<'de>> Deserialize<'de> for ArcSlice<T> {
78 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
79 where
80 D: Deserializer<'de>,
81 {
82 let r = Vec::deserialize(deserializer)?;
83 Ok(ArcSlice::from_iter(r.into_iter()))
84 }
85}
86
87impl<T> ArcSlice<T> {
88 #[inline]
91 pub fn from_iter<I>(items: I) -> Self
92 where
93 I: Iterator<Item = T> + ExactSizeIterator,
94 {
95 if items.len() == 0 {
96 return Self::default();
97 }
98 ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items))
99 }
100
101 #[inline]
105 pub fn from_iter_leaked<I>(items: I) -> Self
106 where
107 I: Iterator<Item = T> + ExactSizeIterator,
108 {
109 let arc = ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items);
110 arc.mark_as_intentionally_leaked();
111 ArcSlice(arc)
112 }
113
114 #[inline]
117 pub fn forget(self) -> ForgottenArcSlicePtr<T> {
118 let ret = ForgottenArcSlicePtr(self.0.raw_ptr().cast());
119 mem::forget(self);
120 ret
121 }
122
123 #[inline]
126 pub fn leaked_empty_ptr() -> *mut std::os::raw::c_void {
127 let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone();
128 let ptr = empty.0.raw_ptr();
129 std::mem::forget(empty);
130 ptr.cast().as_ptr()
131 }
132
133 pub fn is_unique(&self) -> bool {
135 self.0.is_unique()
136 }
137}
138
139impl<T: MallocSizeOf> MallocUnconditionalSizeOf for ArcSlice<T> {
140 #[allow(unsafe_code)]
141 fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
142 let mut size = unsafe { ops.malloc_size_of(self.0.heap_ptr()) };
143 for el in self.iter() {
144 size += el.size_of(ops);
145 }
146 size
147 }
148}
149
150impl<T: Hash> Hash for ArcSlice<T> {
151 fn hash<H: Hasher>(&self, state: &mut H) {
152 T::hash_slice(&**self, state)
153 }
154}
155
156#[repr(C)]
161pub struct ForgottenArcSlicePtr<T>(NonNull<T>);