Skip to main content

async_selector/
pollable.rs

1//! Traits that make the [`Selector`](crate::selector::Selector) generic over asynchronous tasks and polling logic.
2//!
3//! Unless you want to exercise the full flexibility of the selector, you don't need to use these traits.
4//! You can use plain [`FutureSelector`](crate::FutureSelector) and [`StreamSelector`](crate::StreamSelector).
5
6use std::{
7    ops::ControlFlow,
8    pin::Pin,
9    task::{Context, Poll},
10};
11
12use futures::Stream;
13
14/// Task that can be polled inside a [`Selector`](crate::selector::Selector).
15pub trait Pollable<'a, E: ?Sized, EMut: ?Sized> {
16    /// Type of values returned when polling the task.
17    type Progress;
18
19    /// Polls the given task with references to strongly typed extensions.
20    ///
21    /// # Extensions
22    ///
23    /// This method supports passing references to immutable and mutable extensions
24    /// that can be used by the task. This allows the tasks for operating on a shared state
25    /// without any unsafe code or synchronization primitives.
26    /// Even more, extensions allow for static polymorphism in the types returned by the task.
27    /// See relevant [example](https://github.com/Razz4780/async-selector/blob/main/examples/extensions.rs).
28    ///
29    /// # Returns
30    ///
31    /// * [`ControlFlow::Continue`] if the task has not finished and might yield more values
32    /// * [`ControlFlow::Break`] if the task has finished
33    fn poll_progress(
34        self: Pin<&mut Self>,
35        ext: &'a E,
36        ext_mut: &mut EMut,
37        cx: &mut Context<'_>,
38    ) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>>;
39}
40
41/// Sealed complementary trait used internally by [`Selector`](crate::selector::Selector).
42///
43/// Allows for handling plain [`Future`]s and [`Stream`]s as [`Pollable`]s through [`PollFuture`] and [`PollStream`].
44pub trait PollProxy<'a, P, E: ?Sized, EMut: ?Sized>: sealed::Sealed {
45    type Progress;
46
47    fn poll_progress(
48        state: Pin<&mut P>,
49        ext: &'a E,
50        ext_mut: &mut EMut,
51        cx: &mut Context<'_>,
52    ) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>>;
53}
54
55/// [`PollProxy`] that transforms [`Future`]s into [`Pollable`] tasks.
56#[derive(Debug, Default, Clone, Copy)]
57pub struct PollFuture;
58
59impl sealed::Sealed for PollFuture {}
60
61impl<'a, F: Future> PollProxy<'a, F, (), ()> for PollFuture {
62    type Progress = F::Output;
63
64    fn poll_progress(
65        state: Pin<&mut F>,
66        _: &'a (),
67        _: &mut (),
68        cx: &mut Context<'_>,
69    ) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
70        state.poll(cx).map(Some).map(ControlFlow::Break)
71    }
72}
73
74/// [`PollProxy`] that transforms [`Stream`]s into [`Pollable`] tasks.
75#[derive(Debug, Default, Clone, Copy)]
76pub struct PollStream;
77
78impl sealed::Sealed for PollStream {}
79
80impl<'a, S: Stream> PollProxy<'a, S, (), ()> for PollStream {
81    type Progress = S::Item;
82
83    fn poll_progress(
84        state: Pin<&mut S>,
85        _: &'a (),
86        _: &mut (),
87        cx: &mut Context<'_>,
88    ) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
89        state.poll_next(cx).map(|opt| {
90            opt.map(ControlFlow::Continue)
91                .unwrap_or(ControlFlow::Break(None))
92        })
93    }
94}
95
96/// Noop [`PollProxy`] that only works with [`Pollable`]s.
97#[derive(Debug, Default, Clone, Copy)]
98pub struct PollDirect;
99
100impl sealed::Sealed for PollDirect {}
101
102impl<'a, P, E, EMut> PollProxy<'a, P, E, EMut> for PollDirect
103where
104    P: Pollable<'a, E, EMut>,
105    E: ?Sized,
106    EMut: ?Sized,
107{
108    type Progress = P::Progress;
109
110    fn poll_progress(
111        state: Pin<&mut P>,
112        ext: &'a E,
113        ext_mut: &mut EMut,
114        cx: &mut Context<'_>,
115    ) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
116        state.poll_progress(ext, ext_mut, cx)
117    }
118}
119
120mod sealed {
121    pub trait Sealed {}
122}