wit_bindgen/rt/async_support/
future_support.rs

1//! Runtime support for `future<T>` in the component model.
2//!
3//! There are a number of tricky concerns to all balance when implementing
4//! bindings to `future<T>`, specifically with how it interacts with Rust. This
5//! will attempt to go over some of the high-level details of the implementation
6//! here.
7//!
8//! ## Leak safety
9//!
10//! It's safe to leak any value at any time currently in Rust. In other words
11//! Rust doesn't have linear types (yet). Typically this isn't really a problem
12//! but the component model intrinsics we're working with here operate by being
13//! given a pointer and then at some point in the future the pointer may be
14//! read. This means that it's our responsibility to keep this pointer alive and
15//! valid for the entire duration of an asynchronous operation.
16//!
17//! Chiefly this means that borrowed values are a no-no in this module. For
18//! example if you were to send a `&[u8]` as an implementation of
19//! `future<list<u8>>` that would not be sound. For example:
20//!
21//! * The future send operation is started, recording an address of `&[u8]`.
22//! * The future is then leaked.
23//! * According to rustc, later in code the original `&[u8]` is then no longer
24//!   borrowed.
25//! * The original source of `&[u8]` could then be deallocated.
26//! * Then the component model actually reads the pointer that it was given.
27//!
28//! This constraint effectively means that all types flowing in-and-out of
29//! futures, streams, and async APIs are all "owned values", notably no
30//! lifetimes. This requires, for example, that `future<list<u8>>` operates on
31//! `Vec<u8>`.
32//!
33//! This is in stark contrast to bindings generated for `list<u8>` otherwise,
34//! however, where for example a synchronous import with a `list<u8>` argument
35//! would be bound with a `&[u8]` argument. Until Rust has some form of linear
36//! types, however, it's not possible to loosen this restriction soundly because
37//! it's generally not safe to leak an active I/O operation. This restriction is
38//! similar to why it's so difficult to bind `io_uring` in safe Rust, which
39//! operates similarly to the component model where pointers are submitted and
40//! read in the future after the original call for submission returns.
41//!
42//! ## Lowering Owned Values
43//!
44//! According to the above everything with futures/streams operates on owned
45//! values already, but this also affects precisely how lifting and lowering is
46//! performed. In general any active asynchronous operation could be cancelled
47//! at any time, meaning we have to deal with situations such as:
48//!
49//! * A `write` hasn't even started yet.
50//! * A `write` was started and then cancelled.
51//! * A `write` was started and then the other end dropped the channel.
52//! * A `write` was started and then the other end received the value.
53//!
54//! In all of these situations regardless of the structure of `T` we can't leak
55//! memory. The `future.write` intrinsic, however, takes no ownership of the
56//! memory involved which means that we're still responsible for cleaning up
57//! lists. It does take ownership, however, of `own<T>` handles and other
58//! resources.
59//!
60//! The way that this is solved for futures/streams is to lean further into
61//! processing owned values. Namely lowering a `T` takes `T`-by-value, not `&T`.
62//! This means that lowering operates similarly to return values of exported
63//! functions, not parameters to imported functions. By lowering an owned value
64//! of `T` this preserves a nice property where the lowered value has exclusive
65//! ownership of all of its pointers/resources/etc. Lowering `&T` may require a
66//! "cleanup list" for example which we avoid here entirely.
67//!
68//! This then makes the second and third cases above, getting a value back after
69//! lowering, much easier. Namely re-acquisition of a value is simple `lift`
70//! operation as if we received a value on the channel.
71//!
72//! ## Inefficiencies
73//!
74//! The above requirements generally mean that this is not a hyper-efficient
75//! implementation. All writes and reads, for example, start out with allocation
76//! memory on the heap to be owned by the asynchronous operation. Writing a
77//! `list<u8>` to a future passes ownership of `Vec<u8>` but in theory doesn't
78//! not actually require relinquishing ownership of the vector. Furthermore
79//! there's no way to re-acquire a `T` after it has been sent, but all of `T` is
80//! still valid except for `own<U>` resources.
81//!
82//! That's all to say that this implementation can probably still be improved
83//! upon, but doing so is thought to be pretty nontrivial at this time. It
84//! should be noted though that there are other high-level inefficiencies with
85//! WIT unrelated to this module. For example `list<T>` is not always
86//! represented the same in Rust as it is in the canonical ABI. That means that
87//! sending `list<T>` into a future might require copying the entire list and
88//! changing its layout. Currently this is par-for-the-course with bindings.
89//!
90//! ## Linear (exactly once) Writes
91//!
92//! The component model requires that a writable end of a future must be written
93//! to before closing, otherwise the drop operation traps. Ideally usage of
94//! this API shouldn't result in traps so this is modeled in the Rust-level API
95//! to prevent this trap from occurring. Rust does not support linear types
96//! (types that must be used exactly once), instead it only has affine types
97//! (types which must be used at most once), meaning that this requires some
98//! runtime support.
99//!
100//! Specifically the `FutureWriter` structure stores two auxiliary Rust-specific
101//! pieces of information:
102//!
103//! * A `should_write_default_value` boolean - if `true` on destruction then a
104//!   value has not yet been written and something must be written.
105//! * A `default: fn() -> T` constructor to lazily create the default value to
106//!   be sent in this situation.
107//!
108//! This `default` field is provided by the user when the future is initially
109//! created. Additionally during `Drop` a new Rust-level task will be spawned to
110//! perform the write in the background. That'll keep the component-level task
111//! alive until that write completes but otherwise shouldn't hinder anything
112//! else.
113
114use crate::rt::async_support::waitable::{WaitableOp, WaitableOperation};
115use crate::rt::async_support::ReturnCode;
116use crate::rt::Cleanup;
117use std::alloc::Layout;
118use std::fmt;
119use std::future::{Future, IntoFuture};
120use std::marker;
121use std::mem::{self, ManuallyDrop};
122use std::pin::Pin;
123use std::ptr;
124use std::sync::atomic::{AtomicU32, Ordering::Relaxed};
125use std::sync::{Arc, Mutex};
126use std::task::{Context, Poll, Wake, Waker};
127
128/// Helper trait which encapsulates the various operations which can happen
129/// with a future.
130pub trait FutureOps {
131    /// The Rust type that's sent or received on this future.
132    type Payload;
133
134    /// The `future.new` intrinsic.
135    fn new(&mut self) -> u64;
136    /// The canonical ABI layout of the type that this future is
137    /// sending/receiving.
138    fn elem_layout(&mut self) -> Layout;
139    /// Converts a Rust type to its canonical ABI representation.
140    unsafe fn lower(&mut self, payload: Self::Payload, dst: *mut u8);
141    /// Used to deallocate any Rust-owned lists in the canonical ABI
142    /// representation for when a value is successfully sent but needs to be
143    /// cleaned up.
144    unsafe fn dealloc_lists(&mut self, dst: *mut u8);
145    /// Converts from the canonical ABI representation to a Rust value.
146    unsafe fn lift(&mut self, dst: *mut u8) -> Self::Payload;
147    /// The `future.write` intrinsic
148    unsafe fn start_write(&mut self, future: u32, val: *const u8) -> u32;
149    /// The `future.read` intrinsic
150    unsafe fn start_read(&mut self, future: u32, val: *mut u8) -> u32;
151    /// The `future.cancel-read` intrinsic
152    unsafe fn cancel_read(&mut self, future: u32) -> u32;
153    /// The `future.cancel-write` intrinsic
154    unsafe fn cancel_write(&mut self, future: u32) -> u32;
155    /// The `future.drop-readable` intrinsic
156    unsafe fn drop_readable(&mut self, future: u32);
157    /// The `future.drop-writable` intrinsic
158    unsafe fn drop_writable(&mut self, future: u32);
159}
160
161/// Function table used for [`FutureWriter`] and [`FutureReader`]
162///
163/// Instances of this table are generated by `wit_bindgen::generate!`. This is
164/// not a trait to enable different `FutureVtable<()>` instances to exist, for
165/// example, through different calls to `wit_bindgen::generate!`.
166///
167/// It's not intended that any user implements this vtable, instead it's
168/// intended to only be auto-generated.
169#[doc(hidden)]
170pub struct FutureVtable<T> {
171    /// The Canonical ABI layout of `T` in-memory.
172    pub layout: Layout,
173
174    /// A callback to consume a value of `T` and lower it to the canonical ABI
175    /// pointed to by `dst`.
176    ///
177    /// The `dst` pointer should have `self.layout`. This is used to convert
178    /// in-memory representations in Rust to their canonical representations in
179    /// the component model.
180    pub lower: unsafe fn(value: T, dst: *mut u8),
181
182    /// A callback to deallocate any lists within the canonical ABI value `dst`
183    /// provided.
184    ///
185    /// This is used when a value is successfully sent to another component. In
186    /// such a situation it may be possible that the canonical lowering of `T`
187    /// has lists that are still owned by this component and must be
188    /// deallocated. This is akin to a `post-return` callback for returns of
189    /// exported functions.
190    pub dealloc_lists: unsafe fn(dst: *mut u8),
191
192    /// A callback to lift a value of `T` from the canonical ABI representation
193    /// provided.
194    pub lift: unsafe fn(dst: *mut u8) -> T,
195
196    /// The raw `future.write` intrinsic.
197    pub start_write: unsafe extern "C" fn(future: u32, val: *const u8) -> u32,
198    /// The raw `future.read` intrinsic.
199    pub start_read: unsafe extern "C" fn(future: u32, val: *mut u8) -> u32,
200    /// The raw `future.cancel-write` intrinsic.
201    pub cancel_write: unsafe extern "C" fn(future: u32) -> u32,
202    /// The raw `future.cancel-read` intrinsic.
203    pub cancel_read: unsafe extern "C" fn(future: u32) -> u32,
204    /// The raw `future.drop-writable` intrinsic.
205    pub drop_writable: unsafe extern "C" fn(future: u32),
206    /// The raw `future.drop-readable` intrinsic.
207    pub drop_readable: unsafe extern "C" fn(future: u32),
208    /// The raw `future.new` intrinsic.
209    pub new: unsafe extern "C" fn() -> u64,
210}
211
212impl<T> FutureOps for &'static FutureVtable<T> {
213    type Payload = T;
214
215    fn new(&mut self) -> u64 {
216        unsafe { (self.new)() }
217    }
218    fn elem_layout(&mut self) -> Layout {
219        self.layout
220    }
221    unsafe fn lower(&mut self, payload: Self::Payload, dst: *mut u8) {
222        (self.lower)(payload, dst)
223    }
224    unsafe fn dealloc_lists(&mut self, dst: *mut u8) {
225        (self.dealloc_lists)(dst)
226    }
227    unsafe fn lift(&mut self, dst: *mut u8) -> Self::Payload {
228        (self.lift)(dst)
229    }
230    unsafe fn start_write(&mut self, future: u32, val: *const u8) -> u32 {
231        (self.start_write)(future, val)
232    }
233    unsafe fn start_read(&mut self, future: u32, val: *mut u8) -> u32 {
234        (self.start_read)(future, val)
235    }
236    unsafe fn cancel_read(&mut self, future: u32) -> u32 {
237        (self.cancel_read)(future)
238    }
239    unsafe fn cancel_write(&mut self, future: u32) -> u32 {
240        (self.cancel_write)(future)
241    }
242    unsafe fn drop_readable(&mut self, future: u32) {
243        (self.drop_readable)(future)
244    }
245    unsafe fn drop_writable(&mut self, future: u32) {
246        (self.drop_writable)(future)
247    }
248}
249
250/// Helper function to create a new read/write pair for a component model
251/// future.
252///
253/// # Unsafety
254///
255/// This function is unsafe as it requires the functions within `vtable` to
256/// correctly uphold the contracts of the component model.
257pub unsafe fn future_new<T>(
258    default: fn() -> T,
259    vtable: &'static FutureVtable<T>,
260) -> (FutureWriter<T>, FutureReader<T>) {
261    let (tx, rx) = unsafe { raw_future_new(vtable) };
262    (FutureWriter::new(tx, default), rx)
263}
264
265/// Helper function to create a new read/write pair for a component model
266/// future.
267///
268/// # Unsafety
269///
270/// This function is unsafe as it requires the functions within `vtable` to
271/// correctly uphold the contracts of the component model.
272pub unsafe fn raw_future_new<O>(mut ops: O) -> (RawFutureWriter<O>, RawFutureReader<O>)
273where
274    O: FutureOps + Clone,
275{
276    unsafe {
277        let handles = ops.new();
278        let reader = handles as u32;
279        let writer = (handles >> 32) as u32;
280        rtdebug!("future.new() = [{writer}, {reader}]");
281        (
282            RawFutureWriter::new(writer, ops.clone()),
283            RawFutureReader::new(reader, ops),
284        )
285    }
286}
287
288/// Represents the writable end of a Component Model `future`.
289///
290/// A [`FutureWriter`] can be used to send a single value of `T` to the other
291/// end of a `future`. In a sense this is similar to a oneshot channel in Rust.
292pub struct FutureWriter<T: 'static> {
293    raw: ManuallyDrop<RawFutureWriter<&'static FutureVtable<T>>>,
294
295    /// Whether or not a value should be written during `drop`.
296    ///
297    /// This is set to `false` when a value is successfully written or when a
298    /// value is written but the future is witnessed as being dropped.
299    ///
300    /// Note that this is set to `true` on construction to ensure that only
301    /// location which actually witness a completed write set it to `false`.
302    should_write_default_value: bool,
303
304    /// Constructor for the default value to write during `drop`, should one
305    /// need to be written.
306    default: fn() -> T,
307}
308
309impl<T> FutureWriter<T> {
310    /// Helper function to wrap a handle/vtable into a `FutureWriter`.
311    ///
312    /// # Unsafety
313    ///
314    /// This function is unsafe as it requires the functions within `vtable` to
315    /// correctly uphold the contracts of the component model.
316    unsafe fn new(raw: RawFutureWriter<&'static FutureVtable<T>>, default: fn() -> T) -> Self {
317        Self {
318            raw: ManuallyDrop::new(raw),
319            default,
320            should_write_default_value: true,
321        }
322    }
323
324    /// Write the specified `value` to this `future`.
325    ///
326    /// This method is equivalent to an `async fn` which sends the `value` into
327    /// this future. The asynchronous operation acts as a rendezvous where the
328    /// operation does not complete until the other side has successfully
329    /// received the value.
330    ///
331    /// # Return Value
332    ///
333    /// The returned [`FutureWrite`] is a future that can be `.await`'d. The
334    /// return value of this future is:
335    ///
336    /// * `Ok(())` - the `value` was sent and received. The `self` value was
337    ///   consumed along the way and will no longer be accessible.
338    /// * `Err(FutureWriteError { value })` - an attempt was made to send
339    ///   `value` but the other half of this [`FutureWriter`] was dropped before
340    ///   the value was received. This consumes `self` because the channel is
341    ///   now dropped, but `value` is returned in case the caller wants to reuse
342    ///   it.
343    ///
344    /// # Cancellation
345    ///
346    /// The returned future can be cancelled normally via `drop` which means
347    /// that the `value` provided here, along with this `FutureWriter` itself,
348    /// will be lost. There is also [`FutureWrite::cancel`] which can be used to
349    /// possibly re-acquire `value` and `self` if the operation was cancelled.
350    /// In such a situation the operation can be retried at a future date.
351    pub fn write(mut self, value: T) -> FutureWrite<T> {
352        let raw = unsafe { ManuallyDrop::take(&mut self.raw).write(value) };
353        let default = self.default;
354        mem::forget(self);
355        FutureWrite { raw, default }
356    }
357}
358
359impl<T> fmt::Debug for FutureWriter<T> {
360    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361        f.debug_struct("FutureWriter")
362            .field("handle", &self.raw.handle)
363            .finish()
364    }
365}
366
367impl<T> Drop for FutureWriter<T> {
368    fn drop(&mut self) {
369        // If a value has not yet been written into this writer than that must
370        // be done so now. Take the `raw` writer and perform the write via a
371        // waker that drives the future.
372        //
373        // If `should_write_default_value` is `false` then a write has already
374        // happened and we can go ahead and just synchronously drop this writer
375        // as we would any other handle.
376        if self.should_write_default_value {
377            let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
378            let value = (self.default)();
379            raw.write_and_forget(value);
380        } else {
381            unsafe { ManuallyDrop::drop(&mut self.raw) }
382        }
383    }
384}
385
386/// Represents a write operation which may be cancelled prior to completion.
387///
388/// This is returned by [`FutureWriter::write`].
389pub struct FutureWrite<T: 'static> {
390    raw: RawFutureWrite<&'static FutureVtable<T>>,
391    default: fn() -> T,
392}
393
394/// Result of [`FutureWrite::cancel`].
395#[derive(Debug)]
396pub enum FutureWriteCancel<T: 'static> {
397    /// The cancel request raced with the receipt of the sent value, and the
398    /// value was actually sent. Neither the value nor the writer are made
399    /// available here as both are gone.
400    AlreadySent,
401
402    /// The other end was dropped before cancellation happened.
403    ///
404    /// In this case the original value is returned back to the caller but the
405    /// writer itself is not longer accessible as it's no longer usable.
406    Dropped(T),
407
408    /// The pending write was successfully cancelled and the value being written
409    /// is returned along with the writer to resume again in the future if
410    /// necessary.
411    Cancelled(T, FutureWriter<T>),
412}
413
414impl<T: 'static> Future for FutureWrite<T> {
415    type Output = Result<(), FutureWriteError<T>>;
416
417    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
418        self.pin_project().poll(cx)
419    }
420}
421
422impl<T: 'static> FutureWrite<T> {
423    fn pin_project(self: Pin<&mut Self>) -> Pin<&mut RawFutureWrite<&'static FutureVtable<T>>> {
424        // SAFETY: we've chosen that when `Self` is pinned that it translates to
425        // always pinning the inner field, so that's codified here.
426        unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().raw) }
427    }
428
429    /// Cancel this write if it hasn't already completed.
430    ///
431    /// This method can be used to cancel a write-in-progress and re-acquire
432    /// the writer and the value being sent. Note that the write operation may
433    /// succeed racily or the other end may also drop racily, and these
434    /// outcomes are reflected in the returned value here.
435    ///
436    /// # Panics
437    ///
438    /// Panics if the operation has already been completed via `Future::poll`,
439    /// or if this method is called twice.
440    pub fn cancel(self: Pin<&mut Self>) -> FutureWriteCancel<T> {
441        let default = self.default;
442        match self.pin_project().cancel() {
443            RawFutureWriteCancel::AlreadySent => FutureWriteCancel::AlreadySent,
444            RawFutureWriteCancel::Dropped(val) => FutureWriteCancel::Dropped(val),
445            RawFutureWriteCancel::Cancelled(val, raw) => FutureWriteCancel::Cancelled(
446                val,
447                FutureWriter {
448                    raw: ManuallyDrop::new(raw),
449                    default,
450                    should_write_default_value: true,
451                },
452            ),
453        }
454    }
455}
456
457impl<T: 'static> Drop for FutureWrite<T> {
458    fn drop(&mut self) {
459        if self.raw.op.is_done() {
460            return;
461        }
462
463        // Although the underlying `WaitableOperation` will already
464        // auto-cancel-on-drop we need to specially handle that here because if
465        // the cancellation goes through then it means that no value will have
466        // been written to this future which will cause a trap. By using
467        // `Self::cancel` it's ensured that if cancellation succeeds a
468        // `FutureWriter` is created. In `Drop for FutureWriter` that'll handle
469        // the last-ditch write-default logic.
470        //
471        // SAFETY: we're in the destructor here so the value `self` is about
472        // to go away and we can guarantee we're not moving out of it.
473        let pin = unsafe { Pin::new_unchecked(self) };
474        pin.cancel();
475    }
476}
477
478/// Raw version of [`FutureWriter`].
479pub struct RawFutureWriter<O: FutureOps> {
480    handle: u32,
481    ops: O,
482}
483
484impl<O: FutureOps> RawFutureWriter<O> {
485    unsafe fn new(handle: u32, ops: O) -> Self {
486        Self { handle, ops }
487    }
488
489    /// Same as [`FutureWriter::write`], but the raw version.
490    pub fn write(self, value: O::Payload) -> RawFutureWrite<O> {
491        RawFutureWrite {
492            op: WaitableOperation::new(FutureWriteOp(marker::PhantomData), (self, value)),
493        }
494    }
495
496    /// Writes `value` in the background.
497    ///
498    /// This does not block and is not cancellable.
499    pub fn write_and_forget(self, value: O::Payload)
500    where
501        O: 'static,
502    {
503        return Arc::new(DeferredWrite {
504            write: Mutex::new(self.write(value)),
505        })
506        .wake();
507
508        /// Helper structure which behaves both as a future of sorts and an
509        /// executor of sorts.
510        ///
511        /// This type is constructed in `Drop for FutureWriter<T>` to send out a
512        /// default value when no other has been written. This manages the
513        /// `FutureWrite` operation happening internally through a `Wake`
514        /// implementation. That means that this is a sort of cyclical future
515        /// which, when woken, will complete the write operation.
516        ///
517        /// The purpose of this is to be a "lightweight" way of "spawn"-ing a
518        /// future write to happen in the background. Crucially, however, this
519        /// doesn't require the `async-spawn` feature and instead works with the
520        /// `wasip3_task` C ABI structures (which spawn doesn't support).
521        struct DeferredWrite<O: FutureOps> {
522            write: Mutex<RawFutureWrite<O>>,
523        }
524
525        // SAFETY: Needed to satisfy `Waker::from` but otherwise should be ok
526        // because wasm doesn't have threads anyway right now.
527        unsafe impl<O: FutureOps> Send for DeferredWrite<O> {}
528        unsafe impl<O: FutureOps> Sync for DeferredWrite<O> {}
529
530        impl<O: FutureOps + 'static> Wake for DeferredWrite<O> {
531            fn wake(self: Arc<Self>) {
532                // When a `wake` signal comes in that should happen in two
533                // locations:
534                //
535                // 1. When `DeferredWrite` is initially constructed.
536                // 2. When an event comes in indicating that the internal write
537                //    has completed.
538                //
539                // The implementation here is the same in both cases. A clone of
540                // `self` is converted to a `Waker`, and this `Waker` notably
541                // owns the internal future itself. The internal write operation
542                // is then pushed forward (e.g. it's issued in (1) or checked up
543                // on in (2)).
544                //
545                // If `Pending` is returned then `waker` should have been stored
546                // away within the `wasip3_task` C ABI structure. Otherwise it
547                // should not have been stored away and `self` should be the
548                // sole reference which means everything will get cleaned up
549                // when this function returns.
550                let poll = {
551                    let waker = Waker::from(self.clone());
552                    let mut cx = Context::from_waker(&waker);
553                    let mut write = self.write.lock().unwrap();
554                    unsafe { Pin::new_unchecked(&mut *write).poll(&mut cx) }
555                };
556                if poll.is_ready() {
557                    assert_eq!(Arc::strong_count(&self), 1);
558                } else {
559                    assert!(Arc::strong_count(&self) > 1);
560                }
561                assert_eq!(Arc::weak_count(&self), 0);
562            }
563        }
564    }
565}
566
567impl<O: FutureOps> fmt::Debug for RawFutureWriter<O> {
568    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569        f.debug_struct("RawFutureWriter")
570            .field("handle", &self.handle)
571            .finish()
572    }
573}
574
575impl<O: FutureOps> Drop for RawFutureWriter<O> {
576    fn drop(&mut self) {
577        unsafe {
578            rtdebug!("future.drop-writable({})", self.handle);
579            self.ops.drop_writable(self.handle);
580        }
581    }
582}
583
584/// Represents a write operation which may be cancelled prior to completion.
585///
586/// This is returned by [`FutureWriter::write`].
587pub struct RawFutureWrite<O: FutureOps> {
588    op: WaitableOperation<FutureWriteOp<O>>,
589}
590
591struct FutureWriteOp<O>(marker::PhantomData<O>);
592
593enum WriteComplete<T> {
594    Written,
595    Dropped(T),
596    Cancelled(T),
597}
598
599unsafe impl<O: FutureOps> WaitableOp for FutureWriteOp<O> {
600    type Start = (RawFutureWriter<O>, O::Payload);
601    type InProgress = (RawFutureWriter<O>, Option<Cleanup>);
602    type Result = (WriteComplete<O::Payload>, RawFutureWriter<O>);
603    type Cancel = RawFutureWriteCancel<O>;
604
605    fn start(&mut self, (mut writer, value): Self::Start) -> (u32, Self::InProgress) {
606        // TODO: it should be safe to store the lower-destination in
607        // `WaitableOperation` using `Pin` memory and such, but that would
608        // require some type-level trickery to get a correctly-sized value
609        // plumbed all the way to here. For now just dynamically allocate it and
610        // leave the optimization of leaving out this dynamic allocation to the
611        // future.
612        //
613        // In lieu of that a dedicated location on the heap is created for the
614        // lowering, and then `value`, as an owned value, is lowered into this
615        // pointer to initialize it.
616        let (ptr, cleanup) = Cleanup::new(writer.ops.elem_layout());
617        // SAFETY: `ptr` is allocated with `ops.layout` and should be
618        // safe to use here.
619        let code = unsafe {
620            writer.ops.lower(value, ptr);
621            writer.ops.start_write(writer.handle, ptr)
622        };
623        rtdebug!("future.write({}, {ptr:?}) = {code:#x}", writer.handle);
624        (code, (writer, cleanup))
625    }
626
627    fn start_cancelled(&mut self, (writer, value): Self::Start) -> Self::Cancel {
628        RawFutureWriteCancel::Cancelled(value, writer)
629    }
630
631    fn in_progress_update(
632        &mut self,
633        (mut writer, cleanup): Self::InProgress,
634        code: u32,
635    ) -> Result<Self::Result, Self::InProgress> {
636        let ptr = cleanup
637            .as_ref()
638            .map(|c| c.ptr.as_ptr())
639            .unwrap_or(ptr::null_mut());
640        match code {
641            super::BLOCKED => Err((writer, cleanup)),
642
643            // The other end has dropped its end.
644            //
645            // The value was not received by the other end so `ptr` still has
646            // all of its resources intact. Use `lift` to construct a new
647            // instance of `T` which takes ownership of pointers and resources
648            // and such. The allocation of `ptr` is then cleaned up naturally
649            // when `cleanup` goes out of scope.
650            super::DROPPED | super::CANCELLED => {
651                // SAFETY: we're the ones managing `ptr` so we know it's safe to
652                // pass here.
653                let value = unsafe { writer.ops.lift(ptr) };
654                let status = if code == super::DROPPED {
655                    WriteComplete::Dropped(value)
656                } else {
657                    WriteComplete::Cancelled(value)
658                };
659                Ok((status, writer))
660            }
661
662            // This write has completed.
663            //
664            // Here we need to clean up our allocations. The `ptr` exclusively
665            // owns all of the value being sent and we notably need to cleanup
666            // the transitive list allocations present in this pointer. Use
667            // `dealloc_lists` for that (effectively a post-return lookalike).
668            //
669            // Afterwards the `cleanup` itself is naturally dropped and cleaned
670            // up.
671            super::COMPLETED => {
672                // SAFETY: we're the ones managing `ptr` so we know it's safe to
673                // pass here.
674                unsafe {
675                    writer.ops.dealloc_lists(ptr);
676                }
677                Ok((WriteComplete::Written, writer))
678            }
679
680            other => unreachable!("unexpected code {other:?}"),
681        }
682    }
683
684    fn in_progress_waitable(&mut self, (writer, _): &Self::InProgress) -> u32 {
685        writer.handle
686    }
687
688    fn in_progress_cancel(&mut self, (writer, _): &mut Self::InProgress) -> u32 {
689        // SAFETY: we're managing `writer` and all the various operational bits,
690        // so this relies on `WaitableOperation` being safe.
691        let code = unsafe { writer.ops.cancel_write(writer.handle) };
692        rtdebug!("future.cancel-write({}) = {code:#x}", writer.handle);
693        code
694    }
695
696    fn result_into_cancel(&mut self, (result, writer): Self::Result) -> Self::Cancel {
697        match result {
698            // The value was actually sent, meaning we can't yield back the
699            // future nor the value.
700            WriteComplete::Written => RawFutureWriteCancel::AlreadySent,
701
702            // The value was not sent because the other end either hung up or we
703            // successfully cancelled. In both cases return back the value here
704            // with the writer.
705            WriteComplete::Dropped(val) => RawFutureWriteCancel::Dropped(val),
706            WriteComplete::Cancelled(val) => RawFutureWriteCancel::Cancelled(val, writer),
707        }
708    }
709}
710
711impl<O: FutureOps> Future for RawFutureWrite<O> {
712    type Output = Result<(), FutureWriteError<O::Payload>>;
713
714    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
715        self.pin_project()
716            .poll_complete(cx)
717            .map(|(result, _writer)| match result {
718                WriteComplete::Written => Ok(()),
719                WriteComplete::Dropped(value) | WriteComplete::Cancelled(value) => {
720                    Err(FutureWriteError { value })
721                }
722            })
723    }
724}
725
726impl<O: FutureOps> RawFutureWrite<O> {
727    fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureWriteOp<O>>> {
728        // SAFETY: we've chosen that when `Self` is pinned that it translates to
729        // always pinning the inner field, so that's codified here.
730        unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().op) }
731    }
732
733    /// Same as [`FutureWrite::cancel`], but returns a [`RawFutureWriteCancel`]
734    /// instead.
735    pub fn cancel(self: Pin<&mut Self>) -> RawFutureWriteCancel<O> {
736        self.pin_project().cancel()
737    }
738}
739
740/// Error type in the result of [`FutureWrite`], or the error type that is a result of
741/// a failure to write a future.
742pub struct FutureWriteError<T> {
743    /// The value that could not be sent.
744    pub value: T,
745}
746
747impl<T> fmt::Debug for FutureWriteError<T> {
748    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
749        f.debug_struct("FutureWriteError").finish_non_exhaustive()
750    }
751}
752
753impl<T> fmt::Display for FutureWriteError<T> {
754    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
755        "read end dropped".fmt(f)
756    }
757}
758
759impl<T> std::error::Error for FutureWriteError<T> {}
760
761/// Result of [`FutureWrite::cancel`].
762#[derive(Debug)]
763pub enum RawFutureWriteCancel<O: FutureOps> {
764    /// The cancel request raced with the receipt of the sent value, and the
765    /// value was actually sent. Neither the value nor the writer are made
766    /// available here as both are gone.
767    AlreadySent,
768
769    /// The other end was dropped before cancellation happened.
770    ///
771    /// In this case the original value is returned back to the caller but the
772    /// writer itself is not longer accessible as it's no longer usable.
773    Dropped(O::Payload),
774
775    /// The pending write was successfully cancelled and the value being written
776    /// is returned along with the writer to resume again in the future if
777    /// necessary.
778    Cancelled(O::Payload, RawFutureWriter<O>),
779}
780
781/// Represents the readable end of a Component Model `future<T>`.
782pub type FutureReader<T> = RawFutureReader<&'static FutureVtable<T>>;
783
784/// Represents the readable end of a Component Model `future<T>`.
785pub struct RawFutureReader<O: FutureOps> {
786    handle: AtomicU32,
787    ops: O,
788}
789
790impl<O: FutureOps> fmt::Debug for RawFutureReader<O> {
791    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
792        f.debug_struct("RawFutureReader")
793            .field("handle", &self.handle)
794            .finish()
795    }
796}
797
798impl<O: FutureOps> RawFutureReader<O> {
799    /// Raw constructor for a future reader.
800    ///
801    /// Takes ownership of the `handle` provided.
802    ///
803    /// # Safety
804    ///
805    /// The `ops` specified must be both valid and well-typed for `handle`.
806    pub unsafe fn new(handle: u32, ops: O) -> Self {
807        Self {
808            handle: AtomicU32::new(handle),
809            ops,
810        }
811    }
812
813    #[doc(hidden)]
814    pub fn take_handle(&self) -> u32 {
815        let ret = self.opt_handle().unwrap();
816        self.handle.store(u32::MAX, Relaxed);
817        ret
818    }
819
820    fn handle(&self) -> u32 {
821        self.opt_handle().unwrap()
822    }
823
824    fn opt_handle(&self) -> Option<u32> {
825        match self.handle.load(Relaxed) {
826            u32::MAX => None,
827            other => Some(other),
828        }
829    }
830}
831
832impl<O: FutureOps> IntoFuture for RawFutureReader<O> {
833    type Output = O::Payload;
834    type IntoFuture = RawFutureRead<O>;
835
836    /// Convert this object into a `Future` which will resolve when a value is
837    /// written to the writable end of this `future`.
838    fn into_future(self) -> Self::IntoFuture {
839        RawFutureRead {
840            op: WaitableOperation::new(FutureReadOp(marker::PhantomData), self),
841        }
842    }
843}
844
845impl<O: FutureOps> Drop for RawFutureReader<O> {
846    fn drop(&mut self) {
847        let Some(handle) = self.opt_handle() else {
848            return;
849        };
850        unsafe {
851            rtdebug!("future.drop-readable({handle})");
852            self.ops.drop_readable(handle);
853        }
854    }
855}
856
857/// Represents a read operation which may be cancelled prior to completion.
858///
859/// This represents a read operation on a [`FutureReader`] and is created via
860/// `IntoFuture`.
861pub type FutureRead<T> = RawFutureRead<&'static FutureVtable<T>>;
862
863/// Represents a read operation which may be cancelled prior to completion.
864///
865/// This represents a read operation on a [`FutureReader`] and is created via
866/// `IntoFuture`.
867pub struct RawFutureRead<O: FutureOps> {
868    op: WaitableOperation<FutureReadOp<O>>,
869}
870
871struct FutureReadOp<O>(marker::PhantomData<O>);
872
873enum ReadComplete<T> {
874    Value(T),
875    Cancelled,
876}
877
878unsafe impl<O: FutureOps> WaitableOp for FutureReadOp<O> {
879    type Start = RawFutureReader<O>;
880    type InProgress = (RawFutureReader<O>, Option<Cleanup>);
881    type Result = (ReadComplete<O::Payload>, RawFutureReader<O>);
882    type Cancel = Result<O::Payload, RawFutureReader<O>>;
883
884    fn start(&mut self, mut reader: Self::Start) -> (u32, Self::InProgress) {
885        let (ptr, cleanup) = Cleanup::new(reader.ops.elem_layout());
886        // SAFETY: `ptr` is allocated with `vtable.layout` and should be
887        // safe to use here. Its lifetime for the async operation is hinged on
888        // `WaitableOperation` being safe.
889        let code = unsafe { reader.ops.start_read(reader.handle(), ptr) };
890        rtdebug!("future.read({}, {ptr:?}) = {code:#x}", reader.handle());
891        (code, (reader, cleanup))
892    }
893
894    fn start_cancelled(&mut self, state: Self::Start) -> Self::Cancel {
895        Err(state)
896    }
897
898    fn in_progress_update(
899        &mut self,
900        (mut reader, cleanup): Self::InProgress,
901        code: u32,
902    ) -> Result<Self::Result, Self::InProgress> {
903        match ReturnCode::decode(code) {
904            ReturnCode::Blocked => Err((reader, cleanup)),
905
906            // Let `cleanup` fall out of scope to clean up its allocation here,
907            // and otherwise tahe reader is plumbed through to possibly restart
908            // the read in the future.
909            ReturnCode::Cancelled(0) => Ok((ReadComplete::Cancelled, reader)),
910
911            // The read has completed, so lift the value from the stored memory and
912            // `cleanup` naturally falls out of scope after transferring ownership of
913            // everything to the returned `value`.
914            ReturnCode::Completed(0) => {
915                let ptr = cleanup
916                    .as_ref()
917                    .map(|c| c.ptr.as_ptr())
918                    .unwrap_or(ptr::null_mut());
919
920                // SAFETY: we're the ones managing `ptr` so we know it's safe to
921                // pass here.
922                let value = unsafe { reader.ops.lift(ptr) };
923                Ok((ReadComplete::Value(value), reader))
924            }
925
926            other => panic!("unexpected code {other:?}"),
927        }
928    }
929
930    fn in_progress_waitable(&mut self, (reader, _): &Self::InProgress) -> u32 {
931        reader.handle()
932    }
933
934    fn in_progress_cancel(&mut self, (reader, _): &mut Self::InProgress) -> u32 {
935        // SAFETY: we're managing `reader` and all the various operational bits,
936        // so this relies on `WaitableOperation` being safe.
937        let code = unsafe { reader.ops.cancel_read(reader.handle()) };
938        rtdebug!("future.cancel-read({}) = {code:#x}", reader.handle());
939        code
940    }
941
942    fn result_into_cancel(&mut self, (value, reader): Self::Result) -> Self::Cancel {
943        match value {
944            // The value was actually read, so thread that through here.
945            ReadComplete::Value(value) => Ok(value),
946
947            // The read was successfully cancelled, so thread through the
948            // `reader` to possibly restart later on.
949            ReadComplete::Cancelled => Err(reader),
950        }
951    }
952}
953
954impl<O: FutureOps> Future for RawFutureRead<O> {
955    type Output = O::Payload;
956
957    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
958        self.pin_project()
959            .poll_complete(cx)
960            .map(|(result, _reader)| match result {
961                ReadComplete::Value(val) => val,
962                // This is only possible if, after calling `FutureRead::cancel`,
963                // the future is polled again. The `cancel` method is documented
964                // as "don't do that" so this is left to panic.
965                ReadComplete::Cancelled => panic!("cannot poll after cancelling"),
966            })
967    }
968}
969
970impl<O: FutureOps> RawFutureRead<O> {
971    fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureReadOp<O>>> {
972        // SAFETY: we've chosen that when `Self` is pinned that it translates to
973        // always pinning the inner field, so that's codified here.
974        unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().op) }
975    }
976
977    /// Cancel this read if it hasn't already completed.
978    ///
979    /// Return values include:
980    ///
981    /// * `Ok(value)` - future completed before this cancellation request
982    ///   was received.
983    /// * `Err(reader)` - read operation was cancelled and it can be retried in
984    ///   the future if desired.
985    ///
986    /// # Panics
987    ///
988    /// Panics if the operation has already been completed via `Future::poll`,
989    /// or if this method is called twice. Additionally if this method completes
990    /// then calling `poll` again on `self` will panic.
991    pub fn cancel(self: Pin<&mut Self>) -> Result<O::Payload, RawFutureReader<O>> {
992        self.pin_project().cancel()
993    }
994}