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 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}