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
136impl fmt::Debug for GenericSharedMemory {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 f.debug_tuple("GenericSharedMemory").finish()
139 }
140}
141
142impl Serialize for GenericSharedMemory {
143 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
144 match &self.0 {
145 GenericSharedMemoryVariant::Ipc(memory) => {
146 s.serialize_newtype_variant("GenericSharedMemory", 0, "Ipc", memory)
147 },
148 GenericSharedMemoryVariant::InProcess(arc) => {
149 if use_ipc() {
150 return Err(serde::ser::Error::custom(
151 "Arc<Vec<u8>> found in multiprocess mode!",
152 ));
153 } let address = Arc::into_raw(arc.clone()) as *mut Vec<u8> as usize;
156 s.serialize_newtype_variant("GenericSharedMemory", 1, "InProcess", &address)
157 },
158 }
159 }
160}
161
162struct GenericSharedMemoryVisitor {}
163
164impl<'de> serde::de::Visitor<'de> for GenericSharedMemoryVisitor {
165 type Value = GenericSharedMemory;
166
167 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
168 formatter.write_str("a GenericReceiver variant")
169 }
170
171 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
172 where
173 A: serde::de::EnumAccess<'de>,
174 {
175 #[derive(Deserialize)]
176 enum GenericSharedMemoryVariantNames {
177 Ipc,
178 InProcess,
179 }
180
181 let (variant_name, variant_data): (GenericSharedMemoryVariantNames, _) = data.variant()?;
182
183 match variant_name {
184 GenericSharedMemoryVariantNames::Ipc => variant_data
185 .newtype_variant::<IpcSharedMemory>()
186 .map(|receiver| GenericSharedMemory(GenericSharedMemoryVariant::Ipc(receiver))),
187 GenericSharedMemoryVariantNames::InProcess => {
188 if use_ipc() {
189 return Err(serde::de::Error::custom(
190 "Arc data found in multiprocess mode!",
191 ));
192 }
193 let addr = variant_data.newtype_variant::<usize>()?;
194 let ptr = addr as *mut Vec<u8>;
195 #[expect(unsafe_code)]
198 let arc = unsafe { Arc::from_raw(ptr) };
199 Ok(GenericSharedMemory(GenericSharedMemoryVariant::InProcess(
200 arc,
201 )))
202 },
203 }
204 }
205}
206
207impl<'a> Deserialize<'a> for GenericSharedMemory {
208 fn deserialize<D>(d: D) -> Result<GenericSharedMemory, D::Error>
209 where
210 D: Deserializer<'a>,
211 {
212 d.deserialize_enum(
213 "GenericSharedMemory",
214 &["Ipc", "InProcess"],
215 GenericSharedMemoryVisitor {},
216 )
217 }
218}
219
220#[cfg(test)]
221mod single_process_shared_memory_test {
222 use std::sync::Arc;
223
224 use ipc_channel::ipc::IpcSharedMemory;
225
226 use super::GenericSharedMemory;
227 use crate::generic_channel::{self};
228
229 #[test]
230 fn test_ipc() {
231 let bytes = vec![0xba; 10];
232 let bytes_copy = bytes.clone();
233 let shared_memory = GenericSharedMemory(super::GenericSharedMemoryVariant::Ipc(
234 IpcSharedMemory::from_bytes(&bytes),
235 ));
236
237 let (send, recv) = generic_channel::channel().unwrap();
238 send.send(shared_memory).expect("Could not send");
239 assert_eq!(recv.recv().unwrap().to_vec(), bytes_copy);
240 }
241
242 #[test]
243 fn test_inprocess() {
244 let bytes = vec![0xba; 10];
245 let bytes_copy = bytes.clone();
246 let shared_memory = GenericSharedMemory(super::GenericSharedMemoryVariant::InProcess(
247 Arc::new(bytes.clone()),
248 ));
249
250 let (send, recv) = generic_channel::channel().unwrap();
251 send.send(shared_memory).expect("Could not send");
252 assert_eq!(recv.recv().unwrap().to_vec(), bytes_copy);
253 }
254}