use crate::{async_rt, Interest, Preferences};
use futures_channel::oneshot;
use futures_lite::{stream, StreamExt as _};
pub trait CallbackFn: FnMut(Preferences) + Send + Sync + 'static {}
impl<F> CallbackFn for F where F: FnMut(Preferences) + Send + Sync + 'static {}
pub struct Subscription(
#[expect(dead_code, reason = "only used to send a canceled message on drop")]
Option<oneshot::Sender<()>>,
);
#[cfg(test)]
static_assertions::assert_impl_all!(Subscription: Send, Sync);
impl Preferences {
#[doc = include_str!("doc/caveats.md")]
pub fn subscribe(interest: Interest, mut callback: impl CallbackFn) -> Subscription {
if interest.is_empty() {
return Subscription(None);
}
let (sender, receiver) = oneshot::channel();
let mut stream = Self::stream(interest)
.map(Message::Preferences)
.race(stream::once_future(receiver).map(|_| Message::Shutdown));
async_rt::spawn_future(async move {
while let Some(message) = stream.next().await {
match message {
Message::Preferences(preferences) => callback(preferences),
Message::Shutdown => break,
}
}
});
Subscription(Some(sender))
}
}
enum Message {
Preferences(Preferences),
Shutdown,
}