pushwire-client 0.1.1

Generic multiplexed push client with WebSocket and SSE transports
Documentation
//! Channel subscription management.
//!
//! Tracks which channels the client is subscribed to and builds the
//! `SystemOp::Subscribe` / `SystemOp::Unsubscribe` messages.

use dashmap::DashSet;
use pushwire_core::{ChannelKind, SystemOp};

/// Tracks active channel subscriptions.
pub(crate) struct SubscriptionTracker<C: ChannelKind> {
    channels: DashSet<C>,
}

impl<C: ChannelKind> SubscriptionTracker<C> {
    pub(crate) fn new() -> Self {
        Self {
            channels: DashSet::new(),
        }
    }

    /// Add channels to the subscription set. Returns the `Subscribe` system op
    /// if any channels were newly added.
    pub(crate) fn subscribe(&self, channels: &[C]) -> Option<SystemOp<C>> {
        let mut added = Vec::new();
        for ch in channels {
            if self.channels.insert(*ch) {
                added.push(*ch);
            }
        }
        if added.is_empty() {
            None
        } else {
            Some(SystemOp::Subscribe { channels: added })
        }
    }

    /// Remove channels from the subscription set. Returns the `Unsubscribe`
    /// system op if any channels were actually removed.
    pub(crate) fn unsubscribe(&self, channels: &[C]) -> Option<SystemOp<C>> {
        let mut removed = Vec::new();
        for ch in channels {
            if self.channels.remove(ch).is_some() {
                removed.push(*ch);
            }
        }
        if removed.is_empty() {
            None
        } else {
            Some(SystemOp::Unsubscribe { channels: removed })
        }
    }

    /// All currently subscribed channels.
    pub(crate) fn active(&self) -> Vec<C> {
        self.channels.iter().map(|c| *c).collect()
    }
}