1use std::mem::MaybeUninit;
2use std::sync::Arc;
3
4pub fn arc_map<T: Clone, F: FnMut(T) -> T>(mut arc: Arc<T>, mut f: F) -> Arc<T> {
5 unsafe {
6 Arc::make_mut(&mut arc);
8
9 let mut uninit_arc = Arc::from_raw(Arc::into_raw(arc).cast::<MaybeUninit<T>>());
11
12 let ptr = Arc::get_mut(&mut uninit_arc).unwrap_unchecked() as *mut MaybeUninit<T>;
14 *ptr = MaybeUninit::new(f(ptr.read().assume_init()));
15
16 Arc::from_raw(Arc::into_raw(uninit_arc).cast::<T>())
18 }
19}
20
21pub fn try_arc_map<T: Clone, E, F: FnMut(T) -> Result<T, E>>(
22 mut arc: Arc<T>,
23 mut f: F,
24) -> Result<Arc<T>, E> {
25 unsafe {
26 Arc::make_mut(&mut arc);
28
29 let mut uninit_arc = Arc::from_raw(Arc::into_raw(arc).cast::<MaybeUninit<T>>());
31
32 let ptr = Arc::get_mut(&mut uninit_arc).unwrap_unchecked() as *mut MaybeUninit<T>;
34 *ptr = MaybeUninit::new(f(ptr.read().assume_init())?);
35
36 Ok(Arc::from_raw(Arc::into_raw(uninit_arc).cast::<T>()))
38 }
39}