1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use std::marker::PhantomData;
use dope_core::driver::token::{SlotIndex, Token};
use super::Manifold;
#[repr(transparent)]
pub struct TypedToken<M>(Token, PhantomData<*mut M>);
impl<M> Clone for TypedToken<M> {
fn clone(&self) -> Self {
*self
}
}
impl<M> Copy for TypedToken<M> {}
impl<M> TypedToken<M> {
pub const fn try_new<'d>(token: Token) -> Option<Self>
where
M: Manifold<'d>,
{
if token.route() == M::ID {
Some(Self(token, PhantomData))
} else {
None
}
}
/// # Safety
/// The caller guarantees `t` was issued for manifold `M`.
pub const unsafe fn new_unchecked(token: Token) -> Self {
Self(token, PhantomData)
}
/// Retags a token while statically proving that both manifolds own the
/// same runtime route.
///
/// This is the zero-cost forwarding operation for transparent manifold
/// wrappers. A differing pair of route IDs fails during monomorphization
/// rather than adding a runtime branch.
///
/// ```compile_fail
/// use std::pin::Pin;
///
/// use dope::manifold::Manifold;
/// use dope::manifold::typed::TypedToken;
/// use dope::{DriverContext, Token};
///
/// struct Outer;
/// struct Inner;
///
/// impl<'d> Manifold<'d> for Outer {
/// const ID: u8 = 1;
/// fn pre_park(self: Pin<&mut Self>, _: &mut DriverContext<'_, 'd>) {}
/// }
///
/// impl<'d> Manifold<'d> for Inner {
/// const ID: u8 = 2;
/// fn pre_park(self: Pin<&mut Self>, _: &mut DriverContext<'_, 'd>) {}
/// }
///
/// fn forward<'d>(token: TypedToken<Outer>) -> TypedToken<Inner> {
/// token.retag::<'d, Inner>()
/// }
/// ```
pub const fn retag<'d, N>(self) -> TypedToken<N>
where
M: Manifold<'d>,
N: Manifold<'d>,
{
const {
assert!(
M::ID == N::ID,
"cannot retag a token across different manifold routes"
)
};
TypedToken(self.0, PhantomData)
}
pub const fn into_inner(self) -> Token {
self.0
}
pub const fn slot(self) -> SlotIndex {
self.0.slot()
}
}