use std::sync::{Arc, Mutex, Weak};
use crate::{TransportBinding, TransportHandle, TransportJoinFuture, TransportRuntime};
use boxology_contract::{CapabilityDescriptor, CapabilityShape, Detail, ExposureLevel};
pub struct StubTransport {
runtime: Mutex<Option<Weak<TransportRuntime<()>>>>,
}
impl StubTransport {
pub fn new() -> Self {
Self {
runtime: Mutex::new(None),
}
}
pub fn runtime(&self) -> Option<Arc<TransportRuntime<()>>> {
self.runtime
.lock()
.expect("stub runtime lock poisoned")
.as_ref()
.and_then(Weak::upgrade)
}
}
impl Default for StubTransport {
fn default() -> Self {
Self::new()
}
}
pub struct StubTransportHandle {
_runtime: Arc<TransportRuntime<()>>,
}
impl TransportHandle for StubTransportHandle {
fn stop_intake(&self) {}
fn cancel_tasks(&self) {}
fn abort_tasks(&self) {}
fn join_tasks(self: Box<Self>) -> TransportJoinFuture {
Box::pin(std::future::ready(Ok(())))
}
}
impl TransportBinding for StubTransport {
type Config = ();
type Handle = StubTransportHandle;
fn config(&self) -> Arc<()> {
Arc::new(())
}
fn conform(
&self,
descriptor: &CapabilityDescriptor,
_level: ExposureLevel,
) -> Result<(), Detail> {
match descriptor.shape() {
CapabilityShape::Unary => Ok(()),
_ => Err(Detail::new("unsupported_interaction_shape")
.with_message("stub transport supports unary capabilities only")),
}
}
fn prepare(&self, _descriptors: &[&'static CapabilityDescriptor]) -> Result<(), Detail> {
Ok(())
}
fn start(&self, runtime: TransportRuntime<()>) -> Result<StubTransportHandle, Detail> {
let mut probe = self.runtime.lock().expect("stub runtime lock poisoned");
if probe.is_some() {
return Err(Detail::new("stub_already_started"));
}
let runtime = Arc::new(runtime);
*probe = Some(Arc::downgrade(&runtime));
Ok(StubTransportHandle { _runtime: runtime })
}
}