1use sark_http::payload::owned;
3
4use crate::{
5 duplex::{self, admit, machine},
6 manifold::stream::Boundary,
7};
8
9pub trait Buf<'d> {
13 type Input;
14 type Error;
15 type Receipt;
16
17 fn state(&self) -> Buffer;
18
19 fn push(&mut self, input: Self::Input) -> Result<(), Rejected<Self::Input, Self::Error>>;
20
21 fn take(&mut self) -> Take<'d, Self::Receipt>;
22}
23
24#[derive(Clone, Copy, PartialEq, Eq)]
26#[repr(u8)]
27pub enum Buffer {
28 Empty,
29 Queued,
30}
31
32pub enum Take<'d, R> {
34 Empty,
35 Item {
36 input: owned::Segments<'d>,
37 receipt: R,
38 },
39}
40
41use o3::mem::Rejected;
42
43#[must_use = "a rejected duplex input remains an affine owner"]
45#[derive(Debug)]
46pub enum PushError<I, E> {
47 Finished(I),
48 Buffer(Rejected<I, E>),
49 Finish {
50 input: I,
51 error: machine::FinishError,
52 },
53}
54
55#[derive(Clone, Copy, PartialEq, Eq)]
56#[repr(u8)]
57enum Phase {
58 Open,
59 Finished,
60 Closed,
61}
62
63#[derive(Clone, Copy, PartialEq, Eq)]
65#[repr(u8)]
66pub enum Status {
67 Open,
68 Closed,
69}
70
71#[derive(Clone, Copy, PartialEq, Eq)]
73#[repr(u8)]
74pub enum Work {
75 Idle,
76 Ready,
77}
78
79pub struct State<'d, D, B>
81where
82 D: duplex::Session<'d>,
83{
84 raw: machine::Machine<'d, D>,
85 buffer: B,
86 phase: Phase,
87}
88
89#[must_use = "consume the duplex transaction and its affine carrier receipt"]
91pub struct Turn<T, F> {
92 step: T,
93 feed: Feed<F>,
94}
95
96impl<T, F> Turn<T, F> {
97 pub fn into_parts(self) -> (T, Feed<F>) {
98 (self.step, self.feed)
99 }
100}
101
102#[derive(PartialEq, Eq)]
104#[must_use = "consume the affine receipt for the input callback that ran"]
105pub enum Feed<R> {
106 Idle,
107 Consumed(R),
108}
109
110impl<'d, D, B> State<'d, D, B>
111where
112 D: duplex::Session<'d>,
113 B: Buf<'d>,
114{
115 pub fn open(session: D, buffer: B) -> Self {
116 Self {
117 raw: machine::Machine::new(session),
118 buffer,
119 phase: Phase::Open,
120 }
121 }
122
123 pub fn finished(session: D, buffer: B) -> Self {
124 Self {
125 raw: machine::Machine::with_finish(session),
126 buffer,
127 phase: Phase::Finished,
128 }
129 }
130
131 pub fn into_buffer(self) -> B {
133 self.buffer
134 }
135
136 pub const fn status(&self) -> Status {
137 match (self.phase, self.raw.progress()) {
138 (Phase::Open, machine::Progress::Idle | machine::Progress::Turn) => Status::Open,
139 (Phase::Finished | Phase::Closed, _) | (Phase::Open, machine::Progress::Finished) => {
140 Status::Closed
141 }
142 }
143 }
144
145 pub fn work(&self) -> Work {
146 match (self.raw.progress(), self.phase, self.buffer.state()) {
147 (machine::Progress::Finished, _, _)
148 | (machine::Progress::Idle, _, Buffer::Empty)
149 | (machine::Progress::Idle, Phase::Closed, Buffer::Queued) => Work::Idle,
150 (machine::Progress::Idle | machine::Progress::Turn, _, _) => Work::Ready,
151 }
152 }
153
154 pub fn push(
157 &mut self,
158 input: B::Input,
159 boundary: Boundary,
160 ) -> Result<(), PushError<B::Input, B::Error>> {
161 match self.status() {
162 Status::Open => {}
163 Status::Closed => return Err(PushError::Finished(input)),
164 }
165
166 let (finish, input) = match boundary {
167 Boundary::End => match self.raw.finish(input) {
168 Ok((finish, input)) => (Some(finish), input),
169 Err((error, input)) => return Err(PushError::Finish { input, error }),
170 },
171 Boundary::More => (None, input),
172 };
173
174 self.buffer.push(input).map_err(PushError::Buffer)?;
175 if let Some(finish) = finish {
176 finish.commit();
177 self.phase = match self.buffer.state() {
178 Buffer::Empty => Phase::Closed,
179 Buffer::Queued => Phase::Finished,
180 };
181 }
182 Ok(())
183 }
184
185 pub fn finish(&mut self) -> Result<(), machine::FinishError> {
188 match self.phase {
189 Phase::Open => {
190 let finish = match self.raw.finish(()) {
191 Ok((finish, ())) => finish,
192 Err((error, ())) => return Err(error),
193 };
194 finish.commit();
195 self.phase = match self.buffer.state() {
196 Buffer::Empty => Phase::Closed,
197 Buffer::Queued => Phase::Finished,
198 };
199 Ok(())
200 }
201 Phase::Finished => Err(machine::FinishError::Finished),
202 Phase::Closed => Err(machine::FinishError::Closed),
203 }
204 }
205
206 pub fn transact<R, E>(
210 &mut self,
211 admit: impl for<'turn> FnOnce(
212 admit::Emission<'turn, 'd, D>,
213 ) -> admit::Admission<'turn, 'd, D, R, E>,
214 ) -> Turn<machine::Transaction<R, E>, B::Receipt> {
215 let feed = self.feed();
216 let step = self
217 .raw
218 .transact(&mut [], &mut Vec::new(), |_, emission| admit(emission));
219 Turn { step, feed }
220 }
221
222 fn feed(&mut self) -> Feed<B::Receipt> {
223 match (self.phase, self.raw.progress()) {
224 (Phase::Closed, _) | (Phase::Open | Phase::Finished, machine::Progress::Finished) => {
225 return Feed::Idle;
226 }
227 (Phase::Open | Phase::Finished, machine::Progress::Idle | machine::Progress::Turn) => {}
228 }
229 let raw = &mut self.raw;
230 let buffer = &mut self.buffer;
231 let slot = match raw.input() {
232 machine::Access::Vacant(slot) => slot,
233 machine::Access::Blocked => return Feed::Idle,
234 };
235 match buffer.take() {
236 Take::Empty => Feed::Idle,
237 Take::Item { input, receipt } => {
238 slot.commit(input);
239 if self.phase == Phase::Finished {
240 match buffer.state() {
241 Buffer::Empty => self.phase = Phase::Closed,
242 Buffer::Queued => {}
243 }
244 };
245 Feed::Consumed(receipt)
246 }
247 }
248 }
249}