use crate::Interceptor;
use crate::noop::NoopInterceptor;
#[derive(Clone)]
pub struct Registry<P> {
inner: P,
}
impl Registry<NoopInterceptor> {
pub fn new() -> Self {
Registry {
inner: NoopInterceptor::new(),
}
}
}
impl Default for Registry<NoopInterceptor> {
fn default() -> Self {
Self::new()
}
}
impl<P: Interceptor> Registry<P> {
pub fn from(inner: P) -> Self {
Registry { inner }
}
pub fn with<O, F>(self, f: F) -> Registry<O>
where
F: FnOnce(P) -> O,
O: Interceptor,
{
Registry {
inner: f(self.inner),
}
}
pub fn build(self) -> P {
self.inner
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::TaggedPacket;
use sansio::Protocol;
use shared::error::Error;
use std::time::Instant;
fn dummy_rtp_packet() -> TaggedPacket {
TaggedPacket {
now: Instant::now(),
transport: Default::default(),
message: crate::Packet::Rtp(rtp::Packet::default()),
}
}
struct TestInterceptor<P> {
inner: P,
name: &'static str,
}
impl<P> TestInterceptor<P> {
fn new(inner: P) -> Self {
Self {
inner,
name: "test",
}
}
fn with_name(name: &'static str) -> impl FnOnce(P) -> Self {
move |inner| Self { inner, name }
}
}
impl<P: Interceptor> Protocol<TaggedPacket, TaggedPacket, ()> for TestInterceptor<P> {
type Rout = TaggedPacket;
type Wout = TaggedPacket;
type Eout = ();
type Error = Error;
type Time = Instant;
fn handle_read(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
self.inner.handle_read(msg)
}
fn poll_read(&mut self) -> Option<Self::Rout> {
self.inner.poll_read()
}
fn handle_write(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
self.inner.handle_write(msg)
}
fn poll_write(&mut self) -> Option<Self::Wout> {
self.inner.poll_write()
}
}
impl<P: Interceptor> Interceptor for TestInterceptor<P> {
fn bind_local_stream(&mut self, info: &crate::StreamInfo) {
self.inner.bind_local_stream(info);
}
fn unbind_local_stream(&mut self, info: &crate::StreamInfo) {
self.inner.unbind_local_stream(info);
}
fn bind_remote_stream(&mut self, info: &crate::StreamInfo) {
self.inner.bind_remote_stream(info);
}
fn unbind_remote_stream(&mut self, info: &crate::StreamInfo) {
self.inner.unbind_remote_stream(info);
}
}
#[test]
fn test_registry_new() {
let registry = Registry::new();
let mut chain = registry.build();
let pkt = dummy_rtp_packet();
chain.handle_read(pkt).unwrap();
assert!(chain.poll_read().is_some());
}
#[test]
fn test_registry_with_single_interceptor() {
let registry = Registry::new().with(TestInterceptor::new);
let mut chain = registry.build();
let pkt = dummy_rtp_packet();
chain.handle_read(pkt).unwrap();
assert!(chain.poll_read().is_some());
assert_eq!(chain.name, "test");
}
#[test]
fn test_registry_with_multiple_interceptors() {
let registry = Registry::new()
.with(TestInterceptor::with_name("inner"))
.with(TestInterceptor::with_name("outer"));
let mut chain = registry.build();
let pkt = dummy_rtp_packet();
chain.handle_read(pkt).unwrap();
assert!(chain.poll_read().is_some());
assert_eq!(chain.name, "outer");
assert_eq!(chain.inner.name, "inner");
}
#[test]
fn test_registry_from_inner() {
let custom = NoopInterceptor::new();
let registry = Registry::from(custom).with(TestInterceptor::new);
let mut chain = registry.build();
let pkt = dummy_rtp_packet();
let pkt_message = pkt.message.clone();
chain.handle_write(pkt).unwrap();
assert_eq!(chain.poll_write().unwrap().message, pkt_message);
}
fn register_test_interceptors<P: Interceptor>(
registry: Registry<P>,
) -> Registry<TestInterceptor<TestInterceptor<P>>> {
registry
.with(TestInterceptor::with_name("first"))
.with(TestInterceptor::with_name("second"))
}
#[test]
fn test_helper_function_pattern() {
let registry = Registry::new();
let registry = register_test_interceptors(registry);
let mut chain = registry.build();
let pkt = dummy_rtp_packet();
chain.handle_read(pkt).unwrap();
assert!(chain.poll_read().is_some());
assert_eq!(chain.name, "second");
assert_eq!(chain.inner.name, "first");
}
}