1 use std::fmt;
2 
3 use super::afd;
4 use super::iocp::CompletionStatus;
5 use crate::Token;
6 
7 #[derive(Clone)]
8 pub struct Event {
9     pub flags: u32,
10     pub data: u64,
11 }
12 
token(event: &Event) -> Token13 pub fn token(event: &Event) -> Token {
14     Token(event.data as usize)
15 }
16 
17 impl Event {
new(token: Token) -> Event18     pub(super) fn new(token: Token) -> Event {
19         Event {
20             flags: 0,
21             data: usize::from(token) as u64,
22         }
23     }
24 
set_readable(&mut self)25     pub(super) fn set_readable(&mut self) {
26         self.flags |= afd::POLL_RECEIVE
27     }
28 
29     #[cfg(feature = "os-ext")]
set_writable(&mut self)30     pub(super) fn set_writable(&mut self) {
31         self.flags |= afd::POLL_SEND;
32     }
33 
from_completion_status(status: &CompletionStatus) -> Event34     pub(super) fn from_completion_status(status: &CompletionStatus) -> Event {
35         Event {
36             flags: status.bytes_transferred(),
37             data: status.token() as u64,
38         }
39     }
40 
to_completion_status(&self) -> CompletionStatus41     pub(super) fn to_completion_status(&self) -> CompletionStatus {
42         CompletionStatus::new(self.flags, self.data as usize, std::ptr::null_mut())
43     }
44 
45     #[cfg(feature = "os-ext")]
to_completion_status_with_overlapped( &self, overlapped: *mut super::Overlapped, ) -> CompletionStatus46     pub(super) fn to_completion_status_with_overlapped(
47         &self,
48         overlapped: *mut super::Overlapped,
49     ) -> CompletionStatus {
50         CompletionStatus::new(self.flags, self.data as usize, overlapped)
51     }
52 }
53 
54 pub(crate) const READABLE_FLAGS: u32 = afd::POLL_RECEIVE
55     | afd::POLL_DISCONNECT
56     | afd::POLL_ACCEPT
57     | afd::POLL_ABORT
58     | afd::POLL_CONNECT_FAIL;
59 pub(crate) const WRITABLE_FLAGS: u32 = afd::POLL_SEND | afd::POLL_ABORT | afd::POLL_CONNECT_FAIL;
60 pub(crate) const ERROR_FLAGS: u32 = afd::POLL_CONNECT_FAIL;
61 pub(crate) const READ_CLOSED_FLAGS: u32 =
62     afd::POLL_DISCONNECT | afd::POLL_ABORT | afd::POLL_CONNECT_FAIL;
63 pub(crate) const WRITE_CLOSED_FLAGS: u32 = afd::POLL_ABORT | afd::POLL_CONNECT_FAIL;
64 
is_readable(event: &Event) -> bool65 pub fn is_readable(event: &Event) -> bool {
66     event.flags & READABLE_FLAGS != 0
67 }
68 
is_writable(event: &Event) -> bool69 pub fn is_writable(event: &Event) -> bool {
70     event.flags & WRITABLE_FLAGS != 0
71 }
72 
is_error(event: &Event) -> bool73 pub fn is_error(event: &Event) -> bool {
74     event.flags & ERROR_FLAGS != 0
75 }
76 
is_read_closed(event: &Event) -> bool77 pub fn is_read_closed(event: &Event) -> bool {
78     event.flags & READ_CLOSED_FLAGS != 0
79 }
80 
is_write_closed(event: &Event) -> bool81 pub fn is_write_closed(event: &Event) -> bool {
82     event.flags & WRITE_CLOSED_FLAGS != 0
83 }
84 
is_priority(event: &Event) -> bool85 pub fn is_priority(event: &Event) -> bool {
86     event.flags & afd::POLL_RECEIVE_EXPEDITED != 0
87 }
88 
is_aio(_: &Event) -> bool89 pub fn is_aio(_: &Event) -> bool {
90     // Not supported.
91     false
92 }
93 
is_lio(_: &Event) -> bool94 pub fn is_lio(_: &Event) -> bool {
95     // Not supported.
96     false
97 }
98 
debug_details(f: &mut fmt::Formatter<'_>, event: &Event) -> fmt::Result99 pub fn debug_details(f: &mut fmt::Formatter<'_>, event: &Event) -> fmt::Result {
100     #[allow(clippy::trivially_copy_pass_by_ref)]
101     fn check_flags(got: &u32, want: &u32) -> bool {
102         (got & want) != 0
103     }
104     debug_detail!(
105         FlagsDetails(u32),
106         check_flags,
107         afd::POLL_RECEIVE,
108         afd::POLL_RECEIVE_EXPEDITED,
109         afd::POLL_SEND,
110         afd::POLL_DISCONNECT,
111         afd::POLL_ABORT,
112         afd::POLL_LOCAL_CLOSE,
113         afd::POLL_CONNECT,
114         afd::POLL_ACCEPT,
115         afd::POLL_CONNECT_FAIL,
116     );
117 
118     f.debug_struct("event")
119         .field("flags", &FlagsDetails(event.flags))
120         .field("data", &event.data)
121         .finish()
122 }
123 
124 pub struct Events {
125     /// Raw I/O event completions are filled in here by the call to `get_many`
126     /// on the completion port above. These are then processed to run callbacks
127     /// which figure out what to do after the event is done.
128     pub statuses: Box<[CompletionStatus]>,
129 
130     /// Literal events returned by `get` to the upwards `EventLoop`. This file
131     /// doesn't really modify this (except for the waker), instead almost all
132     /// events are filled in by the `ReadinessQueue` from the `poll` module.
133     pub events: Vec<Event>,
134 }
135 
136 impl Events {
with_capacity(cap: usize) -> Events137     pub fn with_capacity(cap: usize) -> Events {
138         // Note that it's possible for the output `events` to grow beyond the
139         // capacity as it can also include deferred events, but that's certainly
140         // not the end of the world!
141         Events {
142             statuses: vec![CompletionStatus::zero(); cap].into_boxed_slice(),
143             events: Vec::with_capacity(cap),
144         }
145     }
146 
is_empty(&self) -> bool147     pub fn is_empty(&self) -> bool {
148         self.events.is_empty()
149     }
150 
capacity(&self) -> usize151     pub fn capacity(&self) -> usize {
152         self.events.capacity()
153     }
154 
len(&self) -> usize155     pub fn len(&self) -> usize {
156         self.events.len()
157     }
158 
get(&self, idx: usize) -> Option<&Event>159     pub fn get(&self, idx: usize) -> Option<&Event> {
160         self.events.get(idx)
161     }
162 
clear(&mut self)163     pub fn clear(&mut self) {
164         self.events.clear();
165         for status in self.statuses.iter_mut() {
166             *status = CompletionStatus::zero();
167         }
168     }
169 }
170