use arc_swap::ArcSwapOption; use never::Never; use std::sync::Arc; use callbag::{Callbag, Message}; #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum MessageDirection { FromUp, FromDown, } pub trait VariantName { fn variant_name(&self) -> &'static str; } impl VariantName for Message { fn variant_name(&self) -> &'static str { match self { Message::Handshake(_) => "Handshake", Message::Data(_) => "Data", Message::Pull => "Pull", Message::Error(_) => "Error", Message::Terminate => "Terminate", } } } /// See fn noop(_message: Message) {} /// See pub fn never(message: Message) { if let Message::Handshake(sink) = message { sink(Message::Handshake(Arc::new(noop.into()))); } } /// See pub fn make_mock_callbag( name: &'static str, report: R, is_source: bool, ) -> (Callbag, impl Fn(Message)) where I: Clone, O: Clone, R: Fn(&'static str, MessageDirection, Message) + Send + Sync, { let report = Arc::new(report); let talkback_ref = Arc::new(ArcSwapOption::from(None)); let mock = { let talkback_ref = Arc::clone(&talkback_ref); move |message: Message| { report(name, MessageDirection::FromUp, message.clone()); if let Message::Handshake(talkback) = message { talkback_ref.store(Some(Arc::clone(&talkback))); if is_source { let talkback_ref = talkback_ref.load(); let talkback = talkback_ref.as_ref().unwrap(); talkback(Message::Handshake(Arc::new( { let report = report.clone(); move |message| { report(name, MessageDirection::FromDown, message); } } .into(), ))); } } } }; let emit = move |message| { let talkback_ref = talkback_ref.load(); let talkback = talkback_ref.as_ref().unwrap(); talkback(message); }; (mock.into(), emit) }