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>
79 where
80 Self: Sized,
81 {
82 Compat01As03::new(self)
83 }
84}
85impl<Fut: Future01> Future01CompatExt for Fut {}
86
87pub trait Stream01CompatExt: Stream01 {
89 fn compat(self) -> Compat01As03<Self>
106 where
107 Self: Sized,
108 {
109 Compat01As03::new(self)
110 }
111}
112impl<St: Stream01> Stream01CompatExt for St {}
113
114#[cfg(feature = "sink")]
116#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
117pub trait Sink01CompatExt: Sink01 {
118 fn sink_compat(self) -> Compat01As03Sink<Self, Self::SinkItem>
138 where
139 Self: Sized,
140 {
141 Compat01As03Sink::new(self)
142 }
143}
144#[cfg(feature = "sink")]
145impl<Si: Sink01> Sink01CompatExt for Si {}
146
147fn poll_01_to_03<T, E>(x: Result<Async01<T>, E>) -> task03::Poll<Result<T, E>> {
148 match x? {
149 Async01::Ready(t) => task03::Poll::Ready(Ok(t)),
150 Async01::NotReady => task03::Poll::Pending,
151 }
152}
153
154impl<Fut: Future01> Future03 for Compat01As03<Fut> {
155 type Output = Result<Fut::Item, Fut::Error>;
156
157 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> task03::Poll<Self::Output> {
158 poll_01_to_03(self.in_notify(cx, Future01::poll))
159 }
160}
161
162impl<St: Stream01> Stream03 for Compat01As03<St> {
163 type Item = Result<St::Item, St::Error>;
164
165 fn poll_next(
166 mut self: Pin<&mut Self>,
167 cx: &mut Context<'_>,
168 ) -> task03::Poll<Option<Self::Item>> {
169 match self.in_notify(cx, Stream01::poll)? {
170 Async01::Ready(Some(t)) => task03::Poll::Ready(Some(Ok(t))),
171 Async01::Ready(None) => task03::Poll::Ready(None),
172 Async01::NotReady => task03::Poll::Pending,
173 }
174 }
175}
176
177#[cfg(feature = "sink")]
179#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
180#[derive(Debug)]
181#[must_use = "sinks do nothing unless polled"]
182pub struct Compat01As03Sink<S, SinkItem> {
183 pub(crate) inner: Spawn01<S>,
184 pub(crate) buffer: Option<SinkItem>,
185 pub(crate) close_started: bool,
186}
187
188#[cfg(feature = "sink")]
189impl<S, SinkItem> Unpin for Compat01As03Sink<S, SinkItem> {}
190
191#[cfg(feature = "sink")]
192impl<S, SinkItem> Compat01As03Sink<S, SinkItem> {
193 pub fn new(inner: S) -> Self {
195 Self { inner: spawn01(inner), buffer: None, close_started: false }
196 }
197
198 fn in_notify<R>(&mut self, cx: &mut Context<'_>, f: impl FnOnce(&mut S) -> R) -> R {
199 let notify = &WakerToHandle(cx.waker());
200 self.inner.poll_fn_notify(notify, 0, f)
201 }
202
203 pub fn get_ref(&self) -> &S {
205 self.inner.get_ref()
206 }
207
208 pub fn get_mut(&mut self) -> &mut S {
210 self.inner.get_mut()
211 }
212
213 pub fn into_inner(self) -> S {
215 self.inner.into_inner()
216 }
217}
218
219#[cfg(feature = "sink")]
220impl<S, SinkItem> Stream03 for Compat01As03Sink<S, SinkItem>
221where
222 S: Stream01,
223{
224 type Item = Result<S::Item, S::Error>;
225
226 fn poll_next(
227 mut self: Pin<&mut Self>,
228 cx: &mut Context<'_>,
229 ) -> task03::Poll<Option<Self::Item>> {
230 match self.in_notify(cx, Stream01::poll)? {
231 Async01::Ready(Some(t)) => task03::Poll::Ready(Some(Ok(t))),
232 Async01::Ready(None) => task03::Poll::Ready(None),
233 Async01::NotReady => task03::Poll::Pending,
234 }
235 }
236}
237
238#[cfg(feature = "sink")]
239impl<S, SinkItem> Sink03<SinkItem> for Compat01As03Sink<S, SinkItem>
240where
241 S: Sink01<SinkItem = SinkItem>,
242{
243 type Error = S::SinkError;
244
245 fn start_send(mut self: Pin<&mut Self>, item: SinkItem) -> Result<(), Self::Error> {
246 debug_assert!(self.buffer.is_none());
247 self.buffer = Some(item);
248 Ok(())
249 }
250
251 fn poll_ready(
252 mut self: Pin<&mut Self>,
253 cx: &mut Context<'_>,
254 ) -> task03::Poll<Result<(), Self::Error>> {
255 match self.buffer.take() {
256 Some(item) => match self.in_notify(cx, |f| f.start_send(item))? {
257 AsyncSink01::Ready => task03::Poll::Ready(Ok(())),
258 AsyncSink01::NotReady(i) => {
259 self.buffer = Some(i);
260 task03::Poll::Pending
261 }
262 },
263 None => task03::Poll::Ready(Ok(())),
264 }
265 }
266
267 fn poll_flush(
268 mut self: Pin<&mut Self>,
269 cx: &mut Context<'_>,
270 ) -> task03::Poll<Result<(), Self::Error>> {
271 let item = self.buffer.take();
272 match self.in_notify(cx, |f| match item {
273 Some(i) => match f.start_send(i)? {
274 AsyncSink01::Ready => f.poll_complete().map(|i| (i, None)),
275 AsyncSink01::NotReady(t) => Ok((Async01::NotReady, Some(t))),
276 },
277 None => f.poll_complete().map(|i| (i, None)),
278 })? {
279 (Async01::Ready(_), _) => task03::Poll::Ready(Ok(())),
280 (Async01::NotReady, item) => {
281 self.buffer = item;
282 task03::Poll::Pending
283 }
284 }
285 }
286
287 fn poll_close(
288 mut self: Pin<&mut Self>,
289 cx: &mut Context<'_>,
290 ) -> task03::Poll<Result<(), Self::Error>> {
291 let item = self.buffer.take();
292 let close_started = self.close_started;
293
294 let result = self.in_notify(cx, |f| {
295 if !close_started {
296 if let Some(item) = item {
297 if let AsyncSink01::NotReady(item) = f.start_send(item)? {
298 return Ok((Async01::NotReady, Some(item), false));
299 }
300 }
301
302 if let Async01::NotReady = f.poll_complete()? {
303 return Ok((Async01::NotReady, None, false));
304 }
305 }
306
307 Ok((<S as Sink01>::close(f)?, None, true))
308 });
309
310 match result? {
311 (Async01::Ready(_), _, _) => task03::Poll::Ready(Ok(())),
312 (Async01::NotReady, item, close_started) => {
313 self.buffer = item;
314 self.close_started = close_started;
315 task03::Poll::Pending
316 }
317 }
318 }
319}
320
321#[repr(transparent)]
322struct NotifyWaker(UnsafeCell<task03::Waker>);
323
324#[allow(missing_debug_implementations)] #[derive(Clone)]
326struct WakerToHandle<'a>(&'a task03::Waker);
327
328impl From<WakerToHandle<'_>> for NotifyHandle01 {
329 fn from(handle: WakerToHandle<'_>) -> Self {
330 let waker_ptr: Box<task03::Waker> = Box::new(handle.0.clone());
331 let ptr: *mut NotifyWaker = Box::into_raw(waker_ptr) as *mut NotifyWaker;
334
335 unsafe { Self::new(ptr) }
336 }
337}
338
339impl Notify01 for NotifyWaker {
340 fn notify(&self, _: usize) {
341 unsafe { &*self.0.get() }.wake_by_ref();
342 }
343}
344
345unsafe impl Send for NotifyWaker {}
346unsafe impl Sync for NotifyWaker {}
347
348unsafe impl UnsafeNotify01 for NotifyWaker {
349 unsafe fn clone_raw(&self) -> NotifyHandle01 {
350 WakerToHandle(unsafe { &*self.0.get() }).into()
351 }
352
353 unsafe fn drop_raw(&self) {
354 let waker: *mut task03::Waker = self.0.get();
360 drop(unsafe { Box::from_raw(waker) });
361 }
362}
363
364#[cfg(feature = "io-compat")]
365#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
366mod io {
367 use super::*;
368 use futures_io::{AsyncRead as AsyncRead03, AsyncWrite as AsyncWrite03};
369 use std::io::Error;
370 use tokio_io::{AsyncRead as AsyncRead01, AsyncWrite as AsyncWrite01};
371
372 #[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
374 pub trait AsyncRead01CompatExt: AsyncRead01 {
375 fn compat(self) -> Compat01As03<Self>
394 where
395 Self: Sized,
396 {
397 Compat01As03::new(self)
398 }
399 }
400 impl<R: AsyncRead01> AsyncRead01CompatExt for R {}
401
402 #[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
404 pub trait AsyncWrite01CompatExt: AsyncWrite01 {
405 fn compat(self) -> Compat01As03<Self>
424 where
425 Self: Sized,
426 {
427 Compat01As03::new(self)
428 }
429 }
430 impl<W: AsyncWrite01> AsyncWrite01CompatExt for W {}
431
432 impl<R: AsyncRead01> AsyncRead03 for Compat01As03<R> {
433 fn poll_read(
434 mut self: Pin<&mut Self>,
435 cx: &mut Context<'_>,
436 buf: &mut [u8],
437 ) -> task03::Poll<Result<usize, Error>> {
438 poll_01_to_03(self.in_notify(cx, |x| x.poll_read(buf)))
439 }
440 }
441
442 impl<W: AsyncWrite01> AsyncWrite03 for Compat01As03<W> {
443 fn poll_write(
444 mut self: Pin<&mut Self>,
445 cx: &mut Context<'_>,
446 buf: &[u8],
447 ) -> task03::Poll<Result<usize, Error>> {
448 poll_01_to_03(self.in_notify(cx, |x| x.poll_write(buf)))
449 }
450
451 fn poll_flush(
452 mut self: Pin<&mut Self>,
453 cx: &mut Context<'_>,
454 ) -> task03::Poll<Result<(), Error>> {
455 poll_01_to_03(self.in_notify(cx, AsyncWrite01::poll_flush))
456 }
457
458 fn poll_close(
459 mut self: Pin<&mut Self>,
460 cx: &mut Context<'_>,
461 ) -> task03::Poll<Result<(), Error>> {
462 poll_01_to_03(self.in_notify(cx, AsyncWrite01::shutdown))
463 }
464 }
465}