use std::sync::Arc;
use crate::api::handlers::IntoHandler;
pub fn locked<T>(fnmut: impl FnMut(T)) -> impl Fn(T) {
let lock = std::sync::Mutex::new(fnmut);
move |x| zlock!(lock)(x)
}
pub trait CallbackParameter: 'static {
type Message<'a>;
fn from_message(msg: Self::Message<'_>) -> Self;
}
trait CallbackImpl<T: CallbackParameter>: Send + Sync {
fn call(&self, t: T);
fn call_with_message(&self, msg: T::Message<'_>) {
self.call(T::from_message(msg))
}
}
impl<T: CallbackParameter, F: Fn(T) + Send + Sync> CallbackImpl<T> for F {
fn call(&self, t: T) {
self(t)
}
}
pub struct Callback<T: CallbackParameter>(Arc<dyn CallbackImpl<T>>);
impl<T: CallbackParameter> Clone for Callback<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T: CallbackParameter> Callback<T> {
pub fn new(cb: Arc<dyn Fn(T) + Send + Sync>) -> Self {
Self::from(move |msg| cb(msg))
}
#[inline]
pub fn call(&self, arg: T) {
self.0.call(arg)
}
pub(crate) fn call_with_message(&self, msg: T::Message<'_>) {
self.0.call_with_message(msg)
}
}
impl<T: CallbackParameter, F: Fn(T) + Send + Sync + 'static> From<F> for Callback<T> {
fn from(value: F) -> Self {
Self(Arc::new(value))
}
}
impl<T: CallbackParameter> IntoHandler<T> for Callback<T> {
type Handler = ();
fn into_handler(self) -> (Callback<T>, Self::Handler) {
(self, ())
}
}
impl<T: CallbackParameter, F, H> IntoHandler<T> for (F, H)
where
F: Fn(T) + Send + Sync + 'static,
{
type Handler = H;
fn into_handler(self) -> (Callback<T>, Self::Handler) {
(Callback::from(self.0), self.1)
}
}
impl<T: CallbackParameter, H> IntoHandler<T> for (Callback<T>, H) {
type Handler = H;
fn into_handler(self) -> (Callback<T>, Self::Handler) {
self
}
}
impl<T: CallbackParameter + Send + 'static> IntoHandler<T>
for (flume::Sender<T>, flume::Receiver<T>)
{
type Handler = flume::Receiver<T>;
fn into_handler(self) -> (Callback<T>, Self::Handler) {
let (sender, receiver) = self;
(
Callback::from(move |t| {
if let Err(e) = sender.send(t) {
tracing::error!("{}", e)
}
}),
receiver,
)
}
}
pub struct CallbackDrop<Callback, DropFn>
where
DropFn: FnMut() + Send + Sync + 'static,
{
pub callback: Callback,
pub drop: DropFn,
}
impl<Callback, DropFn> Drop for CallbackDrop<Callback, DropFn>
where
DropFn: FnMut() + Send + Sync + 'static,
{
fn drop(&mut self) {
(self.drop)()
}
}
impl<OnEvent, Event: CallbackParameter, DropFn> IntoHandler<Event> for CallbackDrop<OnEvent, DropFn>
where
OnEvent: Fn(Event) + Send + Sync + 'static,
DropFn: FnMut() + Send + Sync + 'static,
{
type Handler = ();
fn into_handler(self) -> (Callback<Event>, Self::Handler) {
(move |evt| (self.callback)(evt), ()).into_handler()
}
}