async_ops/
lib.rs

1// Copyright 2021 Sanjin Sehic
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![no_std]
16#![warn(missing_docs)]
17
18//! `std:ops` traits for `Future`
19//!
20//! This crate provides a way to use
21//! [some `std::ops` traits](#supported-stdops-traits) with [futures](Future).
22//! To be able to use a [`std::ops`](core::ops) trait with a `Future`, first you
23//! need to wrap the `Future` with [`Async`] using [`async_ops::on`](crate::on).
24//! Then, as long the `Future::Output` type implements a supported `std::ops`
25//! trait, then the same `std::ops` trait will be implemented by the `Async`
26//! instance.
27//!
28//! Another option is to wrap a `Future` with `Async` using
29//! [`assignable!`] to enable usage of the `Assign` variants of `std::ops`
30//! traits on the `Future`.
31//!
32//! # Example
33//!
34//! When writing `async` code it is common to do operations that are supported
35//! through `std::ops`. For example, adding to numbers might look like this:
36//!
37//! ```rust
38//! use futures_executor::block_on;
39//!
40//! // Immediately returning a number is done for simplicity and production code
41//! // wouldn't just immediately return a value.
42//! let a = async { 40 };
43//! let b = async { 2 };
44//!
45//! let result = async { a.await + b.await };
46//!
47//! assert_eq!(42, block_on(result));
48//! ```
49//!
50//! Actually, the above code is not optimally implemented because `a` and `b`
51//! are `await`-ed sequentially, instead of concurrently. The appropriate
52//! solution is to use `join!` to be able to concurrently `await` both values
53//! like this:
54//!
55//! ```rust
56//! # use futures_executor::block_on;
57//! # let a = async { 40 };
58//! # let b = async { 2 };
59//!
60//! use futures_util::join;
61//!
62//! let result = async {
63//!   let (a, b) = join!(a, b);
64//!   a + b
65//! };
66//!
67//! assert_eq!(42, block_on(result));
68//! ```
69//!
70//! Or, just use [`async_ops::on`](crate::on) to do the same thing like the
71//! above example in one line:
72//!
73//! ```rust
74//! # use futures_executor::block_on;
75//! # let a = async { 40 };
76//! # let b = async { 2 };
77//!
78//! let result = async { (async_ops::on(a) + b).await };
79//!
80//! assert_eq!(42, block_on(result));
81//! ```
82//!
83//! Note that the `async_ops::on` example will also concurrently `await` both
84//! values.
85//!
86//! # Supported `std::ops` traits
87//!
88//! ## Add
89//!
90//! `Async` implements `Add<Rhs> where Rhs: Future` when the wrapped
91//! `Future::Output` type implements `Add<Rhs::Output>`. The resulting type of
92//! the addition is
93//! `Async<impl Future<Output = <Future::Output as Add<Rhs::Output>>::Output>>`.
94//!
95//! ```rust
96//! use futures_executor::block_on;
97//!
98//! let a = async { 40 };
99//! let b = async { 2 };
100//!
101//! let result = async { (async_ops::on(a) + b).await };
102//!
103//! assert_eq!(42, block_on(result));
104//! ```
105//!
106//! ## AddAssign
107//!
108//! `Async` implements `AddAssign<Rhs> where Rhs: Future` when the wrapped
109//! `Future` type implements `Assignable<<Async<Future> as Add<Rhs>>::Output>`,
110//! which in turn requires the `Future::Output` type to implement
111//! `Add<Rhs::Output>`.
112//!
113//! ```rust
114//! use futures_executor::block_on;
115//!
116//! let a = async { 40 };
117//! let b = async { 2 };
118//!
119//! let result = async {
120//!   async_ops::assignable!(a);
121//!   a += b;
122//!   a.await
123//! };
124//!
125//! assert_eq!(42, block_on(result));
126//! ```
127//!
128//! ## BitAnd
129//!
130//! `Async` implements `BitAnd<Rhs> where Rhs: Future` when the wrapped
131//! `Future::Output` type implements `BitAnd<Rhs::Output>`. The resulting type
132//! of the bitwise and is
133//! `Async<impl Future<Output = <Future::Output as BitAnd<Rhs::Output>>::Output>>`.
134//!
135//! ```rust
136//! use futures_executor::block_on;
137//!
138//! let a = async { 110 };
139//! let b = async { 59 };
140//!
141//! let result = async { (async_ops::on(a) & b).await };
142//!
143//! assert_eq!(42, block_on(result));
144//! ```
145//!
146//! ## BitAndAssign
147//!
148//! `Async` implements `BitAndAssign<Rhs> where Rhs: Future` when the wrapped
149//! `Future` type implements
150//! `Assignable<<Async<Future> as BitAnd<Rhs>>::Output>`, which in turn requires
151//! the `Future::Output` type to implement `BitAnd<Rhs::Output>`.
152//!
153//! ```rust
154//! use futures_executor::block_on;
155//!
156//! let a = async { 110 };
157//! let b = async { 59 };
158//!
159//! let result = async {
160//!   async_ops::assignable!(a);
161//!   a &= b;
162//!   a.await
163//! };
164//!
165//! assert_eq!(42, block_on(result));
166//! ```
167//!
168//! ## BitOr
169//!
170//! `Async` implements `BitOr<Rhs> where Rhs: Future` when the wrapped
171//! `Future::Output` type implements `BitOr<Rhs::Output>`. The resulting type of
172//! the bitwise or is
173//! `Async<impl Future<Output = <Future::Output as BitOr<Rhs::Output>>::Output>>`.
174//!
175//! ```rust
176//! use futures_executor::block_on;
177//!
178//! let a = async { 40 };
179//! let b = async { 10 };
180//!
181//! let result = async { (async_ops::on(a) | b).await };
182//!
183//! assert_eq!(42, block_on(result));
184//! ```
185//!
186//! ## BitOrAssign
187//!
188//! `Async` implements `BitOrAssign<Rhs> where Rhs: Future` when the wrapped
189//! `Future` type implements
190//! `Assignable<<Async<Future> as BitOr<Rhs>>::Output>`, which in turn requires
191//! the `Future::Output` type to implement `BitOr<Rhs::Output>`.
192//!
193//! ```rust
194//! use futures_executor::block_on;
195//!
196//! let a = async { 40 };
197//! let b = async { 10 };
198//!
199//! let result = async {
200//!   async_ops::assignable!(a);
201//!   a |= b;
202//!   a.await
203//! };
204//!
205//! assert_eq!(42, block_on(result));
206//! ```
207//!
208//! ## BitXor
209//!
210//! `Async` implements `BitXor<Rhs> where Rhs: Future` when the wrapped
211//! `Future::Output` type implements `BitXor<Rhs::Output>`. The resulting type
212//! of the bitwise xor is
213//! `Async<impl Future<Output = <Future::Output as BitXor<Rhs::Output>>::Output>>`.
214//!
215//! ```rust
216//! use futures_executor::block_on;
217//!
218//! let a = async { 38 };
219//! let b = async { 12 };
220//!
221//! let result = async { (async_ops::on(a) ^ b).await };
222//!
223//! assert_eq!(42, block_on(result));
224//! ```
225//!
226//! ## BitXorAssign
227//!
228//! `Async` implements `BitXorAssign<Rhs> where Rhs: Future` when the wrapped
229//! `Future` type implements
230//! `Assignable<<Async<Future> as BitXor<Rhs>>::Output>`, which in turn requires
231//! the `Future::Output` type to implement `BitXor<Rhs::Output>`.
232//!
233//! ```rust
234//! use futures_executor::block_on;
235//!
236//! let a = async { 38 };
237//! let b = async { 12 };
238//!
239//! let result = async {
240//!   async_ops::assignable!(a);
241//!   a ^= b;
242//!   a.await
243//! };
244//!
245//! assert_eq!(42, block_on(result));
246//! ```
247//!
248//! ## Div
249//!
250//! `Async` implements `Div<Rhs> where Rhs: Future` when the wrapped
251//! `Future::Output` type implements `Div<Rhs::Output>`. The resulting type of
252//! the division is
253//! `Async<impl Future<Output = <Future::Output as Div<Rhs::Output>>::Output>>`.
254//!
255//! ```rust
256//! use futures_executor::block_on;
257//!
258//! let a = async { 84 };
259//! let b = async { 2 };
260//!
261//! let result = async { (async_ops::on(a) / b).await };
262//!
263//! assert_eq!(42, block_on(result));
264//! ```
265//!
266//! ## DivAssign
267//!
268//! `Async` implements `DivAssign<Rhs> where Rhs: Future` when the wrapped
269//! `Future` type implements `Assignable<<Async<Future> as Div<Rhs>>::Output>`,
270//! which in turn requires the `Future::Output` type to implement
271//! `Div<Rhs::Output>`.
272//!
273//! ```rust
274//! use futures_executor::block_on;
275//!
276//! let a = async { 84 };
277//! let b = async { 2 };
278//!
279//! let result = async {
280//!   async_ops::assignable!(a);
281//!   a /= b;
282//!   a.await
283//! };
284//!
285//! assert_eq!(42, block_on(result));
286//! ```
287//!
288//! ## Mul
289//!
290//! `Async` implements `Mul<Rhs> where Rhs: Future` when the wrapped
291//! `Future::Output` type implements `Mul<Rhs::Output>`. The resulting type of
292//! the multiplication is
293//! `Async<impl Future<Output = <Future::Output as Mul<Rhs::Output>>::Output>>`.
294//!
295//! ```rust
296//! use futures_executor::block_on;
297//!
298//! let a = async { 21 };
299//! let b = async { 2 };
300//!
301//! let result = async { (async_ops::on(a) * b).await };
302//!
303//! assert_eq!(42, block_on(result));
304//! ```
305//!
306//! ## MulAssign
307//!
308//! `Async` implements `MulAssign<Rhs> where Rhs: Future` when the wrapped
309//! `Future` type implements `Assignable<<Async<Future> as Mul<Rhs>>::Output>`,
310//! which in turn requires the `Future::Output` type to implement
311//! `Mul<Rhs::Output>`.
312//!
313//! ```rust
314//! use futures_executor::block_on;
315//!
316//! let a = async { 21 };
317//! let b = async { 2 };
318//!
319//! let result = async {
320//!   async_ops::assignable!(a);
321//!   a *= b;
322//!   a.await
323//! };
324//!
325//! assert_eq!(42, block_on(result));
326//! ```
327//!
328//! ## Neg
329//!
330//! `Async` implements `Neg` when the wrapped `Future::Output` type implements
331//! `Neg`. The resulting type of the negation is
332//! `Async<impl Future<Output = <Future::Output as Neg>::Output>>`.
333//!
334//! ```rust
335//! use futures_executor::block_on;
336//!
337//! let a = async { -42 };
338//!
339//! let result = async { (-async_ops::on(a)).await };
340//!
341//! assert_eq!(42, block_on(result));
342//! ```
343//!
344//! ## Not
345//!
346//! `Async` implements `Not` when the wrapped `Future::Output` type implements
347//! `Not`. The resulting type of the logical negation is
348//! `Async<impl Future<Output = <Future::Output as Not>::Output>>`.
349//!
350//! ```rust
351//! use futures_executor::block_on;
352//!
353//! let a = async { 213_u8 };
354//!
355//! let result = async { (!async_ops::on(a)).await };
356//!
357//! assert_eq!(42, block_on(result));
358//! ```
359//!
360//! ## Rem
361//!
362//! `Async` implements `Rem<Rhs> where Rhs: Future` when the wrapped
363//! `Future::Output` type implements `Rem<Rhs::Output>`. The resulting type of
364//! the reminder operation is
365//! `Async<impl Future<Output = <Future::Output as Rem<Rhs::Output>>::Output>>`.
366//!
367//! ```rust
368//! use futures_executor::block_on;
369//!
370//! let a = async { 42 };
371//! let b = async { 5 };
372//!
373//! let result = async { (async_ops::on(a) % b).await };
374//!
375//! assert_eq!(2, block_on(result));
376//! ```
377//!
378//! ## RemAssign
379//!
380//! `Async` implements `RemAssign<Rhs> where Rhs: Future` when the wrapped
381//! `Future` type implements `Assignable<<Async<Future> as Rem<Rhs>>::Output>`,
382//! which in turn requires the `Future::Output` type to implement
383//! `Rem<Rhs::Output>`.
384//!
385//! ```rust
386//! use futures_executor::block_on;
387//!
388//! let a = async { 42 };
389//! let b = async { 5 };
390//!
391//! let result = async {
392//!   async_ops::assignable!(a);
393//!   a %= b;
394//!   a.await
395//! };
396//!
397//! assert_eq!(2, block_on(result));
398//! ```
399//!
400//! ## Shl
401//!
402//! `Async` implements `Shl<Rhs> where Rhs: Future` when the wrapped
403//! `Future::Output` type implements `Shl<Rhs::Output>`. The resulting type of
404//! the left shift is
405//! `Async<impl Future<Output = <Future::Output as Shl<Rhs::Output>>::Output>>`.
406//!
407//! ```rust
408//! use futures_executor::block_on;
409//!
410//! let a = async { 21 };
411//! let b = async { 1 };
412//!
413//! let result = async { (async_ops::on(a) << b).await };
414//!
415//! assert_eq!(42, block_on(result));
416//! ```
417//!
418//! ## ShlAssign
419//!
420//! `Async` implements `ShlAssign<Rhs> where Rhs: Future` when the wrapped
421//! `Future` type implements `Assignable<<Async<Future> as Shl<Rhs>>::Output>`,
422//! which in turn requires the `Future::Output` type to implement
423//! `Shl<Rhs::Output>`.
424//!
425//! ```rust
426//! use futures_executor::block_on;
427//!
428//! let a = async { 21 };
429//! let b = async { 1 };
430//!
431//! let result = async {
432//!   async_ops::assignable!(a);
433//!   a <<= b;
434//!   a.await
435//! };
436//!
437//! assert_eq!(42, block_on(result));
438//! ```
439//!
440//! ## Shr
441//!
442//! `Async` implements `Shr<Rhs> where Rhs: Future` when the wrapped
443//! `Future::Output` type implements `Shr<Rhs::Output>`. The resulting type of
444//! the right shift is
445//! `Async<impl Future<Output = <Future::Output as Shr<Rhs::Output>>::Output>>`.
446//!
447//! ```rust
448//! use futures_executor::block_on;
449//!
450//! let a = async { 168 };
451//! let b = async { 2 };
452//!
453//! let result = async { (async_ops::on(a) >> b).await };
454//!
455//! assert_eq!(42, block_on(result));
456//! ```
457//!
458//! ## ShrAssign
459//!
460//! `Async` implements `ShrAssign<Rhs> where Rhs: Future` when the wrapped
461//! `Future` type implements `Assignable<<Async<Future> as Shr<Rhs>>::Output>`,
462//! which in turn requires the `Future::Output` type to implement
463//! `Shr<Rhs::Output>`.
464//!
465//! ```rust
466//! use futures_executor::block_on;
467//!
468//! let a = async { 168 };
469//! let b = async { 2 };
470//!
471//! let result = async {
472//!   async_ops::assignable!(a);
473//!   a >>= b;
474//!   a.await
475//! };
476//!
477//! assert_eq!(42, block_on(result));
478//! ```
479//!
480//! ## Sub
481//!
482//! `Async` implements `Sub<Rhs> where Rhs: Future` when the wrapped
483//! `Future::Output` type implements `Sub<Rhs::Output>`. The resulting type of
484//! the subtraction is
485//! `Async<impl Future<Output = <Future::Output as Sub<Rhs::Output>>::Output>>`.
486//!
487//! ```rust
488//! use futures_executor::block_on;
489//!
490//! let a = async { 44 };
491//! let b = async { 2 };
492//!
493//! let result = async { (async_ops::on(a) - b).await };
494//!
495//! assert_eq!(42, block_on(result));
496//! ```
497//!
498//! ## SubAssign
499//!
500//! `Async` implements `SubAssign<Rhs> where Rhs: Future` when the wrapped
501//! `Future` type implements `Assignable<<Async<Future> as Sub<Rhs>>::Output>`,
502//! which in turn requires the `Future::Output` type to implement
503//! `Sub<Rhs::Output>`.
504//!
505//! ```rust
506//! use futures_executor::block_on;
507//!
508//! let a = async { 44 };
509//! let b = async { 2 };
510//!
511//! let result = async {
512//!   async_ops::assignable!(a);
513//!   a -= b;
514//!   a.await
515//! };
516//!
517//! assert_eq!(42, block_on(result));
518//! ```
519
520extern crate alloc;
521
522mod ops;
523
524use core::future::Future;
525use core::pin::Pin;
526use core::task::{Context, Poll};
527
528use futures::future::BoxFuture;
529use pin_project_lite::pin_project;
530
531pub use ops::{
532  add, bitand, bitor, bitxor, div, mul, neg, not, rem, shl, shr, sub, Add, Assignable, Binary,
533  BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, Unary,
534};
535
536/// Wraps the given [`Future`] with [`Async`].
537///
538/// # Example
539///
540/// ```rust
541/// use futures_executor::block_on;
542///
543/// let a = async { 40 };
544/// let b = async { 2 };
545///
546/// let result = async { (async_ops::on(a) + b).await };
547///
548/// assert_eq!(42, block_on(result));
549/// ```
550pub fn on<Fut: Future>(future: Fut) -> Async<Fut> {
551  Async { future }
552}
553
554/// Wraps the given [`Future`] with [`Async`] so that the result can be used
555/// with the `Assign` variants of [`std::ops`](core::ops) traits.
556///
557/// See also [`Async::assignable`].
558///
559/// # Example
560///
561/// ```rust
562/// use futures_executor::block_on;
563///
564/// let a = async { 40 };
565/// let b = async { 2 };
566///
567/// let result = async {
568///   async_ops::assignable!(a);
569///   a += b;
570///   a.await
571/// };
572///
573/// assert_eq!(42, block_on(result));
574/// ```
575#[macro_export]
576macro_rules! assignable {
577  ($var:ident) => {
578    let mut $var = $crate::assignable($var);
579  };
580}
581
582/// Wraps the given [`Future`] with [`Async`] so that the result can be used
583/// with the `Assign` variants of [`std::ops`](core::ops) traits.
584///
585/// Use [`assignable!`] and [`Async::assignable`] instead.
586///
587/// # Example
588///
589/// ```rust
590/// use futures_executor::block_on;
591///
592/// let a = async { 40 };
593/// let b = async { 2 };
594///
595/// let result = async {
596///   let mut a = async_ops::assignable(a);
597///   a += b;
598///   a.await
599/// };
600///
601/// assert_eq!(42, block_on(result));
602/// ```
603#[deprecated(
604  since = "1.1.0",
605  note = "Use assignable! or Async::assignable instead."
606)]
607pub fn assignable<'a, Fut: Future + Send + 'a>(future: Fut) -> Async<BoxFuture<'a, Fut::Output>> {
608  let future: BoxFuture<Fut::Output> = Assignable::from(future);
609  Async { future }
610}
611
612pin_project! {
613  /// A wrapper class for a [`Future`] that enables usage of some
614  /// [`std::ops`](core::ops) traits.
615  ///
616  /// This struct will implement a supported `std::ops` trait when
617  /// `<Fut as Future>::Output` type implements the same `std::ops` trait.
618  #[must_use = "futures do nothing unless you `.await` or poll them"]
619  pub struct Async<Fut: Future> {
620    #[pin]
621    future: Fut
622  }
623}
624
625impl<Fut: Future> Async<Fut> {
626  /// Wraps the inner [`Future`] in [`Async`] with the given `Assignable` type
627  /// so that it can be used with `Assign` variants of [`std::ops`](core::ops)
628  /// traits.
629  ///
630  /// See also [`assignable!`].
631  ///
632  /// # Example
633  ///
634  /// ```rust
635  /// use futures_executor::block_on;
636  /// use futures::future::LocalBoxFuture;
637  ///
638  /// let a = async { 40 };
639  /// let b = async { 2 };
640  ///
641  /// let result = async {
642  ///   let mut a = async_ops::on(a).assignable::<LocalBoxFuture<usize>>();
643  ///   a += b;
644  ///   a.await
645  /// };
646  ///
647  /// assert_eq!(42, block_on(result));
648  /// ```
649  pub fn assignable<T: Assignable<Fut> + Future>(self) -> Async<T> {
650    Async {
651      future: T::from(self.future),
652    }
653  }
654
655  /// Does the given [`Unary`] operation `Op` on the wrapped [`Future`] in
656  /// [`Async`] and returns the result in a new [`Async`].
657  ///
658  /// # Example
659  ///
660  /// ```rust
661  /// use std::future::{ready, Ready};
662  /// use futures_executor::block_on;
663  /// use async_ops::Unary;
664  ///
665  /// struct Return42;
666  ///
667  /// impl<Operand> Unary<Operand> for Return42 {
668  ///   type Output = Ready<usize>;
669  ///   fn op(_: Operand) -> Self::Output {
670  ///     ready(42)
671  ///   }
672  /// }
673  ///
674  /// let a = async { 2 };
675  ///
676  /// let result = async {
677  ///   async_ops::on(a).unary_op(Return42).await
678  /// };
679  ///
680  /// assert_eq!(42, block_on(result));
681  /// ```
682  pub fn unary_op<Op: Unary<Fut>>(self, _: Op) -> Async<Op::Output>
683  where
684    Op::Output: Future,
685  {
686    crate::on(Op::op(self.future))
687  }
688
689  /// Does the given [`Binary`] operation `Op` on the wrapped [`Future`] in
690  /// [`Async`] and the given right-hand operand and returns the result in a new
691  /// [`Async`].
692  ///
693  /// See also [`Async::op_assign`].
694  ///
695  /// # Example
696  ///
697  /// ```rust
698  /// use futures_executor::block_on;
699  /// use async_ops::Binary;
700  ///
701  /// struct ReturnRhs;
702  ///
703  /// impl<Lhs, Rhs> Binary<Lhs, Rhs> for ReturnRhs {
704  ///   type Output = Rhs;
705  ///   fn op(_: Lhs, rhs: Rhs) -> Self::Output {
706  ///     rhs
707  ///   }
708  /// }
709  ///
710  /// let a = async { 2 };
711  /// let b = async { 42 };
712  ///
713  /// let result = async {
714  ///   async_ops::on(a).op(ReturnRhs, b).await
715  /// };
716  ///
717  /// assert_eq!(42, block_on(result));
718  /// ```
719  pub fn op<Rhs, Op: Binary<Fut, Rhs>>(self, _: Op, rhs: Rhs) -> Async<Op::Output>
720  where
721    Op::Output: Future,
722  {
723    crate::on(Op::op(self.future, rhs))
724  }
725
726  /// Does the given [`Binary`] operation `Op` on the wrapped [`Future`] in
727  /// [`Async`] and the given right-hand operand and assigns it to `self`.
728  ///
729  /// See also [`Async::op`].
730  ///
731  /// # Example
732  ///
733  /// ```rust
734  /// use futures_executor::block_on;
735  /// use async_ops::Binary;
736  ///
737  /// struct ReturnRhs;
738  ///
739  /// impl<Lhs, Rhs> Binary<Lhs, Rhs> for ReturnRhs {
740  ///   type Output = Rhs;
741  ///   fn op(_: Lhs, rhs: Rhs) -> Self::Output {
742  ///     rhs
743  ///   }
744  /// }
745  ///
746  /// let a = async { 2 };
747  /// let b = async { 42 };
748  ///
749  /// let result = async {
750  ///   async_ops::assignable!(a);
751  ///   a.op_assign(ReturnRhs, b);
752  ///   a.await
753  /// };
754  ///
755  /// assert_eq!(42, block_on(result));
756  /// ```
757  pub fn op_assign<Rhs, Op: Binary<Fut, Rhs>>(&mut self, _: Op, rhs: Rhs)
758  where
759    Fut: Assignable<Op::Output>,
760    Op::Output: Future,
761  {
762    Op::op_assign(&mut self.future, rhs);
763  }
764}
765
766impl<Fut: Future> Future for Async<Fut> {
767  type Output = Fut::Output;
768
769  fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
770    self.project().future.poll(cx)
771  }
772}
773
774#[cfg(test)]
775mod tests {
776  use super::*;
777
778  use alloc::rc::Rc;
779  use core::cell::RefCell;
780
781  use futures_util::future::FutureExt;
782
783  pin_project! {
784    #[derive(Default)]
785    struct FakeFuture<T> {
786      value: Option<T>,
787      // This is of course not safe in the multi-threaded world and normally
788      // Arc and future-safe Mutex should be used. However, because we are only
789      // using now_or_never() to immediately poll the future on the same thread,
790      // it is safe to use Rc and RefCell here.
791      polled_times: Rc<RefCell<usize>>,
792    }
793  }
794
795  impl<T> Future for FakeFuture<T> {
796    type Output = T;
797
798    fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
799      let this = self.project();
800      *this.polled_times.borrow_mut() += 1;
801      match this.value.take() {
802        Some(value) => Poll::Ready(value),
803        None => Poll::Pending,
804      }
805    }
806  }
807
808  #[test]
809  fn ready_when_the_wrapped_future_is_ready() {
810    let mut future = FakeFuture::default();
811    let polled_times = future.polled_times.clone();
812
813    assert_eq!(0, *polled_times.borrow());
814
815    future.value = Some(42);
816    assert_eq!(Some(42), on(future).now_or_never());
817
818    assert_eq!(1, *polled_times.borrow());
819  }
820
821  #[test]
822  fn pending_when_the_wrapped_future_is_pending() {
823    let future = FakeFuture::<usize>::default();
824    let polled_times = future.polled_times.clone();
825
826    assert_eq!(0, *polled_times.borrow());
827
828    assert_eq!(None, on(future).now_or_never());
829
830    assert_eq!(1, *polled_times.borrow());
831  }
832}
833
834#[cfg(doctest)]
835mod readme {
836  use doc_comment::doctest;
837
838  doctest!("../README.md");
839}