1use futures_01::executor::{
2 spawn as spawn01, Notify as Notify01, NotifyHandle as NotifyHandle01, Spawn as Spawn01,
3 UnsafeNotify as UnsafeNotify01,
4};
5use futures_01::{Async as Async01, Future as Future01, Stream as Stream01};
6#[cfg(feature = "sink")]
7use futures_01::{AsyncSink as AsyncSink01, Sink as Sink01};
8use futures_core::{future::Future as Future03, stream::Stream as Stream03, task as task03};
9#[cfg(feature = "sink")]
10use futures_sink::Sink as Sink03;
11use std::boxed::Box;
12use std::cell::UnsafeCell;
13use std::pin::Pin;
14use std::task::Context;
15
16#[cfg(feature = "io-compat")]
17#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
18#[allow(unreachable_pub)] pub use io::{AsyncRead01CompatExt, AsyncWrite01CompatExt};
20
21#[derive(Debug)]
24#[must_use = "futures do nothing unless you `.await` or poll them"]
25pub struct Compat01As03<T> {
26 pub(crate) inner: Spawn01<T>,
27}
28
29impl<T> Unpin for Compat01As03<T> {}
30
31impl<T> Compat01As03<T> {
32 pub fn new(object: T) -> Self {
35 Self { inner: spawn01(object) }
36 }
37
38 fn in_notify<R>(&mut self, cx: &mut Context<'_>, f: impl FnOnce(&mut T) -> R) -> R {
39 let notify = &WakerToHandle(cx.waker());
40 self.inner.poll_fn_notify(notify, 0, f)
41 }
42
43 pub fn get_ref(&self) -> &T {
45 self.inner.get_ref()
46 }
47
48 pub fn get_mut(&mut self) -> &mut T {
51 self.inner.get_mut()
52 }
53
54 pub fn into_inner(self) -> T {
57 self.inner.into_inner()
58 }
59}
60
61pub trait Future01CompatExt: Future01 {
63 fn compat(self) -> Compat01As03<Self>
80 where
81 Self: Sized,
82 {
83 Compat01As03::new(self)
84 }
85}
86impl<Fut: Future01> Future01CompatExt for Fut {}
87
88pub trait Stream01CompatExt: Stream01 {
90 fn compat(self) -> Compat01As03<Self>
108 where
109 Self: Sized,
110 {
111 Compat01As03::new(self)
112 }
113}
114impl<St: Stream01> Stream01CompatExt for St {}
115
116#[cfg(feature = "sink")]
118#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
119pub trait Sink01CompatExt: Sink01 {
120 fn sink_compat(self) -> Compat01As03Sink<Self, Self::SinkItem>
141 where
142 Self: Sized,
143 {
144 Compat01As03Sink::new(self)
145 }
146}
147#[cfg(feature = "sink")]
148impl<Si: Sink01> Sink01CompatExt for Si {}
149
150fn poll_01_to_03<T, E>(x: Result<Async01<T>, E>) -> task03::Poll<Result<T, E>> {
151 match x? {
152 Async01::Ready(t) => task03::Poll::Ready(Ok(t)),
153 Async01::NotReady => task03::Poll::Pending,
154 }
155}
156
157impl<Fut: Future01> Future03 for Compat01As03<Fut> {
158 type Output = Result<Fut::Item, Fut::Error>;
159
160 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> task03::Poll<Self::Output> {
161 poll_01_to_03(self.in_notify(cx, Future01::poll))
162 }
163}
164
165impl<St: Stream01> Stream03 for Compat01As03<St> {
166 type Item = Result<St::Item, St::Error>;
167
168 fn poll_next(
169 mut self: Pin<&mut Self>,
170 cx: &mut Context<'_>,
171 ) -> task03::Poll<Option<Self::Item>> {
172 match self.in_notify(cx, Stream01::poll)? {
173 Async01::Ready(Some(t)) => task03::Poll::Ready(Some(Ok(t))),
174 Async01::Ready(None) => task03::Poll::Ready(None),
175 Async01::NotReady => task03::Poll::Pending,
176 }
177 }
178}
179
180#[cfg(feature = "sink")]
182#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
183#[derive(Debug)]
184#[must_use = "sinks do nothing unless polled"]
185pub struct Compat01As03Sink<S, SinkItem> {
186 pub(crate) inner: Spawn01<S>,
187 pub(crate) buffer: Option<SinkItem>,
188 pub(crate) close_started: bool,
189}
190
191#[cfg(feature = "sink")]
192impl<S, SinkItem> Unpin for Compat01As03Sink<S, SinkItem> {}
193
194#[cfg(feature = "sink")]
195impl<S, SinkItem> Compat01As03Sink<S, SinkItem> {
196 pub fn new(inner: S) -> Self {
198 Self { inner: spawn01(inner), buffer: None, close_started: false }
199 }
200
201 fn in_notify<R>(&mut self, cx: &mut Context<'_>, f: impl FnOnce(&mut S) -> R) -> R {
202 let notify = &WakerToHandle(cx.waker());
203 self.inner.poll_fn_notify(notify, 0, f)
204 }
205
206 pub fn get_ref(&self) -> &S {
208 self.inner.get_ref()
209 }
210
211 pub fn get_mut(&mut self) -> &mut S {
213 self.inner.get_mut()
214 }
215
216 pub fn into_inner(self) -> S {
218 self.inner.into_inner()
219 }
220}
221
222#[cfg(feature = "sink")]
223impl<S, SinkItem> Stream03 for Compat01As03Sink<S, SinkItem>
224where
225 S: Stream01,
226{
227 type Item = Result<S::Item, S::Error>;
228
229 fn poll_next(
230 mut self: Pin<&mut Self>,
231 cx: &mut Context<'_>,
232 ) -> task03::Poll<Option<Self::Item>> {
233 match self.in_notify(cx, Stream01::poll)? {
234 Async01::Ready(Some(t)) => task03::Poll::Ready(Some(Ok(t))),
235 Async01::Ready(None) => task03::Poll::Ready(None),
236 Async01::NotReady => task03::Poll::Pending,
237 }
238 }
239}
240
241#[cfg(feature = "sink")]
242impl<S, SinkItem> Sink03<SinkItem> for Compat01As03Sink<S, SinkItem>
243where
244 S: Sink01<SinkItem = SinkItem>,
245{
246 type Error = S::SinkError;
247
248 fn start_send(mut self: Pin<&mut Self>, item: SinkItem) -> Result<(), Self::Error> {
249 debug_assert!(self.buffer.is_none());
250 self.buffer = Some(item);
251 Ok(())
252 }
253
254 fn poll_ready(
255 mut self: Pin<&mut Self>,
256 cx: &mut Context<'_>,
257 ) -> task03::Poll<Result<(), Self::Error>> {
258 match self.buffer.take() {
259 Some(item) => match self.in_notify(cx, |f| f.start_send(item))? {
260 AsyncSink01::Ready => task03::Poll::Ready(Ok(())),
261 AsyncSink01::NotReady(i) => {
262 self.buffer = Some(i);
263 task03::Poll::Pending
264 }
265 },
266 None => task03::Poll::Ready(Ok(())),
267 }
268 }
269
270 fn poll_flush(
271 mut self: Pin<&mut Self>,
272 cx: &mut Context<'_>,
273 ) -> task03::Poll<Result<(), Self::Error>> {
274 let item = self.buffer.take();
275 match self.in_notify(cx, |f| match item {
276 Some(i) => match f.start_send(i)? {
277 AsyncSink01::Ready => f.poll_complete().map(|i| (i, None)),
278 AsyncSink01::NotReady(t) => Ok((Async01::NotReady, Some(t))),
279 },
280 None => f.poll_complete().map(|i| (i, None)),
281 })? {
282 (Async01::Ready(_), _) => task03::Poll::Ready(Ok(())),
283 (Async01::NotReady, item) => {
284 self.buffer = item;
285 task03::Poll::Pending
286 }
287 }
288 }
289
290 fn poll_close(
291 mut self: Pin<&mut Self>,
292 cx: &mut Context<'_>,
293 ) -> task03::Poll<Result<(), Self::Error>> {
294 let item = self.buffer.take();
295 let close_started = self.close_started;
296
297 let result = self.in_notify(cx, |f| {
298 if !close_started {
299 if let Some(item) = item {
300 if let AsyncSink01::NotReady(item) = f.start_send(item)? {
301 return Ok((Async01::NotReady, Some(item), false));
302 }
303 }
304
305 if let Async01::NotReady = f.poll_complete()? {
306 return Ok((Async01::NotReady, None, false));
307 }
308 }
309
310 Ok((<S as Sink01>::close(f)?, None, true))
311 });
312
313 match result? {
314 (Async01::Ready(_), _, _) => task03::Poll::Ready(Ok(())),
315 (Async01::NotReady, item, close_started) => {
316 self.buffer = item;
317 self.close_started = close_started;
318 task03::Poll::Pending
319 }
320 }
321 }
322}
323
324#[repr(transparent)]
325struct NotifyWaker(UnsafeCell<task03::Waker>);
326
327#[allow(missing_debug_implementations)] #[derive(Clone)]
329struct WakerToHandle<'a>(&'a task03::Waker);
330
331impl From<WakerToHandle<'_>> for NotifyHandle01 {
332 fn from(handle: WakerToHandle<'_>) -> Self {
333 let waker_ptr: Box<task03::Waker> = Box::new(handle.0.clone());
334 let ptr: *mut NotifyWaker = Box::into_raw(waker_ptr) as *mut NotifyWaker;
337
338 unsafe { Self::new(ptr) }
339 }
340}
341
342impl Notify01 for NotifyWaker {
343 fn notify(&self, _: usize) {
344 unsafe { &*self.0.get() }.wake_by_ref();
345 }
346}
347
348unsafe impl Send for NotifyWaker {}
349unsafe impl Sync for NotifyWaker {}
350
351unsafe impl UnsafeNotify01 for NotifyWaker {
352 unsafe fn clone_raw(&self) -> NotifyHandle01 {
353 WakerToHandle(unsafe { &*self.0.get() }).into()
354 }
355
356 unsafe fn drop_raw(&self) {
357 let waker: *mut task03::Waker = self.0.get();
363 drop(unsafe { Box::from_raw(waker) });
364 }
365}
366
367#[cfg(feature = "io-compat")]
368#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
369mod io {
370 use super::*;
371 use futures_io::{AsyncRead as AsyncRead03, AsyncWrite as AsyncWrite03};
372 use std::io::Error;
373 use tokio_io::{AsyncRead as AsyncRead01, AsyncWrite as AsyncWrite01};
374
375 #[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
377 pub trait AsyncRead01CompatExt: AsyncRead01 {
378 fn compat(self) -> Compat01As03<Self>
397 where
398 Self: Sized,
399 {
400 Compat01As03::new(self)
401 }
402 }
403 impl<R: AsyncRead01> AsyncRead01CompatExt for R {}
404
405 #[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
407 pub trait AsyncWrite01CompatExt: AsyncWrite01 {
408 fn compat(self) -> Compat01As03<Self>
427 where
428 Self: Sized,
429 {
430 Compat01As03::new(self)
431 }
432 }
433 impl<W: AsyncWrite01> AsyncWrite01CompatExt for W {}
434
435 impl<R: AsyncRead01> AsyncRead03 for Compat01As03<R> {
436 fn poll_read(
437 mut self: Pin<&mut Self>,
438 cx: &mut Context<'_>,
439 buf: &mut [u8],
440 ) -> task03::Poll<Result<usize, Error>> {
441 poll_01_to_03(self.in_notify(cx, |x| x.poll_read(buf)))
442 }
443 }
444
445 impl<W: AsyncWrite01> AsyncWrite03 for Compat01As03<W> {
446 fn poll_write(
447 mut self: Pin<&mut Self>,
448 cx: &mut Context<'_>,
449 buf: &[u8],
450 ) -> task03::Poll<Result<usize, Error>> {
451 poll_01_to_03(self.in_notify(cx, |x| x.poll_write(buf)))
452 }
453
454 fn poll_flush(
455 mut self: Pin<&mut Self>,
456 cx: &mut Context<'_>,
457 ) -> task03::Poll<Result<(), Error>> {
458 poll_01_to_03(self.in_notify(cx, AsyncWrite01::poll_flush))
459 }
460
461 fn poll_close(
462 mut self: Pin<&mut Self>,
463 cx: &mut Context<'_>,
464 ) -> task03::Poll<Result<(), Error>> {
465 poll_01_to_03(self.in_notify(cx, AsyncWrite01::shutdown))
466 }
467 }
468}