use disqualified::ShortName;
use crate::{SubscriptionClosedFlag, SubscriptionLike, Teardown, TeardownCollection};
use std::{fmt::Debug, vec};
pub struct SubscriptionData {
closed_flag: SubscriptionClosedFlag,
finalizers: Vec<Box<dyn FnOnce() + Send + Sync>>,
}
impl SubscriptionData {
pub fn new_with_teardown(teardown: Teardown) -> Self {
if let Some(teardown) = teardown.take() {
Self {
closed_flag: false.into(),
finalizers: vec![teardown],
}
} else {
Self::default()
}
}
}
impl Default for SubscriptionData {
fn default() -> Self {
Self {
finalizers: Vec::new(),
closed_flag: false.into(),
}
}
}
impl SubscriptionLike for SubscriptionData {
#[inline]
fn is_closed(&self) -> bool {
*self.closed_flag
}
fn unsubscribe(&mut self) {
if !self.is_closed() {
self.closed_flag.close();
for teardown in self.finalizers.drain(..) {
(teardown)();
}
}
}
}
impl TeardownCollection for SubscriptionData {
fn add_teardown(&mut self, teardown: Teardown) {
if self.is_closed() {
teardown.execute();
} else if let Some(teardown_fn) = teardown.take() {
self.finalizers.push(teardown_fn);
}
}
}
impl Debug for SubscriptionData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(
"{} {{ is_closed: {}, finalizers: {} }}",
ShortName::of::<Self>(),
self.is_closed(),
self.finalizers.len()
))
}
}
impl Drop for SubscriptionData {
fn drop(&mut self) {
if !self.is_closed() {
self.unsubscribe();
}
}
}