nuts/nut/iac/publish/
response.rs

1use std::{future::Future, task::Poll};
2
3use crate::nut::Nut;
4
5#[derive(Default)]
6pub(crate) struct ResponseTracker {
7    slots: Vec<SlotState>,
8}
9
10enum SlotState {
11    Available,
12    Occupied,
13    Done,
14}
15
16pub(crate) struct Slot(usize);
17
18#[allow(clippy::single_match)]
19impl ResponseTracker {
20    pub fn allocate(&mut self) -> Slot {
21        for (i, slot) in self.slots.iter_mut().enumerate() {
22            match slot {
23                SlotState::Available => {
24                    *slot = SlotState::Occupied;
25                    return Slot(i);
26                }
27                _ => {}
28            }
29        }
30        let i = self.slots.len();
31        self.slots.push(SlotState::Occupied);
32        Slot(i)
33    }
34    pub fn done(&mut self, slot: &Slot) {
35        self.slots[slot.0] = SlotState::Done;
36    }
37    fn free(&mut self, index: usize) {
38        self.slots[index] = SlotState::Available;
39    }
40}
41
42pub struct NutsResponse {
43    index: usize,
44}
45
46impl NutsResponse {
47    pub(crate) fn new(slot: &Slot) -> Self {
48        Self { index: slot.0 }
49    }
50}
51
52impl Future for NutsResponse {
53    type Output = ();
54
55    fn poll(
56        self: std::pin::Pin<&mut Self>,
57        _cx: &mut std::task::Context<'_>,
58    ) -> Poll<Self::Output> {
59        Nut::with_response_tracker_mut(|response_tracker| {
60            match response_tracker.slots[self.index] {
61                SlotState::Available => panic!("Corrupted futures State"),
62                SlotState::Occupied => Poll::Pending,
63                SlotState::Done => {
64                    response_tracker.free(self.index);
65                    Poll::Ready(())
66                }
67            }
68        })
69    }
70}