zmux 1.0.0

Rust implementation of the ZMux v1 stream multiplexing protocol
Documentation
use crate::error::Error;
use crate::payload::StreamMetadata;
use crate::session::SessionState;
use std::fmt;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::sync::Arc;
use std::time::SystemTime;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum EventType {
    StreamOpened,
    StreamAccepted,
    SessionClosed,
}

impl EventType {
    #[inline]
    pub fn as_str(self) -> &'static str {
        match self {
            Self::StreamOpened => "stream_opened",
            Self::StreamAccepted => "stream_accepted",
            Self::SessionClosed => "session_closed",
        }
    }
}

impl fmt::Display for EventType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

impl AsRef<str> for EventType {
    #[inline]
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StreamEventInfo {
    pub stream_id: u64,
    pub metadata: StreamMetadata,
    pub local: bool,
    pub bidirectional: bool,
    pub application_visible: bool,
}

impl StreamEventInfo {
    #[inline]
    pub fn open_info(&self) -> &[u8] {
        &self.metadata.open_info
    }

    #[inline]
    pub fn open_info_len(&self) -> usize {
        self.metadata.open_info.len()
    }

    #[inline]
    pub fn has_open_info(&self) -> bool {
        !self.metadata.open_info.is_empty()
    }
}

#[derive(Debug, Clone)]
pub struct Event {
    pub event_type: EventType,
    pub session_state: SessionState,
    pub stream_id: u64,
    pub stream: Option<StreamEventInfo>,
    pub local: bool,
    pub bidirectional: bool,
    pub time: SystemTime,
    pub error: Option<Error>,
    pub application_visible: bool,
}

pub type EventHandler = Arc<dyn Fn(Event) + Send + Sync + 'static>;

#[inline]
pub(crate) fn dispatch_event(handler: &EventHandler, event: Event) {
    let _ = catch_unwind(AssertUnwindSafe(|| handler(event)));
}

#[cfg(test)]
mod tests {
    use super::EventType;

    #[test]
    fn event_type_is_displayable_and_string_borrowable() {
        assert_eq!(EventType::StreamOpened.as_str(), "stream_opened");
        assert_eq!(EventType::StreamAccepted.to_string(), "stream_accepted");
        assert_eq!(EventType::SessionClosed.as_ref(), "session_closed");
    }
}