use serde_json::Value;
use proxima_core::ProximaError;
use proxima_core::factory::Named;
use proxima_core::signal::Signal;
use crate::pipe::alloc_tier;
use crate::pipe::primitives::SendPipe;
pub trait SourcePipe: SendPipe<In = Signal, Out = (), Err = ProximaError> {}
impl<Implementor> SourcePipe for Implementor where
Implementor: SendPipe<In = Signal, Out = (), Err = ProximaError>
{
}
pub type SourceHandle = alloc_tier::PipeHandle<Signal, ()>;
pub fn into_source_handle<Implementor>(pipe: Implementor) -> SourceHandle
where
Implementor: SendPipe<In = Signal, Out = (), Err = ProximaError> + 'static,
{
alloc_tier::into_handle(pipe)
}
pub trait SourceFactory: Named {
fn build(&self, spec: &Value) -> Result<SourceHandle, ProximaError>;
}
pub type SourceFactoryRegistry = proxima_core::FactoryRegistry<dyn SourceFactory>;
#[cfg(all(test, not(loom)))]
#[allow(clippy::unwrap_used, clippy::expect_used)]
mod tests {
use super::*;
use core::future::Future;
use core::sync::atomic::{AtomicUsize, Ordering};
struct CountingSource {
calls: alloc::sync::Arc<AtomicUsize>,
}
impl SendPipe for CountingSource {
type In = Signal;
type Out = ();
type Err = ProximaError;
fn call(&self, _cancel: Signal) -> impl Future<Output = Result<(), ProximaError>> + Send {
self.calls.fetch_add(1, Ordering::SeqCst);
async move { Ok(()) }
}
}
#[proxima::test]
async fn source_handle_dispatches_to_inner() {
let calls = alloc::sync::Arc::new(AtomicUsize::new(0));
let handle: SourceHandle = into_source_handle(CountingSource {
calls: calls.clone(),
});
let signal = Signal::new();
SendPipe::call(&handle, signal).await.expect("call");
assert_eq!(calls.load(Ordering::SeqCst), 1);
}
}