use std::{
borrow::Cow,
ops::{Deref, DerefMut},
};
use crate::Str;
pub struct Global<T> {
#[cfg(target_arch = "wasm32")]
data: std::mem::ManuallyDrop<std::cell::LazyCell<T>>,
#[cfg(not(target_arch = "wasm32"))]
data: std::sync::LazyLock<T>,
}
impl<T> Global<T> {
pub const fn new(create_fn: fn() -> T) -> Self {
#[cfg(target_arch = "wasm32")]
{
Global {
data: std::mem::ManuallyDrop::new(std::cell::LazyCell::new(create_fn)),
}
}
#[cfg(not(target_arch = "wasm32"))]
{
Global {
data: std::sync::LazyLock::new(create_fn),
}
}
}
}
unsafe impl<T> Send for Global<T> {}
unsafe impl<T> Sync for Global<T> {}
impl<T> Deref for Global<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
#[derive(Default)]
pub struct Shared<T> {
#[cfg(not(target_arch = "wasm32"))]
inner: std::sync::Arc<std::sync::RwLock<T>>,
#[cfg(target_arch = "wasm32")]
inner: std::rc::Rc<std::cell::RefCell<T>>,
}
impl<T: PartialEq> PartialEq for Shared<T> {
#[cfg(not(target_arch = "wasm32"))]
fn eq(&self, other: &Self) -> bool {
self.inner.read().unwrap().eq(&other.inner.read().unwrap())
}
#[cfg(target_arch = "wasm32")]
fn eq(&self, other: &Self) -> bool {
self.inner.borrow().eq(&other.inner.borrow())
}
}
impl<T> Clone for Shared<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T: 'static> From<T> for Shared<T> {
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T> Shared<T> {
pub fn new(value: T) -> Self {
Self {
#[cfg(not(target_arch = "wasm32"))]
inner: std::sync::Arc::new(std::sync::RwLock::new(value)),
#[cfg(target_arch = "wasm32")]
inner: std::rc::Rc::new(std::cell::RefCell::new(value)),
}
}
pub fn get(&self) -> impl Deref<Target = T> {
#[cfg(not(target_arch = "wasm32"))]
{
self.inner.read().unwrap()
}
#[cfg(target_arch = "wasm32")]
{
self.inner.borrow()
}
}
pub fn get_mut(&self) -> impl DerefMut<Target = T> {
#[cfg(not(target_arch = "wasm32"))]
{
self.inner.write().unwrap()
}
#[cfg(target_arch = "wasm32")]
{
self.inner.borrow_mut()
}
}
pub fn set(&self, value: T) -> T {
std::mem::replace(self.get_mut().deref_mut(), value)
}
}
impl Shared<Str> {
pub fn from_string(s: impl AsRef<str>) -> Self {
let cow = Cow::from(s.as_ref().to_owned());
Shared::from(cow)
}
}