1use std::task;
4
5use o3::mem::Rejected;
6
7use crate::{
8 abi::{self, machine},
9 context,
10 manifold::file::read,
11};
12
13enum Stage<'p, 'd> {
14 Request(read::Request<'d>),
15 Ticket(read::Ticket<'p, 'd>),
16}
17
18#[must_use = "a fiber does nothing unless it is driven"]
20pub struct Operation<'p, 'd> {
21 port: &'p read::Port<'d>,
22 stage: machine::Machine<Stage<'p, 'd>>,
23}
24
25impl<'p, 'd> Operation<'p, 'd> {
26 pub fn new(port: &'p read::Port<'d>, request: read::Request<'d>) -> Self {
27 Self {
28 port,
29 stage: machine::Machine::new(Stage::Request(request)),
30 }
31 }
32}
33
34impl<'d> abi::Fiber<'d> for Operation<'_, 'd> {
35 type Output = Result<read::Completion<'d>, Rejected<read::Request<'d>, read::Admission>>;
36
37 fn poll(call: context::PollCall<'_, '_, 'd, Self>) -> task::Poll<Self::Output> {
38 let (this, cx) = call.into_parts();
39 let this = this.get_mut();
40 let waiter = cx.as_ref().completion();
41 this.stage.step(|stage| {
42 let ticket = match stage {
43 Stage::Ticket(ticket) => ticket,
44 Stage::Request(request) => match this.port.try_request(request) {
45 Ok(ticket) => ticket,
46 Err(cause) => return machine::Step::Complete(task::Poll::Ready(Err(cause))),
47 },
48 };
49 match ticket.poll(waiter) {
50 read::Poll::Pending(ticket) => {
51 machine::Step::Suspend(Stage::Ticket(ticket), task::Poll::Pending)
52 }
53 read::Poll::Ready(completion) => {
54 machine::Step::Complete(task::Poll::Ready(Ok(completion)))
55 }
56 }
57 })
58 }
59}