#![deny(missing_docs)]
use hashbrown::HashMap;
use serde_hashkey as hashkey;
use std::any::{Any, TypeId};
use std::cmp;
use std::error;
use std::fmt;
use std::hash;
use std::marker;
use std::mem;
use std::ptr;
use std::sync::Arc;
use tokio::sync::{broadcast, RwLock};
pub type RefReadGuard<'a, T> = tokio::sync::RwLockReadGuard<'a, T>;
#[doc(hidden)]
pub mod derive {
pub use tokio::select;
}
#[macro_use]
#[allow(unused_imports)]
extern crate async_injector_derive;
#[doc(hidden)]
pub use self::async_injector_derive::*;
#[derive(Debug)]
pub enum Error {
SerializationError(hashkey::Error),
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::SerializationError(..) => "serialization error".fmt(fmt),
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Self::SerializationError(e) => Some(e),
}
}
}
impl From<hashkey::Error> for Error {
fn from(value: hashkey::Error) -> Self {
Error::SerializationError(value)
}
}
pub struct Stream<T> {
rx: broadcast::Receiver<Option<Value>>,
marker: marker::PhantomData<T>,
}
impl<T> Stream<T> {
pub async fn recv(&mut self) -> Option<T> {
let value = loop {
let value = self.rx.recv().await;
match value {
Ok(value) => break value,
Err(broadcast::error::RecvError::Lagged { .. }) => continue,
_ => return None,
};
};
let value = match value {
Some(value) => value,
_ => return None,
};
Some(unsafe { value.downcast::<T>() })
}
}
struct Value {
data: *const (),
value_clone_fn: unsafe fn(*const ()) -> *const (),
value_drop_fn: unsafe fn(*const ()),
}
impl Value {
pub(crate) fn new<T>(data: T) -> Self
where
T: 'static + Clone + Send + Sync,
{
return Self {
data: Box::into_raw(Box::new(data)) as *const (),
value_clone_fn: value_clone_fn::<T>,
value_drop_fn: value_drop_fn::<T>,
};
unsafe fn value_clone_fn<T>(data: *const ()) -> *const ()
where
T: Clone,
{
let data = T::clone(&*(data as *const _));
Box::into_raw(Box::new(data)) as *const ()
}
unsafe fn value_drop_fn<T>(value: *const ()) {
ptr::drop_in_place(value as *mut () as *mut T)
}
}
pub(crate) unsafe fn downcast_ref<T>(&self) -> &T {
&*(self.data as *const T)
}
pub(crate) unsafe fn downcast_mut<T>(&mut self) -> &mut T {
&mut *(self.data as *const T as *mut T)
}
pub(crate) unsafe fn downcast<T>(self) -> T {
let value = Box::from_raw(self.data as *const T as *mut T);
mem::forget(self);
*value
}
}
unsafe impl Send for Value {}
unsafe impl Sync for Value {}
impl Clone for Value {
fn clone(&self) -> Self {
let data = unsafe { (self.value_clone_fn)(self.data as *const _) };
Self {
data,
value_clone_fn: self.value_clone_fn,
value_drop_fn: self.value_drop_fn,
}
}
}
impl Drop for Value {
fn drop(&mut self) {
unsafe {
(self.value_drop_fn)(self.data);
}
}
}
struct Storage {
value: Arc<RwLock<Option<Value>>>,
tx: broadcast::Sender<Option<Value>>,
}
impl Default for Storage {
fn default() -> Self {
let (tx, _) = broadcast::channel(1);
Self {
value: Arc::new(RwLock::new(None)),
tx,
}
}
}
struct Inner {
storage: RwLock<HashMap<RawKey, Storage>>,
}
#[derive(Clone)]
pub struct Injector {
inner: Arc<Inner>,
}
impl Injector {
pub fn new() -> Self {
Self {
inner: Arc::new(Inner {
storage: Default::default(),
}),
}
}
pub async fn clear<T>(&self) -> Option<T>
where
T: Clone + Any + Send + Sync,
{
self.clear_key(Key::<T>::of()).await
}
pub async fn clear_key<T>(&self, key: impl AsRef<Key<T>>) -> Option<T>
where
T: Clone + Any + Send + Sync,
{
let key = key.as_ref().as_raw_key();
let storage = self.inner.storage.read().await;
let storage = storage.get(key)?;
let value = storage.value.write().await.take()?;
let _ = storage.tx.send(None);
Some(unsafe { value.downcast() })
}
pub async fn update<T>(&self, value: T) -> Option<T>
where
T: Clone + Any + Send + Sync,
{
self.update_key(Key::<T>::of(), value).await
}
pub async fn update_key<T>(&self, key: impl AsRef<Key<T>>, value: T) -> Option<T>
where
T: Clone + Any + Send + Sync,
{
let key = key.as_ref().as_raw_key();
let value = Value::new(T::from(value));
let mut storage = self.inner.storage.write().await;
let storage = storage.entry(key.clone()).or_default();
let _ = storage.tx.send(Some(value.clone()));
let old = storage.value.write().await.replace(value)?;
Some(unsafe { old.downcast() })
}
pub async fn exists<T>(&self) -> bool
where
T: Clone + Any + Send + Sync,
{
self.exists_key(&Key::<T>::of()).await
}
pub async fn exists_key<T>(&self, key: impl AsRef<Key<T>>) -> bool
where
T: Clone + Any + Send + Sync,
{
let key = key.as_ref().as_raw_key();
let storage = self.inner.storage.read().await;
if let Some(s) = storage.get(key) {
s.value.read().await.is_some()
} else {
false
}
}
pub async fn mutate<T, M, R>(&self, mutator: M) -> Option<R>
where
T: Clone + Any + Send + Sync,
M: FnMut(&mut T) -> R,
{
self.mutate_key(&Key::<T>::of(), mutator).await
}
pub async fn mutate_key<T, M, R>(&self, key: impl AsRef<Key<T>>, mut mutator: M) -> Option<R>
where
T: Clone + Any + Send + Sync,
M: FnMut(&mut T) -> R,
{
let key = key.as_ref().as_raw_key();
let storage = self.inner.storage.read().await;
let storage = match storage.get(key) {
Some(s) => s,
None => return None,
};
let mut value = storage.value.write().await;
if let Some(value) = &mut *value {
let output = mutator(unsafe { value.downcast_mut() });
let value = value.clone();
let _ = storage.tx.send(Some(value));
return Some(output);
}
None
}
pub async fn get<T>(&self) -> Option<T>
where
T: Clone + Any + Send + Sync,
{
self.get_key(&Key::<T>::of()).await
}
pub async fn get_key<T>(&self, key: impl AsRef<Key<T>>) -> Option<T>
where
T: Clone + Any + Send + Sync,
{
let key = key.as_ref().as_raw_key();
let storage = self.inner.storage.read().await;
let storage = match storage.get(key) {
Some(storage) => storage,
None => return None,
};
let value = storage.value.read().await;
if let Some(value) = &*value {
Some(unsafe { value.downcast_ref::<T>().clone() })
} else {
None
}
}
pub async fn stream<T>(&self) -> (Stream<T>, Option<T>)
where
T: Clone + Any + Send + Sync,
{
self.stream_key(Key::<T>::of()).await
}
pub async fn stream_key<T>(&self, key: impl AsRef<Key<T>>) -> (Stream<T>, Option<T>)
where
T: Clone + Any + Send + Sync,
{
let key = key.as_ref().as_raw_key();
let mut storage = self.inner.storage.write().await;
let storage = storage.entry(key.clone()).or_default();
let rx = storage.tx.subscribe();
let value = storage.value.read().await;
let value = match &*value {
Some(value) => {
Some(unsafe { value.downcast_ref::<T>().clone() })
}
None => None,
};
let stream = Stream {
rx,
marker: marker::PhantomData,
};
(stream, value)
}
pub async fn var<T>(&self) -> Ref<T>
where
T: Clone + Any + Send + Sync + Unpin,
{
self.var_key(&Key::<T>::of()).await
}
pub async fn var_key<T>(&self, key: impl AsRef<Key<T>>) -> Ref<T>
where
T: Clone + Any + Send + Sync + Unpin,
{
let key = key.as_ref().as_raw_key();
let mut storage = self.inner.storage.write().await;
let storage = storage.entry(key.clone()).or_default();
Ref {
value: storage.value.clone(),
_m: marker::PhantomData,
}
}
}
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
struct RawKey {
type_id: TypeId,
tag_type_id: TypeId,
tag: hashkey::Key,
}
impl RawKey {
fn new<T, K>(tag: hashkey::Key) -> Self
where
T: Any,
K: Any,
{
Self {
type_id: TypeId::of::<T>(),
tag_type_id: TypeId::of::<K>(),
tag,
}
}
}
#[derive(Clone)]
pub struct Key<T>
where
T: Any,
{
raw_key: RawKey,
_marker: marker::PhantomData<T>,
}
impl<T> fmt::Debug for Key<T>
where
T: Any,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.raw_key, fmt)
}
}
impl<T> cmp::PartialEq for Key<T>
where
T: Any,
{
fn eq(&self, other: &Self) -> bool {
self.as_raw_key().eq(other.as_raw_key())
}
}
impl<T> cmp::Eq for Key<T> where T: Any {}
impl<T> cmp::PartialOrd for Key<T>
where
T: Any,
{
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.as_raw_key().partial_cmp(other.as_raw_key())
}
}
impl<T> cmp::Ord for Key<T>
where
T: Any,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_raw_key().cmp(other.as_raw_key())
}
}
impl<T> hash::Hash for Key<T>
where
T: Any,
{
fn hash<H>(&self, state: &mut H)
where
H: hash::Hasher,
{
self.as_raw_key().hash(state);
}
}
impl<T> Key<T>
where
T: Any,
{
pub fn of() -> Self {
Self {
raw_key: RawKey::new::<T, ()>(hashkey::Key::Unit),
_marker: marker::PhantomData,
}
}
pub fn tagged<K>(tag: K) -> Result<Self, Error>
where
K: Any + serde::Serialize,
{
let tag = hashkey::to_key(&tag)?;
Ok(Self {
raw_key: RawKey::new::<T, K>(tag),
_marker: marker::PhantomData,
})
}
fn as_raw_key(&self) -> &RawKey {
&self.raw_key
}
}
impl<T> AsRef<Key<T>> for Key<T>
where
T: 'static,
{
fn as_ref(&self) -> &Self {
self
}
}
#[derive(Clone)]
pub struct Ref<T>
where
T: Clone + Any + Send + Sync,
{
value: Arc<RwLock<Option<Value>>>,
_m: marker::PhantomData<T>,
}
impl<T> Ref<T>
where
T: Clone + Any + Send + Sync,
{
pub async fn read(&self) -> Option<RefReadGuard<'_, T>> {
let value = self.value.read().await;
let result = RefReadGuard::try_map(value, |value| {
match value {
Some(value) => Some(unsafe { value.downcast_ref::<T>() }),
None => None,
}
});
result.ok()
}
pub async fn load(&self) -> Option<T> {
let value = self.value.read().await;
match &*value {
Some(value) => Some(unsafe { value.downcast_ref::<T>().clone() }),
None => None,
}
}
}
#[cfg(test)]
mod tests {
use super::Value;
#[test]
fn test_clone() {
use std::sync::{
atomic::{AtomicUsize, Ordering},
Arc,
};
let count = Arc::new(AtomicUsize::new(0));
let value = Value::new(Foo(count.clone()));
assert_eq!(0, count.load(Ordering::SeqCst));
drop(value.clone());
assert_eq!(1, count.load(Ordering::SeqCst));
drop(value);
assert_eq!(2, count.load(Ordering::SeqCst));
#[derive(Clone)]
struct Foo(Arc<AtomicUsize>);
impl Drop for Foo {
fn drop(&mut self) {
self.0.fetch_add(1, Ordering::SeqCst);
}
}
}
}