use std::{
fmt,
hash::{Hash, Hasher},
};
pub use inner::*;
#[cfg(not(feature = "sync"))]
mod inner {
use std::{cell::RefCell, rc::Rc};
#[repr(transparent)]
pub struct RefCount<T>(pub(super) Rc<RefCell<T>>);
impl<T> Clone for RefCount<T> {
fn clone(&self) -> Self {
Self(Rc::clone(&self.0))
}
}
#[repr(transparent)]
pub struct Weak<T>(pub(super) std::rc::Weak<RefCell<T>>);
pub type Ref<'a, T> = std::cell::Ref<'a, T>;
pub type RefMut<'a, T> = std::cell::RefMut<'a, T>;
impl<T> RefCount<T> {
pub fn new(inner: T) -> Self {
Self(Rc::new(RefCell::new(inner)))
}
pub fn clone(this: &Self) -> Self {
Self(Rc::clone(&this.0))
}
pub fn downgrade(&self) -> Weak<T> {
Weak(Rc::downgrade(&self.0))
}
pub fn get(&self) -> Ref<'_, T> {
self.0.borrow()
}
pub fn get_mut(&self) -> RefMut<'_, T> {
self.0.borrow_mut()
}
}
}
#[cfg(feature = "sync")]
mod inner {
use std::{
marker::PhantomData,
ops,
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
#[repr(transparent)]
pub struct RefCount<T>(pub(super) Arc<RwLock<T>>);
impl<T> Clone for RefCount<T> {
fn clone(&self) -> Self {
Self(Arc::clone(&self.0))
}
}
#[repr(transparent)]
pub struct Weak<T>(pub(super) std::sync::Weak<RwLock<T>>);
pub struct Ref<'a, T: ?Sized>(RwLockReadGuard<'a, T>);
pub type RefMut<'a, T> = RwLockWriteGuard<'a, T>;
impl<T> RefCount<T> {
pub fn new(inner: T) -> Self {
Self(Arc::new(RwLock::new(inner)))
}
pub fn clone(this: &Self) -> Self {
Self(Arc::clone(&this.0))
}
pub fn downgrade(&self) -> Weak<T> {
Weak(Arc::downgrade(&self.0))
}
pub fn get(&self) -> Ref<'_, T> {
Ref(self.0.read().unwrap())
}
pub fn get_mut(&self) -> RefMut<'_, T> {
self.0.write().unwrap()
}
}
impl<T> Ref<'_, T> {
pub const fn map<U: ?Sized, F>(orig: Ref<'_, T>, f: F) -> RefWrap<'_, T, U, F>
where
F: Copy + FnOnce(&T) -> &U,
{
RefWrap {
orig,
access: f,
_phantom: PhantomData,
}
}
}
pub struct RefWrap<'a, T, U: ?Sized, F> {
orig: Ref<'a, T>,
access: F,
_phantom: PhantomData<U>,
}
impl<T, U: ?Sized, F> ops::Deref for RefWrap<'_, T, U, F>
where
F: Copy + FnOnce(&T) -> &U,
{
type Target = U;
fn deref(&self) -> &Self::Target {
(self.access)(&self.orig)
}
}
impl<T: ?Sized> ops::Deref for Ref<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
ops::Deref::deref(&self.0)
}
}
}
impl<T> Weak<T> {
pub fn upgrade(&self) -> Option<RefCount<T>> {
self.0.upgrade().map(RefCount)
}
}
impl<T: fmt::Debug> fmt::Debug for RefCount<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl<T: PartialEq> PartialEq for RefCount<T> {
fn eq(&self, other: &Self) -> bool {
self.get().eq(&other.get())
}
}
impl<T: Eq> Eq for RefCount<T> {}
impl<T: Hash> Hash for RefCount<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.get().hash(state);
}
}
impl<T> Clone for Weak<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T: fmt::Debug> fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl<T: PartialEq> PartialEq for Weak<T> {
fn eq(&self, other: &Self) -> bool {
self.upgrade().eq(&other.upgrade())
}
}
impl<T: Eq> Eq for Weak<T> {}
impl<T: Hash> Hash for Weak<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.upgrade().hash(state);
}
}
#[cfg(not(feature = "sync"))]
const fn _share_gradual_taiko() {}
#[cfg(all(test, feature = "sync"))]
mod tests {
#[test]
fn share_gradual_taiko() {
use crate::{Beatmap, Difficulty, taiko::TaikoGradualDifficulty};
let map = Beatmap::from_bytes(&[]).unwrap();
let mut gradual = TaikoGradualDifficulty::new(Difficulty::new(), &map).unwrap();
std::thread::spawn(move || {
let _ = gradual.next();
});
}
}