1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! The [`PollOnce`] extension trait for host-driven polling.
//!
//! This trait adds a [`poll_once`](PollOnce::poll_once) method to boxed
//! futures, allowing foreign hosts (Go, Java, Python, C, Swift) to drive
//! Rust async state machines without an async runtime.
//!
//! # Example
//!
//! ```rust
//! use core::task::Poll;
//! use future_form::{FutureForm, Sendable, Local};
//! use future_form_ffi::poll_once::PollOnce;
//!
//! // Works on Sendable futures
//! let mut fut = Sendable::from_future(async { 42u32 });
//! assert_eq!(fut.poll_once(), Poll::Ready(42));
//!
//! // Works on Local futures too
//! let mut fut = Local::from_future(async { 42u32 });
//! assert_eq!(fut.poll_once(), Poll::Ready(42));
//! ```
use Box;
use ;
use ;
/// Poll a boxed future once using a no-op waker.
///
/// This is the core primitive for host-driven (sans-IO) async execution.
/// Instead of handing a future to an async runtime, the foreign host calls
/// `poll_once()` repeatedly until the future resolves.
///
/// # Why a trait instead of [`Future`]?
///
/// `PollOnce` looks structurally similar to [`Future::poll`], but differs
/// in two ways that make it a better fit for FFI host-driven polling:
///
/// | | [`Future::poll`] | `PollOnce::poll_once` |
/// |----------|------------------------------------|-----------------------------|
/// | Receiver | `Pin<&mut Self>` | `&mut self` |
/// | Waker | Caller supplies `&mut Context<'_>` | Hardcoded [`Waker::noop()`] |
///
/// **`&mut self` instead of `Pin<&mut Self>`** — the implementations only
/// exist for _already-pinned_ types (`BoxFuture` is
/// `Pin<Box<dyn Future>>`), so the caller never needs to pin anything
/// manually. This keeps FFI bridge code simple.
///
/// **No `Context` / `Waker` parameter** — host-driven polling has no
/// async runtime to wake. The host decides when to re-poll (typically
/// after fulfilling an effect). Baking in [`Waker::noop()`] removes a
/// concept that is meaningless in the FFI context.
///
/// A free function could provide the same _functionality_, but a trait
/// gives uniform `.poll_once()` method syntax across [`BoxFuture`] and
/// [`LocalBoxFuture`] without requiring wrapper boilerplate in every
/// bridge crate.
///
/// # Noop waker
///
/// [`Waker::noop()`] does nothing on `wake()`. This is correct for
/// host-driven polling because the host controls the polling cadence.
///
/// Futures that depend on wake notifications to make progress (e.g., tokio
/// channels, timers) will _not_ advance under noop polling. Host-driven
/// futures should use [`core::future::poll_fn`] and check shared state
/// (atomics, mutexes) directly.
///
/// # Example
///
/// ```rust
/// use core::task::Poll;
/// use future_form::{FutureForm, Sendable, Local};
/// use future_form_ffi::poll_once::PollOnce;
///
/// // Works on Sendable futures
/// let mut fut = Sendable::from_future(async { 42u32 });
/// assert_eq!(fut.poll_once(), Poll::Ready(42));
///
/// // Works on Local futures too
/// let mut fut = Local::from_future(async { 42u32 });
/// assert_eq!(fut.poll_once(), Poll::Ready(42));
/// ```