Skip to main content

dope_core/driver/route/
target.rs

1use core::{fmt, hash, marker, mem};
2
3use crate::driver::route::{self, table};
4
5/// One generation-checked target branded by its driver lifetime and route.
6///
7/// ```compile_fail
8/// use dope_core::driver::route::{KeyTag, Target};
9///
10/// fn rebrand<'a, 'b>(target: Target<'a, KeyTag<1>>) -> Target<'b, KeyTag<1>> {
11///     target
12/// }
13/// ```
14#[derive(Clone, Copy)]
15#[repr(transparent)]
16pub struct Target<'d, Tag: route::Tag> {
17    parts: table::Parts<Tag>,
18    driver: marker::PhantomData<fn(&'d ()) -> &'d ()>,
19}
20
21impl<'d, Tag: route::Tag> Target<'d, Tag> {
22    pub(super) const fn from_parts(parts: table::Parts<Tag>) -> Self {
23        Self {
24            parts,
25            driver: marker::PhantomData,
26        }
27    }
28
29    pub const fn parts(self) -> table::Parts<Tag> {
30        self.parts
31    }
32
33    pub const fn slot(self) -> route::SlotIndex {
34        self.parts.slot()
35    }
36
37    pub const fn epoch(self) -> route::Epoch {
38        self.parts.epoch()
39    }
40
41    pub const fn bind<T>(self, value: T) -> route::Bound<'d, Tag, T> {
42        route::Bound::new(self, value)
43    }
44
45    pub const fn operation(self, kind: u8) -> route::Operation<'d, Tag> {
46        route::Operation::new(route::Token::from_target(self).with_kind(kind))
47    }
48
49    pub const fn dispatch(self) -> route::Operation<'d, Tag> {
50        self.operation(Tag::KIND)
51    }
52}
53
54impl<Tag: route::Tag> PartialEq for Target<'_, Tag> {
55    fn eq(&self, other: &Self) -> bool {
56        self.parts == other.parts
57    }
58}
59
60impl<Tag: route::Tag> Eq for Target<'_, Tag> {}
61
62impl<Tag: route::Tag> hash::Hash for Target<'_, Tag> {
63    fn hash<H: hash::Hasher>(&self, state: &mut H) {
64        self.parts.hash(state);
65    }
66}
67
68impl<Tag: route::Tag> fmt::Debug for Target<'_, Tag> {
69    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
70        formatter
71            .debug_struct("Target")
72            .field("route", &Tag::ROUTE)
73            .field("kind", &Tag::KIND)
74            .field("slot", &self.slot())
75            .field("epoch", &self.epoch())
76            .finish()
77    }
78}
79
80const _: () = {
81    assert!(mem::size_of::<Target<'static, route::KeyTag<1>>>() == mem::size_of::<route::Token>());
82    assert!(
83        mem::align_of::<Target<'static, route::KeyTag<1>>>() == mem::align_of::<route::Token>()
84    );
85};