1use std::fmt::Debug;
14use std::ops::{Deref, DerefMut};
15
16#[cfg(not(target_arch = "wasm32"))]
18use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard, Weak};
19
20#[cfg(target_arch = "wasm32")]
22use std::cell::{Ref, RefCell, RefMut};
23#[cfg(target_arch = "wasm32")]
24use std::rc::{Rc, Weak};
25
26
27#[derive(Debug)]
35pub struct SharedContainer<T: Debug> {
36 #[cfg(not(target_arch = "wasm32"))]
38 inner: Arc<RwLock<T>>,
39
40 #[cfg(target_arch = "wasm32")]
42 inner: Rc<RefCell<T>>,
43}
44
45#[cfg(not(target_arch = "wasm32"))]
47unsafe impl<T: Debug + Send> Send for SharedContainer<T> {}
48
49#[cfg(not(target_arch = "wasm32"))]
50unsafe impl<T: Debug + Send + Sync> Sync for SharedContainer<T> {}
51
52#[derive(Debug)]
60pub struct WeakSharedContainer<T: Debug> {
61 #[cfg(not(target_arch = "wasm32"))]
63 inner: Weak<RwLock<T>>,
64
65 #[cfg(target_arch = "wasm32")]
67 inner: Weak<RefCell<T>>,
68}
69
70impl<T: Debug> Clone for WeakSharedContainer<T> {
71 fn clone(&self) -> Self {
72 WeakSharedContainer {
74 inner: self.inner.clone(),
75 }
76 }
77}
78
79impl<T: Debug + PartialEq> PartialEq for SharedContainer<T> {
80 fn eq(&self, other: &Self) -> bool {
81 match (self.read(), other.read()) {
82 (Some(self_val), Some(other_val)) => *self_val == *other_val,
83 _ => false,
84 }
85 }
86}
87
88impl<T: Debug> Clone for SharedContainer<T> {
89 fn clone(&self) -> Self {
90 #[cfg(not(target_arch = "wasm32"))]
91 {
92 SharedContainer {
93 inner: Arc::clone(&self.inner),
94 }
95 }
96
97 #[cfg(target_arch = "wasm32")]
98 {
99 SharedContainer {
100 inner: Rc::clone(&self.inner),
101 }
102 }
103 }
104}
105
106impl<T: Debug + Clone> SharedContainer<T> {
107 pub fn get_cloned(&self) -> Option<T> {
115 let guard = self.read()?;
116 Some((*guard).clone())
117 }
118}
119
120impl<T: Debug> SharedContainer<T> {
121 pub fn new(value: T) -> Self {
129 #[cfg(not(target_arch = "wasm32"))]
130 {
131 SharedContainer {
132 inner: Arc::new(RwLock::new(value)),
133 }
134 }
135
136 #[cfg(target_arch = "wasm32")]
137 {
138 SharedContainer {
139 inner: Rc::new(RefCell::new(value)),
140 }
141 }
142 }
143
144 pub fn read(&self) -> Option<SharedReadGuard<T>> {
150 #[cfg(not(target_arch = "wasm32"))]
151 {
152 match self.inner.read() {
153 Ok(guard) => Some(SharedReadGuard::Multi(guard)),
154 Err(_) => None,
155 }
156 }
157
158 #[cfg(target_arch = "wasm32")]
159 {
160 match self.inner.try_borrow() {
161 Ok(borrow) => Some(SharedReadGuard::Single(borrow)),
162 Err(_) => None,
163 }
164 }
165 }
166
167 pub fn write(&self) -> Option<SharedWriteGuard<T>> {
173 #[cfg(not(target_arch = "wasm32"))]
174 {
175 match self.inner.write() {
176 Ok(guard) => Some(SharedWriteGuard::Multi(guard)),
177 Err(_) => None,
178 }
179 }
180
181 #[cfg(target_arch = "wasm32")]
182 {
183 match self.inner.try_borrow_mut() {
184 Ok(borrow) => Some(SharedWriteGuard::Single(borrow)),
185 Err(_) => None,
186 }
187 }
188 }
189
190 pub fn downgrade(&self) -> WeakSharedContainer<T> {
198 #[cfg(not(target_arch = "wasm32"))]
199 {
200 WeakSharedContainer {
201 inner: Arc::downgrade(&self.inner),
202 }
203 }
204
205 #[cfg(target_arch = "wasm32")]
206 {
207 WeakSharedContainer {
208 inner: Rc::downgrade(&self.inner),
209 }
210 }
211 }
212}
213
214impl<T: Debug> WeakSharedContainer<T> {
215 pub fn upgrade(&self) -> Option<SharedContainer<T>> {
224 self.inner.upgrade().map(|inner| SharedContainer { inner })
226 }
227}
228pub enum SharedReadGuard<'a, T: Debug> {
235 #[cfg(not(target_arch = "wasm32"))]
236 Multi(RwLockReadGuard<'a, T>),
237
238 #[cfg(target_arch = "wasm32")]
239 Single(Ref<'a, T>),
240}
241
242impl<'a, T: Debug> Deref for SharedReadGuard<'a, T> {
243 type Target = T;
244
245 fn deref(&self) -> &Self::Target {
246 #[cfg(not(target_arch = "wasm32"))]
247 {
248 match self {
249 SharedReadGuard::Multi(guard) => guard.deref(),
250 }
251 }
252
253 #[cfg(target_arch = "wasm32")]
254 {
255 match self {
256 SharedReadGuard::Single(borrow) => borrow.deref(),
257 }
258 }
259 }
260}
261
262pub enum SharedWriteGuard<'a, T: Debug> {
269 #[cfg(not(target_arch = "wasm32"))]
270 Multi(RwLockWriteGuard<'a, T>),
271
272 #[cfg(target_arch = "wasm32")]
273 Single(RefMut<'a, T>),
274}
275
276impl<'a, T: Debug> Deref for SharedWriteGuard<'a, T> {
277 type Target = T;
278
279 fn deref(&self) -> &Self::Target {
280 #[cfg(not(target_arch = "wasm32"))]
281 {
282 match self {
283 SharedWriteGuard::Multi(guard) => guard.deref(),
284 }
285 }
286
287 #[cfg(target_arch = "wasm32")]
288 {
289 match self {
290 SharedWriteGuard::Single(borrow) => borrow.deref(),
291 }
292 }
293 }
294}
295
296impl<'a, T: Debug> DerefMut for SharedWriteGuard<'a, T> {
297 fn deref_mut(&mut self) -> &mut Self::Target {
298 #[cfg(not(target_arch = "wasm32"))]
299 {
300 match self {
301 SharedWriteGuard::Multi(guard) => guard.deref_mut(),
302 }
303 }
304
305 #[cfg(target_arch = "wasm32")]
306 {
307 match self {
308 SharedWriteGuard::Single(borrow) => borrow.deref_mut(),
309 }
310 }
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317
318 #[derive(Debug, Clone, PartialEq)]
319 struct TestStruct {
320 value: i32,
321 }
322
323 #[test]
324 fn test_read_access() {
325 let container = SharedContainer::new(TestStruct { value: 42 });
326
327 let guard = container.read().unwrap();
329 assert_eq!(guard.value, 42);
330 }
331
332 #[test]
333 fn test_write_access() {
334 let container = SharedContainer::new(TestStruct { value: 42 });
335
336 {
338 let mut guard = container.write().unwrap();
339 guard.value = 100;
340 }
341
342 let guard = container.read().unwrap();
344 assert_eq!(guard.value, 100);
345 }
346
347 #[test]
348 fn test_clone_container() {
349 let container1 = SharedContainer::new(TestStruct { value: 42 });
350 let container2 = container1.clone();
351
352 {
354 let mut guard = container2.write().unwrap();
355 guard.value = 100;
356 }
357
358 let guard = container1.read().unwrap();
360 assert_eq!(guard.value, 100);
361 }
362
363 #[test]
364 fn test_get_cloned() {
365 let container = SharedContainer::new(TestStruct { value: 42 });
366 let cloned = container.get_cloned().unwrap();
367 assert_eq!(cloned, TestStruct { value: 42 });
368
369 {
371 let mut guard = container.write().unwrap();
372 guard.value = 100;
373 }
374
375 assert_eq!(cloned, TestStruct { value: 42 });
377
378 let new_clone = container.get_cloned().unwrap();
380 assert_eq!(new_clone, TestStruct { value: 100 });
381 }
382
383 #[test]
384 fn test_weak_ref() {
385 let container = SharedContainer::new(TestStruct { value: 42 });
386
387 let weak = container.downgrade();
389
390 let container2 = weak.upgrade().unwrap();
392
393 {
395 let mut guard = container2.write().unwrap();
396 guard.value = 100;
397 }
398
399 {
401 let guard = container.read().unwrap();
402 assert_eq!(guard.value, 100);
403 }
404 drop(container);
406 drop(container2);
407
408 assert!(weak.upgrade().is_none());
410 }
411
412 #[test]
413 fn test_weak_clone() {
414 let container = SharedContainer::new(TestStruct { value: 42 });
415
416 let weak1 = container.downgrade();
418 let weak2 = weak1.clone();
419
420 let container1 = weak1.upgrade().unwrap();
422 let container2 = weak2.upgrade().unwrap();
423
424 {
426 let mut guard = container2.write().unwrap();
427 guard.value = 100;
428 }
429
430 {
432 let guard = container1.read().unwrap();
433 assert_eq!(guard.value, 100);
434 }
435
436 drop(container);
438 drop(container1);
439 drop(container2);
440
441 assert!(weak1.upgrade().is_none());
443 assert!(weak2.upgrade().is_none());
444 }
445}