#[cfg(feature = "testing")]
use std::sync::Arc;
#[cfg(feature = "testing")]
use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(feature = "testing")]
use ruststream::testing::Coordinator;
#[cfg(feature = "testing")]
use crate::in_process::{ReaderId, Server};
#[derive(Clone, Debug, Default)]
pub(crate) struct Loopback {
#[cfg(feature = "testing")]
server: Option<Arc<Server>>,
}
#[derive(Debug, Default)]
pub(crate) struct Tap {
#[cfg(feature = "testing")]
reader: Option<(Arc<Server>, ReaderId)>,
}
#[derive(Debug, Default)]
#[cfg_attr(
not(feature = "testing"),
allow(
unreachable_pub,
reason = "a window's settle side names it under `testing` only"
)
)]
pub struct InFlight {
#[cfg(feature = "testing")]
coordinator: Option<Coordinator>,
}
#[cfg(not(feature = "testing"))]
const _: () = assert!(size_of::<Loopback>() == 0);
#[cfg(not(feature = "testing"))]
const _: () = assert!(size_of::<Tap>() == 0);
#[cfg(not(feature = "testing"))]
const _: () = assert!(size_of::<InFlight>() == 0);
impl Tap {
#[cfg_attr(
not(feature = "testing"),
allow(
clippy::unused_self,
reason = "the registration is read under `testing` only"
)
)]
pub(crate) fn delivered(&self) -> InFlight {
#[cfg(feature = "testing")]
{
InFlight {
coordinator: self
.reader
.as_ref()
.and_then(|(server, _)| server.coordinator()),
}
}
#[cfg(not(feature = "testing"))]
{
InFlight {}
}
}
}
#[cfg(feature = "testing")]
impl Loopback {
pub(crate) const fn to(server: Arc<Server>) -> Self {
Self {
server: Some(server),
}
}
pub(crate) const fn server(&self) -> Option<&Arc<Server>> {
self.server.as_ref()
}
pub(crate) fn now_ms(&self) -> u64 {
self.server
.as_ref()
.map_or_else(system_ms, |server| server.now_ms())
}
}
#[cfg(feature = "testing")]
fn system_ms() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_or(0, |d| u64::try_from(d.as_millis()).unwrap_or(u64::MAX))
}
#[cfg(feature = "testing")]
impl Tap {
pub(crate) const fn registered(server: Arc<Server>, reader: ReaderId) -> Self {
Self {
reader: Some((server, reader)),
}
}
pub(crate) const fn in_process(&self) -> bool {
self.reader.is_some()
}
pub(crate) async fn readable(&self) {
if let Some((server, reader)) = &self.reader {
server.readable(*reader).await;
}
}
pub(crate) fn discard(&self, n: usize) {
if let Some((server, _)) = &self.reader {
server.released(n);
}
}
}
#[cfg(feature = "testing")]
impl Drop for Tap {
fn drop(&mut self) {
if let Some((server, reader)) = self.reader.take() {
server.detach(reader);
}
}
}
#[cfg(feature = "testing")]
impl Drop for InFlight {
fn drop(&mut self) {
if let Some(coordinator) = self.coordinator.take() {
coordinator.consumed();
}
}
}