Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

wit-bindgen

Package Overview
Dependencies
Maintainers
0
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

wit-bindgen - npm Package Compare versions

Comparing version
0.47.0
to
0.48.0
+1
-1
.cargo_vcs_info.json
{
"git": {
"sha1": "65ee50585900d9de30d48e99d03ff3e3f97ae186"
"sha1": "875e8632bb4b45d6b6ea1e3a72c66354c86d5d29"
},
"path_in_vcs": "crates/guest-rust"
}

@@ -318,5 +318,5 @@ # This file is automatically @generated by Cargo.

name = "wasm-encoder"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06d642d8c5ecc083aafe9ceb32809276a304547a3a6eeecceb5d8152598bc71f"
checksum = "e01164c9dda68301e34fdae536c23ed6fe90ce6d97213ccc171eebbd3d02d6b8"
dependencies = [

@@ -329,5 +329,5 @@ "leb128fmt",

name = "wasm-metadata"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee093e1e1ccffa005b9b778f7a10ccfd58e25a20eccad294a1a93168d076befb"
checksum = "876fe286f2fa416386deedebe8407e6f19e0b5aeaef3d03161e77a15fa80f167"
dependencies = [

@@ -342,5 +342,5 @@ "anyhow",

name = "wasmparser"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b722dcf61e0ea47440b53ff83ccb5df8efec57a69d150e4f24882e4eba7e24a4"
checksum = "46d90019b1afd4b808c263e428de644f3003691f243387d30d673211ee0cb8e8"
dependencies = [

@@ -355,3 +355,3 @@ "bitflags",

name = "wit-bindgen"
version = "0.47.0"
version = "0.48.0"
dependencies = [

@@ -367,5 +367,5 @@ "bitflags",

name = "wit-bindgen-core"
version = "0.47.0"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf62e62178415a705bda25dc01c54ed65c0f956e4efd00ca89447a9a84f4881"
checksum = "a64f7435c8448e456bc6e8f14e27ee4f65926cbdfe72b7bf95badeae2501bacf"
dependencies = [

@@ -379,5 +379,5 @@ "anyhow",

name = "wit-bindgen-rust"
version = "0.47.0"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6d585319871ca18805056f69ddec7541770fc855820f9944029cb2b75ea108f"
checksum = "612651c001e0de8bfb7138af5551f80461f25caa627b64d7014a80914cf4f407"
dependencies = [

@@ -396,5 +396,5 @@ "anyhow",

name = "wit-bindgen-rust-macro"
version = "0.47.0"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bde589435d322e88b8f708f70e313f60dfb7975ac4e7c623fef6f1e5685d90e8"
checksum = "16c64812d84284d45ce7d7371dc9eb0bcda2f0f747128bd1b4dae1e08217bad3"
dependencies = [

@@ -412,5 +412,5 @@ "anyhow",

name = "wit-component"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dc5474b078addc5fe8a72736de8da3acfb3ff324c2491133f8b59594afa1a20"
checksum = "1fd0c57df25e7ee612d946d3b7646c1ddb2310f8280aa2c17e543b66e0812241"
dependencies = [

@@ -432,5 +432,5 @@ "anyhow",

name = "wit-parser"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9875ea3fa272f57cc1fc50f225a7b94021a7878c484b33792bccad0d93223439"
checksum = "09ef1c6ad67f35c831abd4039c02894de97034100899614d1c44e2268ad01c91"
dependencies = [

@@ -437,0 +437,0 @@ "anyhow",

@@ -16,3 +16,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO

name = "wit-bindgen"
version = "0.47.0"
version = "0.48.0"
authors = ["Alex Crichton <alex@alexcrichton.com>"]

@@ -39,5 +39,4 @@ build = "build.rs"

async = [
"macros",
"std",
"wit-bindgen-rust-macro/async",
"wit-bindgen-rust-macro?/async",
]

@@ -87,3 +86,3 @@ async-spawn = [

[dependencies.wit-bindgen-rust-macro]
version = "0.47.0"
version = "0.48.0"
optional = true

@@ -121,2 +121,3 @@ //! Runtime support for `future<T>` in the component model.

use std::marker;
use std::mem::{self, ManuallyDrop};
use std::pin::Pin;

@@ -128,2 +129,35 @@ use std::ptr;

/// Helper trait which encapsulates the various operations which can happen
/// with a future.
pub trait FutureOps {
/// The Rust type that's sent or received on this future.
type Payload;
/// The `future.new` intrinsic.
fn new(&mut self) -> u64;
/// The canonical ABI layout of the type that this future is
/// sending/receiving.
fn elem_layout(&mut self) -> Layout;
/// Converts a Rust type to its canonical ABI representation.
unsafe fn lower(&mut self, payload: Self::Payload, dst: *mut u8);
/// Used to deallocate any Rust-owned lists in the canonical ABI
/// representation for when a value is successfully sent but needs to be
/// cleaned up.
unsafe fn dealloc_lists(&mut self, dst: *mut u8);
/// Converts from the canonical ABI representation to a Rust value.
unsafe fn lift(&mut self, dst: *mut u8) -> Self::Payload;
/// The `future.write` intrinsic
unsafe fn start_write(&mut self, future: u32, val: *const u8) -> u32;
/// The `future.read` intrinsic
unsafe fn start_read(&mut self, future: u32, val: *mut u8) -> u32;
/// The `future.cancel-read` intrinsic
unsafe fn cancel_read(&mut self, future: u32) -> u32;
/// The `future.cancel-write` intrinsic
unsafe fn cancel_write(&mut self, future: u32) -> u32;
/// The `future.drop-readable` intrinsic
unsafe fn drop_readable(&mut self, future: u32);
/// The `future.drop-writable` intrinsic
unsafe fn drop_writable(&mut self, future: u32);
}
/// Function table used for [`FutureWriter`] and [`FutureReader`]

@@ -180,2 +214,40 @@ ///

impl<T> FutureOps for &'static FutureVtable<T> {
type Payload = T;
fn new(&mut self) -> u64 {
unsafe { (self.new)() }
}
fn elem_layout(&mut self) -> Layout {
self.layout
}
unsafe fn lower(&mut self, payload: Self::Payload, dst: *mut u8) {
(self.lower)(payload, dst)
}
unsafe fn dealloc_lists(&mut self, dst: *mut u8) {
(self.dealloc_lists)(dst)
}
unsafe fn lift(&mut self, dst: *mut u8) -> Self::Payload {
(self.lift)(dst)
}
unsafe fn start_write(&mut self, future: u32, val: *const u8) -> u32 {
(self.start_write)(future, val)
}
unsafe fn start_read(&mut self, future: u32, val: *mut u8) -> u32 {
(self.start_read)(future, val)
}
unsafe fn cancel_read(&mut self, future: u32) -> u32 {
(self.cancel_read)(future)
}
unsafe fn cancel_write(&mut self, future: u32) -> u32 {
(self.cancel_write)(future)
}
unsafe fn drop_readable(&mut self, future: u32) {
(self.drop_readable)(future)
}
unsafe fn drop_writable(&mut self, future: u32) {
(self.drop_writable)(future)
}
}
/// Helper function to create a new read/write pair for a component model

@@ -192,4 +264,19 @@ /// future.

) -> (FutureWriter<T>, FutureReader<T>) {
let (tx, rx) = unsafe { raw_future_new(vtable) };
(FutureWriter::new(tx, default), rx)
}
/// Helper function to create a new read/write pair for a component model
/// future.
///
/// # Unsafety
///
/// This function is unsafe as it requires the functions within `vtable` to
/// correctly uphold the contracts of the component model.
pub unsafe fn raw_future_new<O>(mut ops: O) -> (RawFutureWriter<O>, RawFutureReader<O>)
where
O: FutureOps + Clone,
{
unsafe {
let handles = (vtable.new)();
let handles = ops.new();
let reader = handles as u32;

@@ -199,4 +286,4 @@ let writer = (handles >> 32) as u32;

(
FutureWriter::new(writer, default, vtable),
FutureReader::new(reader, vtable),
RawFutureWriter::new(writer, ops.clone()),
RawFutureReader::new(reader, ops),
)

@@ -211,4 +298,3 @@ }

pub struct FutureWriter<T: 'static> {
handle: u32,
vtable: &'static FutureVtable<T>,
raw: ManuallyDrop<RawFutureWriter<&'static FutureVtable<T>>>,

@@ -236,9 +322,7 @@ /// Whether or not a value should be written during `drop`.

/// correctly uphold the contracts of the component model.
#[doc(hidden)]
pub unsafe fn new(handle: u32, default: fn() -> T, vtable: &'static FutureVtable<T>) -> Self {
unsafe fn new(raw: RawFutureWriter<&'static FutureVtable<T>>, default: fn() -> T) -> Self {
Self {
handle,
raw: ManuallyDrop::new(raw),
default,
should_write_default_value: true,
vtable,
}

@@ -274,6 +358,7 @@ }

/// In such a situation the operation can be retried at a future date.
pub fn write(self, value: T) -> FutureWrite<T> {
FutureWrite {
op: WaitableOperation::new(FutureWriteOp(marker::PhantomData), (self, value)),
}
pub fn write(mut self, value: T) -> FutureWrite<T> {
let raw = unsafe { ManuallyDrop::take(&mut self.raw).write(value) };
let default = self.default;
mem::forget(self);
FutureWrite { raw, default }
}

@@ -285,3 +370,3 @@ }

f.debug_struct("FutureWriter")
.field("handle", &self.handle)
.field("handle", &self.raw.handle)
.finish()

@@ -294,26 +379,14 @@ }

// If a value has not yet been written into this writer than that must
// be done so now. Perform a "clone" of `self` ensuring that
// `should_write_default_value` is set to `false` to avoid infinite
// loops by accident. The cloned `FutureWriter` will be responsible for
// performing the `drop-writable` call below once the write has
// completed.
// be done so now. Take the `raw` writer and perform the write via a
// waker that drives the future.
//
// Note, though, that if `should_write_default_value` is `false` then a
// write has already happened and we can go ahead and just synchronously
// drop this writer as we would any other handle.
// If `should_write_default_value` is `false` then a write has already
// happened and we can go ahead and just synchronously drop this writer
// as we would any other handle.
if self.should_write_default_value {
let clone = FutureWriter {
handle: self.handle,
default: self.default,
should_write_default_value: false,
vtable: self.vtable,
};
let value = (clone.default)();
let write = clone.write(value);
Arc::new(DeferredWrite::new(write)).wake();
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
let value = (self.default)();
raw.write_and_forget(value);
} else {
unsafe {
rtdebug!("future.drop-writable({})", self.handle);
(self.vtable.drop_writable)(self.handle);
}
unsafe { ManuallyDrop::drop(&mut self.raw) }
}

@@ -323,27 +396,69 @@ }

/// Helper structure which behaves both as a future of sorts and an executor of
/// sorts.
/// Represents a write operation which may be cancelled prior to completion.
///
/// This type is constructed in `Drop for FutureWriter<T>` to send out a
/// default value when no other has been written. This manages the
/// `FutureWrite` operation happening internally through a `Wake`
/// implementation. That means that this is a sort of cyclical future which,
/// when woken, will complete the write operation.
///
/// The purpose of this is to be a "lightweight" way of "spawn"-ing a future
/// write to happen in the background. Crucially, however, this doesn't require
/// the `async-spawn` feature and instead works with the `wasip3_task` C ABI
/// structures (which spawn doesn't support).
struct DeferredWrite<T: 'static> {
write: Mutex<FutureWrite<T>>,
/// This is returned by [`FutureWriter::write`].
pub struct FutureWrite<T: 'static> {
raw: RawFutureWrite<&'static FutureVtable<T>>,
default: fn() -> T,
}
// TODO
unsafe impl<T> Send for DeferredWrite<T> {}
unsafe impl<T> Sync for DeferredWrite<T> {}
/// Result of [`FutureWrite::cancel`].
#[derive(Debug)]
pub enum FutureWriteCancel<T: 'static> {
/// The cancel request raced with the receipt of the sent value, and the
/// value was actually sent. Neither the value nor the writer are made
/// available here as both are gone.
AlreadySent,
impl<T> DeferredWrite<T> {
fn new(write: FutureWrite<T>) -> DeferredWrite<T> {
DeferredWrite {
write: Mutex::new(write),
/// The other end was dropped before cancellation happened.
///
/// In this case the original value is returned back to the caller but the
/// writer itself is not longer accessible as it's no longer usable.
Dropped(T),
/// The pending write was successfully cancelled and the value being written
/// is returned along with the writer to resume again in the future if
/// necessary.
Cancelled(T, FutureWriter<T>),
}
impl<T: 'static> Future for FutureWrite<T> {
type Output = Result<(), FutureWriteError<T>>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.pin_project().poll(cx)
}
}
impl<T: 'static> FutureWrite<T> {
fn pin_project(self: Pin<&mut Self>) -> Pin<&mut RawFutureWrite<&'static FutureVtable<T>>> {
// SAFETY: we've chosen that when `Self` is pinned that it translates to
// always pinning the inner field, so that's codified here.
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().raw) }
}
/// Cancel this write if it hasn't already completed.
///
/// This method can be used to cancel a write-in-progress and re-acquire
/// the writer and the value being sent. Note that the write operation may
/// succeed racily or the other end may also drop racily, and these
/// outcomes are reflected in the returned value here.
///
/// # Panics
///
/// Panics if the operation has already been completed via `Future::poll`,
/// or if this method is called twice.
pub fn cancel(self: Pin<&mut Self>) -> FutureWriteCancel<T> {
let default = self.default;
match self.pin_project().cancel() {
RawFutureWriteCancel::AlreadySent => FutureWriteCancel::AlreadySent,
RawFutureWriteCancel::Dropped(val) => FutureWriteCancel::Dropped(val),
RawFutureWriteCancel::Cancelled(val, raw) => FutureWriteCancel::Cancelled(
val,
FutureWriter {
raw: ManuallyDrop::new(raw),
default,
should_write_default_value: true,
},
),
}

@@ -353,42 +468,137 @@ }

impl<T> Wake for DeferredWrite<T> {
fn wake(self: Arc<Self>) {
// When a `wake` signal comes in that should happen in two locations:
impl<T: 'static> Drop for FutureWrite<T> {
fn drop(&mut self) {
if self.raw.op.is_done() {
return;
}
// Although the underlying `WaitableOperation` will already
// auto-cancel-on-drop we need to specially handle that here because if
// the cancellation goes through then it means that no value will have
// been written to this future which will cause a trap. By using
// `Self::cancel` it's ensured that if cancellation succeeds a
// `FutureWriter` is created. In `Drop for FutureWriter` that'll handle
// the last-ditch write-default logic.
//
// 1. When `DeferredWrite` is initially constructed.
// 2. When an event comes in indicating that the internal write has
// completed.
//
// The implementation here is the same in both cases. A clone of `self`
// is converted to a `Waker`, and this `Waker` notably owns the
// internal future itself. The internal write operation is then pushed
// forward (e.g. it's issued in (1) or checked up on in (2)).
//
// If `Pending` is returned then `waker` should have been stored away
// within the `wasip3_task` C ABI structure. Otherwise it should not
// have been stored away and `self` should be the sole reference which
// means everything will get cleaned up when this function returns.
let poll = {
let waker = Waker::from(self.clone());
let mut cx = Context::from_waker(&waker);
let mut write = self.write.lock().unwrap();
unsafe { Pin::new_unchecked(&mut *write).poll(&mut cx) }
};
if poll.is_ready() {
assert_eq!(Arc::strong_count(&self), 1);
} else {
assert!(Arc::strong_count(&self) > 1);
// SAFETY: we're in the destructor here so the value `self` is about
// to go away and we can guarantee we're not moving out of it.
let pin = unsafe { Pin::new_unchecked(self) };
pin.cancel();
}
}
/// Raw version of [`FutureWriter`].
pub struct RawFutureWriter<O: FutureOps> {
handle: u32,
ops: O,
}
impl<O: FutureOps> RawFutureWriter<O> {
unsafe fn new(handle: u32, ops: O) -> Self {
Self { handle, ops }
}
/// Same as [`FutureWriter::write`], but the raw version.
pub fn write(self, value: O::Payload) -> RawFutureWrite<O> {
RawFutureWrite {
op: WaitableOperation::new(FutureWriteOp(marker::PhantomData), (self, value)),
}
assert_eq!(Arc::weak_count(&self), 0);
}
/// Writes `value` in the background.
///
/// This does not block and is not cancellable.
pub fn write_and_forget(self, value: O::Payload)
where
O: 'static,
{
return Arc::new(DeferredWrite {
write: Mutex::new(self.write(value)),
})
.wake();
/// Helper structure which behaves both as a future of sorts and an
/// executor of sorts.
///
/// This type is constructed in `Drop for FutureWriter<T>` to send out a
/// default value when no other has been written. This manages the
/// `FutureWrite` operation happening internally through a `Wake`
/// implementation. That means that this is a sort of cyclical future
/// which, when woken, will complete the write operation.
///
/// The purpose of this is to be a "lightweight" way of "spawn"-ing a
/// future write to happen in the background. Crucially, however, this
/// doesn't require the `async-spawn` feature and instead works with the
/// `wasip3_task` C ABI structures (which spawn doesn't support).
struct DeferredWrite<O: FutureOps> {
write: Mutex<RawFutureWrite<O>>,
}
// SAFETY: Needed to satisfy `Waker::from` but otherwise should be ok
// because wasm doesn't have threads anyway right now.
unsafe impl<O: FutureOps> Send for DeferredWrite<O> {}
unsafe impl<O: FutureOps> Sync for DeferredWrite<O> {}
impl<O: FutureOps + 'static> Wake for DeferredWrite<O> {
fn wake(self: Arc<Self>) {
// When a `wake` signal comes in that should happen in two
// locations:
//
// 1. When `DeferredWrite` is initially constructed.
// 2. When an event comes in indicating that the internal write
// has completed.
//
// The implementation here is the same in both cases. A clone of
// `self` is converted to a `Waker`, and this `Waker` notably
// owns the internal future itself. The internal write operation
// is then pushed forward (e.g. it's issued in (1) or checked up
// on in (2)).
//
// If `Pending` is returned then `waker` should have been stored
// away within the `wasip3_task` C ABI structure. Otherwise it
// should not have been stored away and `self` should be the
// sole reference which means everything will get cleaned up
// when this function returns.
let poll = {
let waker = Waker::from(self.clone());
let mut cx = Context::from_waker(&waker);
let mut write = self.write.lock().unwrap();
unsafe { Pin::new_unchecked(&mut *write).poll(&mut cx) }
};
if poll.is_ready() {
assert_eq!(Arc::strong_count(&self), 1);
} else {
assert!(Arc::strong_count(&self) > 1);
}
assert_eq!(Arc::weak_count(&self), 0);
}
}
}
}
impl<O: FutureOps> fmt::Debug for RawFutureWriter<O> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawFutureWriter")
.field("handle", &self.handle)
.finish()
}
}
impl<O: FutureOps> Drop for RawFutureWriter<O> {
fn drop(&mut self) {
unsafe {
rtdebug!("future.drop-writable({})", self.handle);
self.ops.drop_writable(self.handle);
}
}
}
/// Represents a write operation which may be cancelled prior to completion.
///
/// This is returned by [`FutureWriter::write`].
pub struct FutureWrite<T: 'static> {
op: WaitableOperation<FutureWriteOp<T>>,
pub struct RawFutureWrite<O: FutureOps> {
op: WaitableOperation<FutureWriteOp<O>>,
}
struct FutureWriteOp<T>(marker::PhantomData<T>);
struct FutureWriteOp<O>(marker::PhantomData<O>);

@@ -401,12 +611,9 @@ enum WriteComplete<T> {

unsafe impl<T> WaitableOp for FutureWriteOp<T>
where
T: 'static,
{
type Start = (FutureWriter<T>, T);
type InProgress = (FutureWriter<T>, Option<Cleanup>);
type Result = (WriteComplete<T>, FutureWriter<T>);
type Cancel = FutureWriteCancel<T>;
unsafe impl<O: FutureOps> WaitableOp for FutureWriteOp<O> {
type Start = (RawFutureWriter<O>, O::Payload);
type InProgress = (RawFutureWriter<O>, Option<Cleanup>);
type Result = (WriteComplete<O::Payload>, RawFutureWriter<O>);
type Cancel = RawFutureWriteCancel<O>;
fn start(&self, (writer, value): Self::Start) -> (u32, Self::InProgress) {
fn start(&mut self, (mut writer, value): Self::Start) -> (u32, Self::InProgress) {
// TODO: it should be safe to store the lower-destination in

@@ -422,8 +629,8 @@ // `WaitableOperation` using `Pin` memory and such, but that would

// pointer to initialize it.
let (ptr, cleanup) = Cleanup::new(writer.vtable.layout);
// SAFETY: `ptr` is allocated with `vtable.layout` and should be
let (ptr, cleanup) = Cleanup::new(writer.ops.elem_layout());
// SAFETY: `ptr` is allocated with `ops.layout` and should be
// safe to use here.
let code = unsafe {
(writer.vtable.lower)(value, ptr);
(writer.vtable.start_write)(writer.handle, ptr)
writer.ops.lower(value, ptr);
writer.ops.start_write(writer.handle, ptr)
};

@@ -434,8 +641,8 @@ rtdebug!("future.write({}, {ptr:?}) = {code:#x}", writer.handle);

fn start_cancelled(&self, (writer, value): Self::Start) -> Self::Cancel {
FutureWriteCancel::Cancelled(value, writer)
fn start_cancelled(&mut self, (writer, value): Self::Start) -> Self::Cancel {
RawFutureWriteCancel::Cancelled(value, writer)
}
fn in_progress_update(
&self,
&mut self,
(mut writer, cleanup): Self::InProgress,

@@ -461,9 +668,4 @@ code: u32,

// pass here.
let value = unsafe { (writer.vtable.lift)(ptr) };
let value = unsafe { writer.ops.lift(ptr) };
let status = if code == super::DROPPED {
// This writer has been witnessed to be dropped, meaning that
// `writer` is going to get destroyed soon as this return
// value propagates up the stack. There's no need to write
// the default value, so set this to `false`.
writer.should_write_default_value = false;
WriteComplete::Dropped(value)

@@ -486,9 +688,6 @@ } else {

super::COMPLETED => {
// A value was written, so no need to write the default value.
writer.should_write_default_value = false;
// SAFETY: we're the ones managing `ptr` so we know it's safe to
// pass here.
unsafe {
(writer.vtable.dealloc_lists)(ptr);
writer.ops.dealloc_lists(ptr);
}

@@ -502,10 +701,10 @@ Ok((WriteComplete::Written, writer))

fn in_progress_waitable(&self, (writer, _): &Self::InProgress) -> u32 {
fn in_progress_waitable(&mut self, (writer, _): &Self::InProgress) -> u32 {
writer.handle
}
fn in_progress_cancel(&self, (writer, _): &Self::InProgress) -> u32 {
fn in_progress_cancel(&mut self, (writer, _): &mut Self::InProgress) -> u32 {
// SAFETY: we're managing `writer` and all the various operational bits,
// so this relies on `WaitableOperation` being safe.
let code = unsafe { (writer.vtable.cancel_write)(writer.handle) };
let code = unsafe { writer.ops.cancel_write(writer.handle) };
rtdebug!("future.cancel-write({}) = {code:#x}", writer.handle);

@@ -515,7 +714,7 @@ code

fn result_into_cancel(&self, (result, writer): Self::Result) -> Self::Cancel {
fn result_into_cancel(&mut self, (result, writer): Self::Result) -> Self::Cancel {
match result {
// The value was actually sent, meaning we can't yield back the
// future nor the value.
WriteComplete::Written => FutureWriteCancel::AlreadySent,
WriteComplete::Written => RawFutureWriteCancel::AlreadySent,

@@ -525,4 +724,4 @@ // The value was not sent because the other end either hung up or we

// with the writer.
WriteComplete::Dropped(val) => FutureWriteCancel::Dropped(val),
WriteComplete::Cancelled(val) => FutureWriteCancel::Cancelled(val, writer),
WriteComplete::Dropped(val) => RawFutureWriteCancel::Dropped(val),
WriteComplete::Cancelled(val) => RawFutureWriteCancel::Cancelled(val, writer),
}

@@ -532,4 +731,4 @@ }

impl<T: 'static> Future for FutureWrite<T> {
type Output = Result<(), FutureWriteError<T>>;
impl<O: FutureOps> Future for RawFutureWrite<O> {
type Output = Result<(), FutureWriteError<O::Payload>>;

@@ -548,4 +747,4 @@ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {

impl<T: 'static> FutureWrite<T> {
fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureWriteOp<T>>> {
impl<O: FutureOps> RawFutureWrite<O> {
fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureWriteOp<O>>> {
// SAFETY: we've chosen that when `Self` is pinned that it translates to

@@ -556,14 +755,5 @@ // always pinning the inner field, so that's codified here.

/// Cancel this write if it hasn't already completed.
///
/// This method can be used to cancel a write-in-progress and re-acquire
/// the writer and the value being sent. Note that the write operation may
/// succeed racily or the other end may also drop racily, and these
/// outcomes are reflected in the returned value here.
///
/// # Panics
///
/// Panics if the operation has already been completed via `Future::poll`,
/// or if this method is called twice.
pub fn cancel(self: Pin<&mut Self>) -> FutureWriteCancel<T> {
/// Same as [`FutureWrite::cancel`], but returns a [`RawFutureWriteCancel`]
/// instead.
pub fn cancel(self: Pin<&mut Self>) -> RawFutureWriteCancel<O> {
self.pin_project().cancel()

@@ -596,3 +786,3 @@ }

#[derive(Debug)]
pub enum FutureWriteCancel<T: 'static> {
pub enum RawFutureWriteCancel<O: FutureOps> {
/// The cancel request raced with the receipt of the sent value, and the

@@ -607,3 +797,3 @@ /// value was actually sent. Neither the value nor the writer are made

/// writer itself is not longer accessible as it's no longer usable.
Dropped(T),
Dropped(O::Payload),

@@ -613,14 +803,17 @@ /// The pending write was successfully cancelled and the value being written

/// necessary.
Cancelled(T, FutureWriter<T>),
Cancelled(O::Payload, RawFutureWriter<O>),
}
/// Represents the readable end of a Component Model `future<T>`.
pub struct FutureReader<T: 'static> {
pub type FutureReader<T> = RawFutureReader<&'static FutureVtable<T>>;
/// Represents the readable end of a Component Model `future<T>`.
pub struct RawFutureReader<O: FutureOps> {
handle: AtomicU32,
vtable: &'static FutureVtable<T>,
ops: O,
}
impl<T> fmt::Debug for FutureReader<T> {
impl<O: FutureOps> fmt::Debug for RawFutureReader<O> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FutureReader")
f.debug_struct("RawFutureReader")
.field("handle", &self.handle)

@@ -631,8 +824,14 @@ .finish()

impl<T> FutureReader<T> {
#[doc(hidden)]
pub fn new(handle: u32, vtable: &'static FutureVtable<T>) -> Self {
impl<O: FutureOps> RawFutureReader<O> {
/// Raw constructor for a future reader.
///
/// Takes ownership of the `handle` provided.
///
/// # Safety
///
/// The `ops` specified must be both valid and well-typed for `handle`.
pub unsafe fn new(handle: u32, ops: O) -> Self {
Self {
handle: AtomicU32::new(handle),
vtable,
ops,
}

@@ -660,5 +859,5 @@ }

impl<T> IntoFuture for FutureReader<T> {
type Output = T;
type IntoFuture = FutureRead<T>;
impl<O: FutureOps> IntoFuture for RawFutureReader<O> {
type Output = O::Payload;
type IntoFuture = RawFutureRead<O>;

@@ -668,3 +867,3 @@ /// Convert this object into a `Future` which will resolve when a value is

fn into_future(self) -> Self::IntoFuture {
FutureRead {
RawFutureRead {
op: WaitableOperation::new(FutureReadOp(marker::PhantomData), self),

@@ -675,3 +874,3 @@ }

impl<T> Drop for FutureReader<T> {
impl<O: FutureOps> Drop for RawFutureReader<O> {
fn drop(&mut self) {

@@ -683,3 +882,3 @@ let Some(handle) = self.opt_handle() else {

rtdebug!("future.drop-readable({handle})");
(self.vtable.drop_readable)(handle);
self.ops.drop_readable(handle);
}

@@ -693,7 +892,13 @@ }

/// `IntoFuture`.
pub struct FutureRead<T: 'static> {
op: WaitableOperation<FutureReadOp<T>>,
pub type FutureRead<T> = RawFutureRead<&'static FutureVtable<T>>;
/// Represents a read operation which may be cancelled prior to completion.
///
/// This represents a read operation on a [`FutureReader`] and is created via
/// `IntoFuture`.
pub struct RawFutureRead<O: FutureOps> {
op: WaitableOperation<FutureReadOp<O>>,
}
struct FutureReadOp<T>(marker::PhantomData<T>);
struct FutureReadOp<O>(marker::PhantomData<O>);

@@ -705,17 +910,14 @@ enum ReadComplete<T> {

unsafe impl<T> WaitableOp for FutureReadOp<T>
where
T: 'static,
{
type Start = FutureReader<T>;
type InProgress = (FutureReader<T>, Option<Cleanup>);
type Result = (ReadComplete<T>, FutureReader<T>);
type Cancel = Result<T, FutureReader<T>>;
unsafe impl<O: FutureOps> WaitableOp for FutureReadOp<O> {
type Start = RawFutureReader<O>;
type InProgress = (RawFutureReader<O>, Option<Cleanup>);
type Result = (ReadComplete<O::Payload>, RawFutureReader<O>);
type Cancel = Result<O::Payload, RawFutureReader<O>>;
fn start(&self, reader: Self::Start) -> (u32, Self::InProgress) {
let (ptr, cleanup) = Cleanup::new(reader.vtable.layout);
fn start(&mut self, mut reader: Self::Start) -> (u32, Self::InProgress) {
let (ptr, cleanup) = Cleanup::new(reader.ops.elem_layout());
// SAFETY: `ptr` is allocated with `vtable.layout` and should be
// safe to use here. Its lifetime for the async operation is hinged on
// `WaitableOperation` being safe.
let code = unsafe { (reader.vtable.start_read)(reader.handle(), ptr) };
let code = unsafe { reader.ops.start_read(reader.handle(), ptr) };
rtdebug!("future.read({}, {ptr:?}) = {code:#x}", reader.handle());

@@ -725,3 +927,3 @@ (code, (reader, cleanup))

fn start_cancelled(&self, state: Self::Start) -> Self::Cancel {
fn start_cancelled(&mut self, state: Self::Start) -> Self::Cancel {
Err(state)

@@ -731,4 +933,4 @@ }

fn in_progress_update(
&self,
(reader, cleanup): Self::InProgress,
&mut self,
(mut reader, cleanup): Self::InProgress,
code: u32,

@@ -755,3 +957,3 @@ ) -> Result<Self::Result, Self::InProgress> {

// pass here.
let value = unsafe { (reader.vtable.lift)(ptr) };
let value = unsafe { reader.ops.lift(ptr) };
Ok((ReadComplete::Value(value), reader))

@@ -764,10 +966,10 @@ }

fn in_progress_waitable(&self, (reader, _): &Self::InProgress) -> u32 {
fn in_progress_waitable(&mut self, (reader, _): &Self::InProgress) -> u32 {
reader.handle()
}
fn in_progress_cancel(&self, (reader, _): &Self::InProgress) -> u32 {
fn in_progress_cancel(&mut self, (reader, _): &mut Self::InProgress) -> u32 {
// SAFETY: we're managing `reader` and all the various operational bits,
// so this relies on `WaitableOperation` being safe.
let code = unsafe { (reader.vtable.cancel_read)(reader.handle()) };
let code = unsafe { reader.ops.cancel_read(reader.handle()) };
rtdebug!("future.cancel-read({}) = {code:#x}", reader.handle());

@@ -777,3 +979,3 @@ code

fn result_into_cancel(&self, (value, reader): Self::Result) -> Self::Cancel {
fn result_into_cancel(&mut self, (value, reader): Self::Result) -> Self::Cancel {
match value {

@@ -790,4 +992,4 @@ // The value was actually read, so thread that through here.

impl<T: 'static> Future for FutureRead<T> {
type Output = T;
impl<O: FutureOps> Future for RawFutureRead<O> {
type Output = O::Payload;

@@ -807,4 +1009,4 @@ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {

impl<T> FutureRead<T> {
fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureReadOp<T>>> {
impl<O: FutureOps> RawFutureRead<O> {
fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureReadOp<O>>> {
// SAFETY: we've chosen that when `Self` is pinned that it translates to

@@ -829,5 +1031,5 @@ // always pinning the inner field, so that's codified here.

/// then calling `poll` again on `self` will panic.
pub fn cancel(self: Pin<&mut Self>) -> Result<T, FutureReader<T>> {
pub fn cancel(self: Pin<&mut Self>) -> Result<O::Payload, RawFutureReader<O>> {
self.pin_project().cancel()
}
}

@@ -246,3 +246,3 @@ //! For a high-level overview of how this module is implemented see the

fn start(&self, (writer, buf): Self::Start) -> (u32, Self::InProgress) {
fn start(&mut self, (writer, buf): Self::Start) -> (u32, Self::InProgress) {
if writer.done {

@@ -263,3 +263,3 @@ return (DROPPED, (writer, buf));

fn start_cancelled(&self, (_writer, buf): Self::Start) -> Self::Cancel {
fn start_cancelled(&mut self, (_writer, buf): Self::Start) -> Self::Cancel {
(StreamResult::Cancelled, buf)

@@ -269,3 +269,3 @@ }

fn in_progress_update(
&self,
&mut self,
(writer, mut buf): Self::InProgress,

@@ -291,7 +291,7 @@ code: u32,

fn in_progress_waitable(&self, (writer, _): &Self::InProgress) -> u32 {
fn in_progress_waitable(&mut self, (writer, _): &Self::InProgress) -> u32 {
writer.handle
}
fn in_progress_cancel(&self, (writer, _): &Self::InProgress) -> u32 {
fn in_progress_cancel(&mut self, (writer, _): &mut Self::InProgress) -> u32 {
// SAFETY: we're managing `writer` and all the various operational bits,

@@ -304,3 +304,3 @@ // so this relies on `WaitableOperation` being safe.

fn result_into_cancel(&self, result: Self::Result) -> Self::Cancel {
fn result_into_cancel(&mut self, result: Self::Result) -> Self::Cancel {
result

@@ -468,3 +468,3 @@ }

fn start(&self, (reader, mut buf): Self::Start) -> (u32, Self::InProgress) {
fn start(&mut self, (reader, mut buf): Self::Start) -> (u32, Self::InProgress) {
if reader.done {

@@ -502,3 +502,3 @@ return (DROPPED, (reader, buf, None));

fn start_cancelled(&self, (_, buf): Self::Start) -> Self::Cancel {
fn start_cancelled(&mut self, (_, buf): Self::Start) -> Self::Cancel {
(StreamResult::Cancelled, buf)

@@ -508,3 +508,3 @@ }

fn in_progress_update(
&self,
&mut self,
(reader, mut buf, cleanup): Self::InProgress,

@@ -566,7 +566,7 @@ code: u32,

fn in_progress_waitable(&self, (reader, ..): &Self::InProgress) -> u32 {
fn in_progress_waitable(&mut self, (reader, ..): &Self::InProgress) -> u32 {
reader.handle()
}
fn in_progress_cancel(&self, (reader, ..): &Self::InProgress) -> u32 {
fn in_progress_cancel(&mut self, (reader, ..): &mut Self::InProgress) -> u32 {
// SAFETY: we're managing `reader` and all the various operational bits,

@@ -579,3 +579,3 @@ // so this relies on `WaitableOperation` being safe.

fn result_into_cancel(&self, result: Self::Result) -> Self::Cancel {
fn result_into_cancel(&mut self, result: Self::Result) -> Self::Cancel {
result

@@ -582,0 +582,0 @@ }

@@ -45,10 +45,10 @@ //! Bindings used to manage subtasks, or invocations of imported functions.

/// parameters coming first.
fn abi_layout(&self) -> Layout;
fn abi_layout(&mut self) -> Layout;
/// The offset, in bytes, from the start of `ABI_LAYOUT` to where the
/// results will be stored.
fn results_offset(&self) -> usize;
fn results_offset(&mut self) -> usize;
/// The raw function import using `[async-lower]` and the canonical ABI.
unsafe fn call_import(&self, params: Self::ParamsLower, results: *mut u8) -> u32;
unsafe fn call_import(&mut self, params: Self::ParamsLower, results: *mut u8) -> u32;

@@ -64,18 +64,18 @@ /// Bindings-generated version of lowering `params`.

/// ABI).
unsafe fn params_lower(&self, params: Self::Params, dst: *mut u8) -> Self::ParamsLower;
unsafe fn params_lower(&mut self, params: Self::Params, dst: *mut u8) -> Self::ParamsLower;
/// Bindings-generated version of deallocating any lists stored within
/// `lower`.
unsafe fn params_dealloc_lists(&self, lower: Self::ParamsLower);
unsafe fn params_dealloc_lists(&mut self, lower: Self::ParamsLower);
/// Bindings-generated version of deallocating not only owned lists within
/// `lower` but also deallocating any owned resources.
unsafe fn params_dealloc_lists_and_own(&self, lower: Self::ParamsLower);
unsafe fn params_dealloc_lists_and_own(&mut self, lower: Self::ParamsLower);
/// Bindings-generated version of lifting the results stored at `src`.
unsafe fn results_lift(&self, src: *mut u8) -> Self::Results;
unsafe fn results_lift(&mut self, src: *mut u8) -> Self::Results;
/// Helper function to actually perform this asynchronous call with
/// `params`.
fn call(&self, params: Self::Params) -> impl Future<Output = Self::Results>
fn call(&mut self, params: Self::Params) -> impl Future<Output = Self::Results>
where

@@ -98,3 +98,3 @@ Self: Sized,

struct SubtaskOps<'a, T>(&'a T);
struct SubtaskOps<'a, T>(&'a mut T);

@@ -111,3 +111,3 @@ struct Start<T: Subtask> {

fn start(&self, state: Self::Start) -> (u32, Self::InProgress) {
fn start(&mut self, state: Self::Start) -> (u32, Self::InProgress) {
unsafe {

@@ -135,3 +135,3 @@ let (ptr_params, cleanup) = Cleanup::new(self.0.abi_layout());

fn start_cancelled(&self, _state: Self::Start) -> Self::Cancel {
fn start_cancelled(&mut self, _state: Self::Start) -> Self::Cancel {
Err(())

@@ -141,3 +141,3 @@ }

fn in_progress_update(
&self,
&mut self,
mut state: Self::InProgress,

@@ -173,3 +173,4 @@ code: u32,

// itself.
unsafe { Ok(Ok(self.0.results_lift(state.ptr_results(self.0)))) }
let ptr = state.ptr_results(self.0);
unsafe { Ok(Ok(self.0.results_lift(ptr))) }
}

@@ -219,3 +220,3 @@

fn in_progress_waitable(&self, state: &Self::InProgress) -> u32 {
fn in_progress_waitable(&mut self, state: &Self::InProgress) -> u32 {
// This shouldn't get called in the one case this isn't present: when

@@ -227,7 +228,7 @@ // `STATUS_RETURNED` is returned and no waitable is created. That's the

fn in_progress_cancel(&self, state: &Self::InProgress) -> u32 {
fn in_progress_cancel(&mut self, state: &mut Self::InProgress) -> u32 {
unsafe { cancel(self.in_progress_waitable(state)) }
}
fn result_into_cancel(&self, result: Self::Result) -> Self::Cancel {
fn result_into_cancel(&mut self, result: Self::Result) -> Self::Cancel {
result

@@ -259,3 +260,3 @@ }

impl<T: Subtask> InProgress<T> {
fn flag_started(&mut self, op: &T) {
fn flag_started(&mut self, op: &mut T) {
assert!(!self.started);

@@ -272,3 +273,3 @@ self.started = true;

fn ptr_results(&self, op: &T) -> *mut u8 {
fn ptr_results(&mut self, op: &mut T) -> *mut u8 {
// SAFETY: the `T` trait has unsafely promised us that the offset is

@@ -275,0 +276,0 @@ // in-bounds of the allocation layout.

@@ -87,3 +87,3 @@ //! Generic support for "any waitable" and performing asynchronous operations on

/// along with the `InProgress` state.
fn start(&self, state: Self::Start) -> (u32, Self::InProgress);
fn start(&mut self, state: Self::Start) -> (u32, Self::InProgress);

@@ -99,3 +99,3 @@ /// Optionally complete the async operation.

fn in_progress_update(
&self,
&mut self,
state: Self::InProgress,

@@ -107,7 +107,7 @@ code: u32,

/// operation is cancelled before it's started.
fn start_cancelled(&self, state: Self::Start) -> Self::Cancel;
fn start_cancelled(&mut self, state: Self::Start) -> Self::Cancel;
/// Acquires the component-model `waitable` index that the `InProgress`
/// state is waiting on.
fn in_progress_waitable(&self, state: &Self::InProgress) -> u32;
fn in_progress_waitable(&mut self, state: &Self::InProgress) -> u32;

@@ -123,3 +123,3 @@ /// Initiates a request for cancellation of this operation. Returns the

/// component model ABI, for example.
fn in_progress_cancel(&self, state: &Self::InProgress) -> u32;
fn in_progress_cancel(&mut self, state: &mut Self::InProgress) -> u32;

@@ -129,3 +129,3 @@ /// Converts a "completion result" into a "cancel result". This is necessary

/// first acquired and then transitioned to a cancel request.
fn result_into_cancel(&self, result: Self::Result) -> Self::Cancel;
fn result_into_cancel(&mut self, result: Self::Result) -> Self::Cancel;
}

@@ -159,3 +159,3 @@

) -> (
&S,
&mut S,
&mut WaitableOperationState<S>,

@@ -172,3 +172,3 @@ Pin<&mut CompletionStatus>,

(
&me.op,
&mut me.op,
&mut me.state,

@@ -451,2 +451,7 @@ Pin::new_unchecked(&mut me.completion_status),

}
/// Returns whether or not this operation has completed.
pub fn is_done(&self) -> bool {
matches!(self.state, WaitableOperationState::Done)
}
}

@@ -464,13 +469,11 @@

fn drop(&mut self) {
// SAFETY: we're in the destructor here so the value `self` is about
// to go away and we can guarantee we're not moving out of it.
let mut pin = unsafe { Pin::new_unchecked(self) };
let (_, state, _) = pin.as_mut().pin_project();
// If this operation has already completed then skip cancellation,
// otherwise it's our job to cancel anything in-flight.
if let WaitableOperationState::Done = state {
if self.is_done() {
return;
}
// SAFETY: we're in the destructor here so the value `self` is about
// to go away and we can guarantee we're not moving out of it.
let pin = unsafe { Pin::new_unchecked(self) };
pin.cancel();

@@ -477,0 +480,0 @@ }

@@ -5,7 +5,7 @@ // This file is generated by ./ci/rebuild-libwit-bindgen-cabi.sh

extern void *cabi_realloc_wit_bindgen_0_47_0(void *ptr, size_t old_size, size_t align, size_t new_size);
extern void *cabi_realloc_wit_bindgen_0_48_0(void *ptr, size_t old_size, size_t align, size_t new_size);
__attribute__((__weak__, __export_name__("cabi_realloc")))
void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {
return cabi_realloc_wit_bindgen_0_47_0(ptr, old_size, align, new_size);
return cabi_realloc_wit_bindgen_0_48_0(ptr, old_size, align, new_size);
}
// This file is generated by ./ci/rebuild-libwit-bindgen-cabi.sh
#[unsafe(no_mangle)]
pub unsafe extern "C" fn cabi_realloc_wit_bindgen_0_47_0(
pub unsafe extern "C" fn cabi_realloc_wit_bindgen_0_48_0(
old_ptr: *mut u8,

@@ -6,0 +6,0 @@ old_len: usize,

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet