1use core::marker;
3
4use o3::{
5 base::marker::ThreadBound,
6 buffer::{resident, segments},
7};
8
9use crate::duplex::machine;
10
11type Owner<'turn, D> = marker::PhantomData<(
12 D,
13 ThreadBound,
14 fn(D) -> D,
15 fn(&'turn mut ()) -> &'turn mut (),
16)>;
17
18#[must_use = "classify this emitted duplex turn"]
20pub struct Emission<'turn, 'd, D> {
21 pub(in crate::duplex) payload: Payload<'turn, 'd, D>,
22 pub(in crate::duplex) end: machine::End,
23 pub(in crate::duplex) after: machine::After,
24}
25
26impl<'turn, 'd, D> Emission<'turn, 'd, D> {
27 pub fn into_parts(self) -> (Payload<'turn, 'd, D>, machine::End, machine::After) {
28 (self.payload, self.end, self.after)
29 }
30}
31
32#[must_use = "consume the payload and its admission permission"]
34pub enum Payload<'turn, 'd, D> {
35 Present {
36 output: segments::Nonempty<resident::Shared<'d>>,
37 permit: Permit<'turn, Present, D>,
38 },
39 Vacant(Permit<'turn, Vacant, D>),
40}
41
42pub enum Present {}
44
45pub enum Vacant {}
47
48#[must_use = "classify this carrier admission attempt"]
50pub struct Permit<'turn, M, D> {
51 pub(in crate::duplex) owner: Owner<'turn, D>,
52 pub(in crate::duplex) mode: marker::PhantomData<M>,
53}
54
55impl<'turn, M, D> Permit<'turn, M, D> {
56 pub fn commit<'d, R, E>(self, receipt: R) -> Admission<'turn, 'd, D, R, E> {
57 Admission::new(self.owner, Decision::Committed { receipt })
58 }
59}
60
61impl<'turn, D> Permit<'turn, Present, D> {
62 pub fn pending<'d, R, E>(
63 self,
64 rest: segments::Nonempty<resident::Shared<'d>>,
65 receipt: R,
66 ) -> Admission<'turn, 'd, D, R, E> {
67 Admission::new(
68 self.owner,
69 Decision::Pending {
70 remainder: rest,
71 receipt,
72 },
73 )
74 }
75
76 pub fn returned<'d, R, E>(
77 self,
78 error: E,
79 rest: segments::Nonempty<resident::Shared<'d>>,
80 ) -> Admission<'turn, 'd, D, R, E> {
81 Admission::new(
82 self.owner,
83 Decision::Returned {
84 error,
85 remainder: rest,
86 },
87 )
88 }
89}
90
91impl<'turn, D> Permit<'turn, Vacant, D> {
92 pub fn blocked<'d, R, E>(self, receipt: R) -> Admission<'turn, 'd, D, R, E> {
93 Admission::new(self.owner, Decision::Blocked { receipt })
94 }
95
96 pub fn reject<'d, R, E>(self, error: E) -> Admission<'turn, 'd, D, R, E> {
97 Admission::new(self.owner, Decision::Rejected { error })
98 }
99}
100
101#[must_use = "return this disposition to the duplex machine"]
103#[repr(transparent)]
104pub struct Admission<'turn, 'd, D, R, E> {
105 pub(in crate::duplex) decision: Decision<'d, R, E>,
106 pub(in crate::duplex) owner: Owner<'turn, D>,
107}
108
109impl<'turn, 'd, D, R, E> Admission<'turn, 'd, D, R, E> {
110 fn new(owner: Owner<'turn, D>, decision: Decision<'d, R, E>) -> Self {
111 Self { decision, owner }
112 }
113}
114
115pub(in crate::duplex) enum Decision<'d, R, E> {
116 Committed {
117 receipt: R,
118 },
119 Pending {
120 remainder: segments::Nonempty<resident::Shared<'d>>,
121 receipt: R,
122 },
123 Blocked {
124 receipt: R,
125 },
126 Rejected {
127 error: E,
128 },
129 Returned {
130 error: E,
131 remainder: segments::Nonempty<resident::Shared<'d>>,
132 },
133}
134
135const _: () = {
136 assert!(core::mem::size_of::<Permit<'static, Present, crate::duplex::Never>>() == 0);
137 assert!(core::mem::align_of::<Permit<'static, Present, crate::duplex::Never>>() == 1);
138 assert!(
139 core::mem::size_of::<Payload<'static, 'static, crate::duplex::Never>>()
140 == core::mem::size_of::<Option<segments::Nonempty<resident::Shared<'static>>>>()
141 );
142 assert!(
143 core::mem::align_of::<Payload<'static, 'static, crate::duplex::Never>>()
144 == core::mem::align_of::<Option<segments::Nonempty<resident::Shared<'static>>>>()
145 );
146 assert!(
147 core::mem::size_of::<Admission<'static, 'static, crate::duplex::Never, usize, usize>>()
148 == core::mem::size_of::<Decision<'static, usize, usize>>()
149 );
150 assert!(
151 core::mem::align_of::<Admission<'static, 'static, crate::duplex::Never, usize, usize>>()
152 == core::mem::align_of::<Decision<'static, usize, usize>>()
153 );
154};