use super::Subscription;
pub trait BoxedSubscriptionInner {
fn boxed_unsubscribe(self: Box<Self>);
fn boxed_is_closed(&self) -> bool;
}
impl<T: Subscription> BoxedSubscriptionInner for T {
#[inline]
fn boxed_unsubscribe(self: Box<Self>) { (*self).unsubscribe() }
#[inline]
fn boxed_is_closed(&self) -> bool { self.is_closed() }
}
pub struct BoxedSubscription(Box<dyn BoxedSubscriptionInner>);
pub struct BoxedSubscriptionSend(Box<dyn BoxedSubscriptionInner + Send>);
impl BoxedSubscription {
#[inline]
pub fn new(subscription: impl Subscription + 'static) -> Self { Self(Box::new(subscription)) }
}
impl BoxedSubscriptionSend {
#[inline]
pub fn new(subscription: impl Subscription + Send + 'static) -> Self {
Self(Box::new(subscription))
}
}
pub trait IntoBoxedSubscription<Target> {
fn into_boxed(self) -> Target;
}
impl<T: Subscription + 'static> IntoBoxedSubscription<BoxedSubscription> for T {
#[inline]
fn into_boxed(self) -> BoxedSubscription { BoxedSubscription::new(self) }
}
impl<T: Subscription + Send + 'static> IntoBoxedSubscription<BoxedSubscriptionSend> for T {
#[inline]
fn into_boxed(self) -> BoxedSubscriptionSend { BoxedSubscriptionSend::new(self) }
}
impl Subscription for BoxedSubscription {
#[inline]
fn unsubscribe(self) { self.0.boxed_unsubscribe() }
#[inline]
fn is_closed(&self) -> bool { self.0.boxed_is_closed() }
}
impl Subscription for BoxedSubscriptionSend {
#[inline]
fn unsubscribe(self) { self.0.boxed_unsubscribe() }
#[inline]
fn is_closed(&self) -> bool { self.0.boxed_is_closed() }
}
#[cfg(test)]
mod tests {
use std::{cell::RefCell, rc::Rc};
use super::*;
struct MockSubscription {
closed: Rc<RefCell<bool>>,
}
impl MockSubscription {
fn new() -> (Self, Rc<RefCell<bool>>) {
let closed = Rc::new(RefCell::new(false));
(Self { closed: closed.clone() }, closed)
}
}
impl Subscription for MockSubscription {
fn unsubscribe(self) { *self.closed.borrow_mut() = true; }
fn is_closed(&self) -> bool { *self.closed.borrow() }
}
#[rxrust_macro::test]
fn test_local_boxed_subscription() {
let (mock, closed) = MockSubscription::new();
let boxed = BoxedSubscription::new(mock);
assert!(!boxed.is_closed());
boxed.unsubscribe();
assert!(*closed.borrow());
}
#[rxrust_macro::test]
fn test_local_boxed_subscription_with_unit() {
let boxed = BoxedSubscription::new(());
assert!(boxed.is_closed()); boxed.unsubscribe(); }
#[rxrust_macro::test]
fn test_boxed_subscription_in_collection() {
let (mock1, closed1) = MockSubscription::new();
let (mock2, closed2) = MockSubscription::new();
let subs: Vec<BoxedSubscription> =
vec![BoxedSubscription::new(mock1), BoxedSubscription::new(mock2)];
assert!(!*closed1.borrow());
assert!(!*closed2.borrow());
for sub in subs {
sub.unsubscribe();
}
assert!(*closed1.borrow());
assert!(*closed2.borrow());
}
}