use thiserror::Error;
use crate::{Signal, SubscriberNotification, SubscriptionLike};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SubscriptionNotification {
Unsubscribe,
}
#[derive(Error, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SubscriberToSubscriptionNotificationConversionError {
#[error("Subscriptions are unable to receive 'Next' notifications!")]
CannotReceiveNext,
#[error("Subscriptions are unable to receive 'Error' notifications!")]
CannotReceiveError,
#[error("Subscriptions are unable to receive 'Complete' notifications!")]
CannotReceiveComplete,
}
impl<In, InError> TryFrom<SubscriberNotification<In, InError>> for SubscriptionNotification
where
In: Signal,
InError: Signal,
{
type Error = SubscriberToSubscriptionNotificationConversionError;
fn try_from(value: SubscriberNotification<In, InError>) -> Result<Self, Self::Error> {
match value {
SubscriberNotification::Unsubscribe => Ok(SubscriptionNotification::Unsubscribe),
SubscriberNotification::Next(_) => {
Err(SubscriberToSubscriptionNotificationConversionError::CannotReceiveNext)
}
SubscriberNotification::Error(_) => {
Err(SubscriberToSubscriptionNotificationConversionError::CannotReceiveError)
}
SubscriberNotification::Complete => {
Err(SubscriberToSubscriptionNotificationConversionError::CannotReceiveComplete)
}
}
}
}
pub trait SubscriptionLikePushNotificationExtention: SubscriptionLike {
fn push(&mut self, notification: impl Into<SubscriptionNotification>);
}
impl<T: ?Sized> SubscriptionLikePushNotificationExtention for T
where
T: SubscriptionLike,
{
fn push(&mut self, notification: impl Into<SubscriptionNotification>) {
match notification.into() {
SubscriptionNotification::Unsubscribe => self.unsubscribe(),
}
}
}
#[cfg(test)]
mod test {
use super::*;
mod push {
use rx_core_macro_subscription_derive::RxSubscription;
use crate::SubscriptionLike;
use super::*;
#[derive(RxSubscription, Default)]
#[_rx_core_common_crate(crate)]
struct MockSubscription {
unsubscribed: bool,
}
impl SubscriptionLike for MockSubscription {
fn is_closed(&self) -> bool {
self.unsubscribed
}
fn unsubscribe(&mut self) {
self.unsubscribed = true;
}
}
#[test]
fn should_call_unsubscribe_when_pushing_an_unsubscribe_notification() {
let mut subscription = MockSubscription::default();
subscription.push(SubscriptionNotification::Unsubscribe);
assert!(subscription.is_closed());
}
}
mod subscriber_notification_try_conversion {
use super::*;
#[test]
fn should_not_convert_next() {
let subscription_notification: Result<SubscriptionNotification, _> =
SubscriberNotification::<usize>::Next(1).try_into();
assert_eq!(
subscription_notification,
Err(SubscriberToSubscriptionNotificationConversionError::CannotReceiveNext)
);
}
#[test]
fn should_not_convert_error() {
let subscription_notification: Result<SubscriptionNotification, _> =
SubscriberNotification::<usize, &'static str>::Error("error").try_into();
assert_eq!(
subscription_notification,
Err(SubscriberToSubscriptionNotificationConversionError::CannotReceiveError)
);
}
#[test]
fn should_not_convert_complete() {
let subscription_notification: Result<SubscriptionNotification, _> =
SubscriberNotification::<usize, &'static str>::Complete.try_into();
assert_eq!(
subscription_notification,
Err(SubscriberToSubscriptionNotificationConversionError::CannotReceiveComplete)
);
}
#[test]
fn should_convert_unsubscribe_successfully() {
let subscription_notification: Result<SubscriptionNotification, _> =
SubscriberNotification::<usize>::Unsubscribe.try_into();
assert_eq!(
subscription_notification,
Ok(SubscriptionNotification::Unsubscribe)
);
}
}
}