Skip to main content

AsyncHostedDep

Trait AsyncHostedDep 

Source
pub trait AsyncHostedDep:
    Sized
    + Send
    + Sync
    + 'static {
    // Required methods
    fn descriptor(&self) -> Vec<u8> ;
    fn from_descriptor(bytes: &[u8]) -> impl Future<Output = Self> + Send;
}
Expand description

Async counterpart of HostedDep. Implement this when worker-side reconstruction needs to .await (e.g. opening async network clients, doing async filesystem work, calling Provided*::new(...).await constructors).

No opt-in flag is required: the helper functions emitted by #[test_dep(scope = Hosted)] auto-select the async path under the tokio runtime, so simply implementing AsyncHostedDep is enough.

#[test_dep(scope = Hosted)]
async fn dependencies() -> EnvBasedTestDependencies { /* … */ }

impl test_r::core::AsyncHostedDep for EnvBasedTestDependencies {
    fn descriptor(&self) -> Vec<u8> { /* … */ }

    async fn from_descriptor(bytes: &[u8]) -> Self { /* … */ }
}

AsyncHostedDep is the tokio-only async counterpart of HostedDep. Under the tokio test runtime the Hosted helper functions emitted by #[test_dep(scope = Hosted)] always go through AsyncHostedDep, regardless of whether the user wrote impl HostedDep (covered by the blanket bridge below) or impl AsyncHostedDep directly. Under the sync runtime, the same helpers stay on HostedDep: a scope = Hosted registration that uses an async-only AsyncHostedDep type therefore fails to compile in sync builds. (Writing the impl on its own still compiles fine; only the #[test_dep(scope = Hosted)] registration fails.)

descriptor() stays synchronous and is called on the parent owner value, exactly as in HostedDep; the only difference is that from_descriptor returns a Future so worker-side reconstruction can await.

The legacy async_worker attribute is deprecated and ignored (it now only triggers a compile-time deprecation warning at the dep’s registration site); remove it from any new code.

Required Methods§

Source

fn descriptor(&self) -> Vec<u8>

Owner-side: produce the descriptor bytes that workers will use to reconstruct a connected handle. Called from the parent runner process exactly once per Hosted dep, just like HostedDep::descriptor.

Source

fn from_descriptor(bytes: &[u8]) -> impl Future<Output = Self> + Send

Worker-side: asynchronously reconstruct a handle from descriptor bytes received from the parent.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl<T> AsyncHostedDep for T
where T: HostedDep,

Blanket bridge: every HostedDep is automatically also an AsyncHostedDep. The bridged from_descriptor returns std::future::ready, so the bridge itself adds only an immediately-ready future and the runtime can await all Hosted reconstruction uniformly.

This lets the test-r runtime drive every Hosted descriptor reconstruction through one async path under the tokio runtime, regardless of whether the dep’s own implementation is sync (impl HostedDep for ...) or async (impl AsyncHostedDep for ...). The async_worker macro flag is unnecessary — the implementor picks sync vs async purely at the trait-impl call site.

Cost: the bridge itself is negligible (ready(x).await is an immediately-ready future); when the runtime later routes every Hosted reconstruction through the async path there is still a small async-wrapper overhead per worker-startup-per-dep (polling the outer future, and possibly one boxed-future allocation from WorkerReconstructor::Async), but no extra user-level async work.

Coherence note: on stable Rust, with this blanket impl in place a concrete type cannot manually implement both HostedDep and AsyncHostedDep — rustc rejects that as conflicting implementations. That compile-time error is the intended signal that one of the two manual impls is redundant and should be removed.

Source-compat note: if downstream code imports both HostedDep and AsyncHostedDep into the same scope and calls trait methods by method syntax (e.g. MyType::from_descriptor(bytes) or dep.descriptor()), the call can become ambiguous now that one type satisfies both traits. Resolve with UFCS — <MyType as HostedDep>::from_descriptor(bytes).