1
0
Fork 0
forked from wry/wry
wry/crates/utils/src/clonecell.rs

98 lines
2.3 KiB
Rust

use {
crate::ptr_ext::{MutPtrExt, PtrExt},
jay_config::{keyboard::mods::Modifiers, window::Window},
std::{
cell::UnsafeCell,
fmt::{Debug, Formatter},
mem,
rc::{Rc, Weak},
sync::Arc,
},
};
pub struct CloneCell<T> {
data: UnsafeCell<T>,
}
impl<T: UnsafeCellCloneSafe> Clone for CloneCell<T> {
fn clone(&self) -> Self {
Self {
data: UnsafeCell::new(self.get()),
}
}
}
impl<T: UnsafeCellCloneSafe + Debug> Debug for CloneCell<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.get().fmt(f)
}
}
impl<T> CloneCell<T> {
pub const fn new(t: T) -> Self {
Self {
data: UnsafeCell::new(t),
}
}
#[inline(always)]
pub fn get(&self) -> T
where
T: UnsafeCellCloneSafe,
{
unsafe { self.data.get().deref().clone() }
}
#[inline(always)]
pub fn set(&self, t: T) -> T {
unsafe { mem::replace(self.data.get().deref_mut(), t) }
}
#[inline(always)]
pub fn take(&self) -> T
where
T: Default,
{
self.set(T::default())
}
}
impl<T> CloneCell<Option<T>> {
#[inline(always)]
pub fn is_some(&self) -> bool {
unsafe { self.data.get().deref().is_some() }
}
#[inline(always)]
pub fn is_none(&self) -> bool {
unsafe { self.data.get().deref().is_none() }
}
}
impl<T: Default> Default for CloneCell<T> {
fn default() -> Self {
Self::new(Default::default())
}
}
pub unsafe trait UnsafeCellCloneSafe: Clone {}
unsafe impl<T: UnsafeCellCloneSafe> UnsafeCellCloneSafe for Option<T> {}
unsafe impl<T: ?Sized> UnsafeCellCloneSafe for Rc<T> {}
unsafe impl<T: ?Sized> UnsafeCellCloneSafe for Weak<T> {}
unsafe impl<T: ?Sized> UnsafeCellCloneSafe for Arc<T> {}
unsafe impl UnsafeCellCloneSafe for () {}
unsafe impl UnsafeCellCloneSafe for u64 {}
unsafe impl UnsafeCellCloneSafe for i32 {}
unsafe impl UnsafeCellCloneSafe for u32 {}
unsafe impl UnsafeCellCloneSafe for usize {}
unsafe impl<A: UnsafeCellCloneSafe, B: UnsafeCellCloneSafe> UnsafeCellCloneSafe for (A, B) {}
unsafe impl UnsafeCellCloneSafe for Modifiers {}
unsafe impl UnsafeCellCloneSafe for Window {}
unsafe impl<T> UnsafeCellCloneSafe for crate::linkedlist::NodeRef<T> {}