Skip to main content

dope_core/driver/route/
token.rs

1use core::{hash, marker, num};
2
3use o3::base::marker::ThreadBound;
4
5use crate::driver::{
6    route,
7    route::{Epoch, indices, indices::SlotIndex, kind, table},
8};
9
10#[derive(Clone, Copy, PartialEq, Eq, Debug)]
11#[repr(C)]
12pub struct Token {
13    pub(super) epoch: num::NonZero<u64>,
14    pub(super) thread: ThreadBound,
15    pub(super) meta: u64,
16}
17
18impl hash::Hash for Token {
19    fn hash<H: hash::Hasher>(&self, state: &mut H) {
20        hash::Hash::hash(&self.epoch.get(), state);
21        hash::Hash::hash(&self.meta, state);
22    }
23}
24
25impl Token {
26    pub(in crate::driver) const fn from_flight(
27        epoch: route::Epoch,
28        payload: [u8; 6],
29        kind: kind::Native,
30        route: route::Route,
31    ) -> Self {
32        let (epoch, thread) = epoch.into_parts();
33        let [a, b, c, d, e, f] = payload;
34        Self {
35            epoch,
36            thread,
37            meta: u64::from_le_bytes([a, b, c, d, e, f, kind as u8, route.raw()]),
38        }
39    }
40
41    const fn pack(
42        route: route::Route,
43        kind: u8,
44        slot: indices::SlotIndex,
45        epoch: route::Epoch,
46    ) -> Self {
47        let (epoch, thread) = epoch.into_parts();
48        Self {
49            epoch,
50            thread,
51            meta: ((route.raw() as u64) << route::SHIFT)
52                | ((kind as u64) << route::KIND_SHIFT)
53                | slot.raw() as u64,
54        }
55    }
56
57    pub const fn route(self) -> route::Route {
58        route::Route::from_bits((self.meta >> route::SHIFT) as u8)
59    }
60
61    pub const fn kind(self) -> Result<kind::Kind, kind::Unknown> {
62        let raw = self.kind_raw();
63        match raw {
64            0 => Ok(kind::Kind::Unspecified),
65            1 => Ok(kind::Kind::Accept),
66            2 => Ok(kind::Kind::Recv),
67            3 => Ok(kind::Kind::Send),
68            5 => Ok(kind::Kind::Socket),
69            6 => Ok(kind::Kind::Connect),
70            7 => Ok(kind::Kind::Shutdown),
71            11 => Ok(kind::Kind::Open),
72            19 => Ok(kind::Kind::OneShot),
73            21 => Ok(kind::Kind::TaskQueue),
74            25 => Ok(kind::Kind::Tuning),
75            28 => Ok(kind::Kind::Write),
76            29 => Ok(kind::Kind::Sync),
77            unknown => Err(kind::Unknown::new(unknown)),
78        }
79    }
80
81    pub(crate) const fn kind_raw(self) -> u8 {
82        (self.meta >> route::KIND_SHIFT) as u8
83    }
84
85    pub const fn slot(self) -> indices::SlotIndex {
86        SlotIndex::from_field(self.meta)
87    }
88
89    pub const fn epoch(self) -> route::Epoch {
90        Epoch::new(self.epoch, self.thread)
91    }
92
93    pub(super) const fn encode<Tag, C>(parts: table::Parts<Tag>) -> Self
94    where
95        Tag: route::Select<C>,
96        C: kind::Class,
97    {
98        Self::pack(Tag::ROUTE, C::CODE.raw(), parts.slot(), parts.epoch())
99    }
100
101    #[doc(hidden)]
102    pub const fn from_parts<Tag: route::Tag>(parts: table::Parts<Tag>) -> Self {
103        Self::pack(
104            Tag::ROUTE,
105            <Tag::Class as kind::Class>::CODE.raw(),
106            parts.slot(),
107            parts.epoch(),
108        )
109    }
110}
111
112#[derive(Clone, Copy, Debug)]
113pub(crate) struct Brand<'d, Tag> {
114    pub(super) driver: crate::driver::Invariant<'d>,
115    tag: marker::PhantomData<*mut Tag>,
116}
117
118impl<'d, Tag> Brand<'d, Tag> {
119    pub(crate) const fn new(driver: crate::driver::Invariant<'d>) -> Self {
120        Self {
121            driver,
122            tag: marker::PhantomData,
123        }
124    }
125}
126
127#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
128#[repr(transparent)]
129pub(crate) struct OutboundKey(u8);
130
131impl OutboundKey {
132    pub(crate) const fn raw(self) -> u32 {
133        self.0 as u32
134    }
135
136    pub(crate) const fn from_raw(raw: u32) -> Option<Self> {
137        if raw < route::FRAMEWORK as u32 {
138            Some(Self(raw as u8))
139        } else {
140            None
141        }
142    }
143
144    /// Type-branded outbound key for callers that carry an application route tag.
145    pub(crate) const fn for_tag<Tag: route::Tag>() -> Self {
146        const { assert!(Tag::ROUTE.raw() != route::FRAMEWORK) };
147        Self(Tag::ROUTE.raw())
148    }
149}