servo_base/generic_channel/
shared_memory.rs1use std::fmt;
6use std::ops::Deref;
7use std::sync::Arc;
8
9use ipc_channel::ipc::IpcSharedMemory;
10use malloc_size_of::MallocSizeOf;
11use serde::de::VariantAccess;
12use serde::{Deserialize, Deserializer, Serialize, Serializer};
13
14use crate::generic_channel::use_ipc;
15
16#[derive(Clone)]
17pub struct GenericSharedMemory(GenericSharedMemoryVariant);
18
19#[derive(Clone)]
20enum GenericSharedMemoryVariant {
21 Ipc(IpcSharedMemory),
22 InProcess(Arc<Vec<u8>>),
23}
24
25impl AsRef<[u8]> for GenericSharedMemory {
26 fn as_ref(&self) -> &[u8] {
27 self
28 }
29}
30
31impl Deref for GenericSharedMemory {
32 type Target = [u8];
33
34 #[inline]
35 fn deref(&self) -> &[u8] {
36 match &self.0 {
37 GenericSharedMemoryVariant::Ipc(ipc_shared_memory) => ipc_shared_memory,
38 GenericSharedMemoryVariant::InProcess(items) => items.as_slice(),
39 }
40 }
41}
42
43impl MallocSizeOf for GenericSharedMemory {
44 fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
45 match &self.0 {
46 GenericSharedMemoryVariant::Ipc(_) => 0,
47 GenericSharedMemoryVariant::InProcess(items) => items.size_of(ops),
48 }
49 }
50}
51
52impl GenericSharedMemory {
53 pub fn from_bytes(bytes: &[u8]) -> Self {
54 if use_ipc() {
55 GenericSharedMemory(GenericSharedMemoryVariant::Ipc(
56 IpcSharedMemory::from_bytes(bytes),
57 ))
58 } else {
59 GenericSharedMemory(GenericSharedMemoryVariant::InProcess(Arc::new(
60 bytes.to_owned(),
61 )))
62 }
63 }
64
65 pub fn from_byte(data: u8, length: usize) -> Self {
66 if use_ipc() {
67 GenericSharedMemory(GenericSharedMemoryVariant::Ipc(IpcSharedMemory::from_byte(
68 data, length,
69 )))
70 } else {
71 GenericSharedMemory(GenericSharedMemoryVariant::InProcess(Arc::new(vec![
72 data;
73 length
74 ])))
75 }
76 }
77
78 pub fn from_vec(bytes: Vec<u8>) -> Self {
84 if use_ipc() {
85 GenericSharedMemory(GenericSharedMemoryVariant::Ipc(
86 IpcSharedMemory::from_bytes(&bytes),
87 ))
88 } else {
89 GenericSharedMemory(GenericSharedMemoryVariant::InProcess(Arc::new(bytes)))
90 }
91 }
92
93 pub fn from_arc_vec(arc: Arc<Vec<u8>>) -> Self {
97 if use_ipc() {
98 GenericSharedMemory(GenericSharedMemoryVariant::Ipc(
99 IpcSharedMemory::from_bytes(&arc),
100 ))
101 } else {
102 GenericSharedMemory(GenericSharedMemoryVariant::InProcess(arc))
103 }
104 }
105
106 pub fn into_arc_vec(self) -> Arc<Vec<u8>> {
109 match self.0 {
110 GenericSharedMemoryVariant::Ipc(ipc_shared_memory) => {
111 Arc::new(ipc_shared_memory.to_vec())
112 },
113 GenericSharedMemoryVariant::InProcess(arc) => arc,
114 }
115 }
116
117 pub fn from_bytes_with_mutator(bytes: &[u8], mutator: impl FnOnce(&mut [u8])) -> Self {
118 let mut shared_memory = Self::from_bytes(bytes);
119 match &mut shared_memory.0 {
120 GenericSharedMemoryVariant::Ipc(ipc_shared_memory) => {
121 #[expect(unsafe_code)]
122 unsafe {
123 mutator(ipc_shared_memory.deref_mut())
124 }
125 },
126 GenericSharedMemoryVariant::InProcess(arc) => mutator(
127 Arc::get_mut(arc)
128 .expect("Arc just created from bytes")
129 .as_mut_slice(),
130 ),
131 }
132 shared_memory
133 }
134
135 #[expect(unsafe_code)]
136 pub unsafe fn deref_mut(&mut self) -> &mut [u8] {
142 match &mut self.0 {
143 GenericSharedMemoryVariant::Ipc(ipc_shared_memory) => {
144 #[expect(unsafe_code)]
145 unsafe {
146 ipc_shared_memory.deref_mut()
147 }
148 },
149 GenericSharedMemoryVariant::InProcess(arc) => Arc::get_mut(arc)
150 .expect("Arc just created from bytes")
151 .as_mut_slice(),
152 }
153 }
154}
155
156impl fmt::Debug for GenericSharedMemory {
157 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158 f.debug_tuple("GenericSharedMemory").finish()
159 }
160}
161
162impl Serialize for GenericSharedMemory {
163 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
164 match &self.0 {
165 GenericSharedMemoryVariant::Ipc(memory) => {
166 s.serialize_newtype_variant("GenericSharedMemory", 0, "Ipc", memory)
167 },
168 GenericSharedMemoryVariant::InProcess(arc) => {
169 if use_ipc() {
170 return Err(serde::ser::Error::custom(
171 "Arc<Vec<u8>> found in multiprocess mode!",
172 ));
173 } let address = Arc::into_raw(arc.clone()) as *mut Vec<u8> as usize;
176 s.serialize_newtype_variant("GenericSharedMemory", 1, "InProcess", &address)
177 },
178 }
179 }
180}
181
182struct GenericSharedMemoryVisitor {}
183
184impl<'de> serde::de::Visitor<'de> for GenericSharedMemoryVisitor {
185 type Value = GenericSharedMemory;
186
187 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
188 formatter.write_str("a GenericReceiver variant")
189 }
190
191 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
192 where
193 A: serde::de::EnumAccess<'de>,
194 {
195 #[derive(Deserialize)]
196 enum GenericSharedMemoryVariantNames {
197 Ipc,
198 InProcess,
199 }
200
201 let (variant_name, variant_data): (GenericSharedMemoryVariantNames, _) = data.variant()?;
202
203 match variant_name {
204 GenericSharedMemoryVariantNames::Ipc => variant_data
205 .newtype_variant::<IpcSharedMemory>()
206 .map(|receiver| GenericSharedMemory(GenericSharedMemoryVariant::Ipc(receiver))),
207 GenericSharedMemoryVariantNames::InProcess => {
208 if use_ipc() {
209 return Err(serde::de::Error::custom(
210 "Arc data found in multiprocess mode!",
211 ));
212 }
213 let addr = variant_data.newtype_variant::<usize>()?;
214 let ptr = addr as *mut Vec<u8>;
215 #[expect(unsafe_code)]
218 let arc = unsafe { Arc::from_raw(ptr) };
219 Ok(GenericSharedMemory(GenericSharedMemoryVariant::InProcess(
220 arc,
221 )))
222 },
223 }
224 }
225}
226
227impl<'a> Deserialize<'a> for GenericSharedMemory {
228 fn deserialize<D>(d: D) -> Result<GenericSharedMemory, D::Error>
229 where
230 D: Deserializer<'a>,
231 {
232 d.deserialize_enum(
233 "GenericSharedMemory",
234 &["Ipc", "InProcess"],
235 GenericSharedMemoryVisitor {},
236 )
237 }
238}
239
240#[cfg(test)]
241mod single_process_shared_memory_test {
242 use std::sync::Arc;
243
244 use ipc_channel::ipc::IpcSharedMemory;
245
246 use super::GenericSharedMemory;
247 use crate::generic_channel::{self};
248
249 #[test]
250 fn test_ipc() {
251 let bytes = vec![0xba; 10];
252 let bytes_copy = bytes.clone();
253 let shared_memory = GenericSharedMemory(super::GenericSharedMemoryVariant::Ipc(
254 IpcSharedMemory::from_bytes(&bytes),
255 ));
256
257 let (send, recv) = generic_channel::channel().unwrap();
258 send.send(shared_memory).expect("Could not send");
259 assert_eq!(recv.recv().unwrap().to_vec(), bytes_copy);
260 }
261
262 #[test]
263 fn test_inprocess() {
264 let bytes = vec![0xba; 10];
265 let bytes_copy = bytes.clone();
266 let shared_memory = GenericSharedMemory(super::GenericSharedMemoryVariant::InProcess(
267 Arc::new(bytes.clone()),
268 ));
269
270 let (send, recv) = generic_channel::channel().unwrap();
271 send.send(shared_memory).expect("Could not send");
272 assert_eq!(recv.recv().unwrap().to_vec(), bytes_copy);
273 }
274}