Skip to main content

dope_runtime/client/
provider.rs

1use std::marker;
2
3use dope_core::driver;
4
5use crate::{client, topology::lending};
6
7/// Produces a client from the exact selected provider.
8/// The provider type carries its storage loans; each client requires those loans
9/// and its driver domain to outlive the issued application scope.
10pub trait Provider<'d> {
11    type Client<'app>: 'app
12    where
13        Self: 'app,
14        'd: 'app;
15
16    fn provide<'app>(context: client::Context<'_, 'app, 'd, Self>) -> Self::Client<'app>
17    where
18        Self: 'app,
19        'd: 'app;
20}
21
22/// Owns two providers and issues their clients in the same lending scope.
23/// Both pinned roots remain owned until their dependent application is released.
24#[pin_project::pin_project]
25#[derive(dope_gen::Application)]
26#[dispatcher(core = ::dope_core, manifold = crate, runtime = crate, driver = 'd)]
27pub struct Pair<'d, A: lending::Root<'d>, B: lending::Root<'d>> {
28    #[dispatcher(state)]
29    scope: marker::PhantomData<(
30        driver::Reference<'d>,
31        *const A::Provider,
32        *const B::Provider,
33    )>,
34    #[pin]
35    #[app]
36    first: A,
37    #[pin]
38    #[app]
39    second: B,
40}
41
42impl<'d, A: lending::Root<'d>, B: lending::Root<'d>> Pair<'d, A, B> {
43    pub const fn new(first: A, second: B) -> Self {
44        Self {
45            scope: marker::PhantomData,
46            first,
47            second,
48        }
49    }
50}
51
52impl<'d, A: lending::Root<'d>, B: lending::Root<'d>> Provider<'d> for Pair<'d, A, B> {
53    type Client<'app>
54        = (
55        <A::Provider as Provider<'d>>::Client<'app>,
56        <B::Provider as Provider<'d>>::Client<'app>,
57    )
58    where
59        Self: 'app,
60        'd: 'app;
61
62    fn provide<'app>(context: client::Context<'_, 'app, 'd, Self>) -> Self::Client<'app>
63    where
64        Self: 'app,
65        'd: 'app,
66    {
67        let (pair, _) = context.into_parts();
68        let pair = pair.project_ref();
69        (
70            Provider::provide(client::Context::new(lending::Root::provider(pair.first))),
71            Provider::provide(client::Context::new(lending::Root::provider(pair.second))),
72        )
73    }
74}