cold_io/
proposal.rs

1// Copyright 2021 Vladislav Melnik
2// SPDX-License-Identifier: MIT
3
4use std::{time::Duration, net::SocketAddr, fmt};
5
6pub trait ReadOnce {
7    fn read(self, buf: &mut [u8]) -> IoResult;
8}
9
10pub trait WriteOnce {
11    fn write(self, data: &[u8]) -> IoResult;
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
15#[must_use = "need to know how many bytes was actually read or written"]
16pub enum IoResult {
17    Closed,
18    Done { length: usize, will_close: bool },
19}
20
21/// The proposal is the input to the state machine.
22/// It provides timer, io, random number generator, and user-defined data.
23pub struct Proposal<R, W, Ext, Rng> {
24    pub rng: Rng,
25    pub elapsed: Duration,
26    pub kind: ProposalKind<R, W, Ext>,
27}
28
29impl<R, W, Ext, Rng> Proposal<R, W, Ext, Rng> {
30    pub fn custom(rng: Rng, ext: Ext) -> Self {
31        Proposal {
32            rng,
33            elapsed: Duration::ZERO,
34            kind: ProposalKind::Custom(ext),
35        }
36    }
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
40pub struct ConnectionId {
41    pub poll_id: u16,
42    pub token: u16,
43}
44
45pub enum ProposalKind<R, W, Ext> {
46    /// Wake the state machine, useful if the state machine
47    /// needs to request something before it receives any event
48    Wake,
49    /// Nothing happened during a time quant
50    Idle,
51    /// New connection
52    Connection {
53        addr: SocketAddr,
54        incoming: bool,
55        id: ConnectionId,
56    },
57    /// The remote peer can provide data.
58    OnReadable(ConnectionId, R),
59    /// The remote peer can accept data.
60    OnWritable(ConnectionId, W),
61    /// User-defined
62    Custom(Ext),
63}
64
65impl<R, W, Ext, Rng> fmt::Display for Proposal<R, W, Ext, Rng>
66where
67    Ext: fmt::Display,
68{
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        write!(f, "elapsed: {:?}, {}", self.elapsed, self.kind)
71    }
72}
73
74impl<R, W, Ext> fmt::Display for ProposalKind<R, W, Ext>
75where
76    Ext: fmt::Display,
77{
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        match self {
80            ProposalKind::Wake => write!(f, "wake"),
81            ProposalKind::Idle => write!(f, "idle..."),
82            ProposalKind::Connection { addr, incoming, id } => {
83                if *incoming {
84                    write!(f, "new incoming connection: {}, addr: {}", id, addr)
85                } else {
86                    write!(f, "new outgoing connection: {}, addr: {}", id, addr)
87                }
88            },
89            ProposalKind::OnReadable(id, _) => write!(f, "local peer can read from {}", id),
90            ProposalKind::OnWritable(id, _) => write!(f, "local peer can write to {}", id),
91            ProposalKind::Custom(ext) => write!(f, "{}", ext),
92        }
93    }
94}
95
96impl fmt::Display for ConnectionId {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        write!(f, "{:04x}.{:04x}", self.poll_id, self.token)
99    }
100}