1use std::{any, cell::Cell, io, task::Context, task::Poll};
2
3use crate::{FilterCtx, FilterLayer, IoRef, Readiness, io::IoState};
4
5#[derive(Debug)]
6pub struct Base(IoRef);
8
9impl Base {
10 pub(crate) fn new(inner: IoRef) -> Self {
11 Base(inner)
12 }
13}
14
15#[derive(Debug)]
16pub struct Layer<F, L = Base>(pub(crate) F, L, Cell<bool>);
22
23impl<F: FilterLayer, L: Filter> Layer<F, L> {
24 pub(crate) fn new(f: F, l: L) -> Self {
25 Self(f, l, Cell::new(false))
26 }
27}
28
29pub(crate) struct NullFilter;
30
31const NULL: NullFilter = NullFilter;
32
33impl NullFilter {
34 pub(super) const fn get() -> &'static dyn Filter {
35 &NULL
36 }
37}
38
39pub trait Filter: 'static {
45 fn query(&self, id: any::TypeId) -> Option<Box<dyn any::Any>>;
47
48 fn process_read_buf(&self, ctx: &mut FilterCtx<'_>) -> io::Result<()>;
50
51 fn process_write_buf(&self, ctx: &mut FilterCtx<'_>) -> io::Result<()>;
53
54 fn shutdown(&self, ctx: &mut FilterCtx<'_>) -> io::Result<Poll<()>>;
57
58 fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness>;
69
70 fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness>;
79}
80
81pub(crate) fn read_readiness(st: &IoState) -> Poll<Readiness> {
84 if st.flags.is_force_closing() {
85 Poll::Ready(Readiness::Terminate)
90 } else if st.flags.is_aborted() {
91 Poll::Ready(Readiness::Close)
94 } else if st.flags.is_read_eof() {
95 Poll::Pending
100 } else if st.flags.is_stopping() {
101 Poll::Pending
106 } else if st.flags.is_stopping_filters() {
107 Poll::Ready(Readiness::Ready)
110 } else if st.flags.is_read_paused_or_backpressure() || st.flags.is_read_wr_backpressure() {
111 Poll::Pending
114 } else {
115 Poll::Ready(Readiness::Ready)
116 }
117}
118
119pub(crate) fn write_readiness(st: &IoState) -> Poll<Readiness> {
122 if st.flags.is_force_closing() {
123 Poll::Ready(Readiness::Terminate)
125 } else if st.flags.is_aborted() {
126 Poll::Ready(Readiness::Close)
129 } else if st.flags.is_stopping() {
130 if st.buffer.write_buf_size() != 0 {
134 Poll::Ready(Readiness::Ready)
135 } else if st.wr_inflight.get() != 0 {
136 Poll::Pending
139 } else {
140 Poll::Ready(Readiness::Close)
141 }
142 } else if st.flags.is_write_paused() {
143 Poll::Pending
144 } else {
145 Poll::Ready(Readiness::Ready)
146 }
147}
148
149impl Filter for Base {
150 fn query(&self, id: any::TypeId) -> Option<Box<dyn any::Any>> {
151 if let Some(hnd) = self.0.0.handle.take() {
152 let res = hnd.query(id);
153 self.0.0.handle.set(Some(hnd));
154 res
155 } else {
156 None
157 }
158 }
159
160 fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness> {
161 let st = &self.0.0;
162 let res = read_readiness(st);
163 if !matches!(res, Poll::Ready(Readiness::Close | Readiness::Terminate)) {
164 st.read_task.register(cx.waker());
165 }
166 res
167 }
168
169 fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness> {
170 let st = &self.0.0;
171 let res = write_readiness(st);
172 if !matches!(res, Poll::Ready(Readiness::Close | Readiness::Terminate)) {
173 st.write_task.register(cx.waker());
174 }
175 res
176 }
177
178 #[inline]
179 fn process_read_buf(&self, _: &mut FilterCtx<'_>) -> io::Result<()> {
180 Ok(())
181 }
182
183 #[inline]
184 fn process_write_buf(&self, _: &mut FilterCtx<'_>) -> io::Result<()> {
185 Ok(())
186 }
187
188 #[inline]
189 fn shutdown(&self, _: &mut FilterCtx<'_>) -> io::Result<Poll<()>> {
190 Ok(Poll::Ready(()))
191 }
192}
193
194impl<F, L> Filter for Layer<F, L>
195where
196 F: FilterLayer,
197 L: Filter,
198{
199 #[inline]
200 fn query(&self, id: any::TypeId) -> Option<Box<dyn any::Any>> {
201 self.0.query(id).or_else(|| self.1.query(id))
202 }
203
204 #[inline]
205 fn shutdown(&self, ctx: &mut FilterCtx<'_>) -> io::Result<Poll<()>> {
206 if !self.2.get() {
207 if ctx.with_buffer(|buf| self.0.shutdown(buf))?.is_ready() {
208 self.process_write_buf(ctx)?;
209 self.2.set(true);
210
211 ctx.clear_write_buf();
213 } else {
214 ctx.with_next(|ctx| self.1.process_write_buf(ctx))?;
218 return Ok(Poll::Pending);
219 }
220 }
221 ctx.with_next(|ctx| self.1.shutdown(ctx))
222 }
223
224 #[inline]
225 fn process_read_buf(&self, ctx: &mut FilterCtx<'_>) -> io::Result<()> {
226 ctx.with_next(|ctx| self.1.process_read_buf(ctx))?;
227 if self.2.get() {
228 Ok(())
229 } else {
230 ctx.with_buffer(|buf| self.0.process_read_buf(buf))
231 }
232 }
233
234 #[inline]
235 fn process_write_buf(&self, ctx: &mut FilterCtx<'_>) -> io::Result<()> {
236 if !self.2.get() {
237 ctx.with_buffer(|buf| self.0.process_write_buf(buf))?;
238 }
239 ctx.with_next(|ctx| self.1.process_write_buf(ctx))
240 }
241
242 #[inline]
243 fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness> {
244 self.1.poll_read_ready(cx)
245 }
246
247 #[inline]
248 fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness> {
249 self.1.poll_write_ready(cx)
250 }
251}
252
253impl Filter for NullFilter {
254 #[inline]
255 fn query(&self, _: any::TypeId) -> Option<Box<dyn any::Any>> {
256 None
257 }
258
259 #[inline]
265 fn poll_read_ready(&self, _: &mut Context<'_>) -> Poll<Readiness> {
266 Poll::Ready(Readiness::Close)
267 }
268
269 #[inline]
270 fn poll_write_ready(&self, _: &mut Context<'_>) -> Poll<Readiness> {
271 Poll::Ready(Readiness::Close)
272 }
273
274 #[inline]
275 fn process_read_buf(&self, _: &mut FilterCtx<'_>) -> io::Result<()> {
276 Ok(())
277 }
278
279 #[inline]
280 fn process_write_buf(&self, _: &mut FilterCtx<'_>) -> io::Result<()> {
281 Ok(())
282 }
283
284 #[inline]
285 fn shutdown(&self, _: &mut FilterCtx<'_>) -> io::Result<Poll<()>> {
286 Ok(Poll::Ready(()))
287 }
288}