summaryrefslogtreecommitdiff
path: root/vendor/wit-bindgen-rt/src
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/wit-bindgen-rt/src
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/wit-bindgen-rt/src')
-rw-r--r--vendor/wit-bindgen-rt/src/async_support.rs515
-rw-r--r--vendor/wit-bindgen-rt/src/async_support/future_support.rs362
-rw-r--r--vendor/wit-bindgen-rt/src/async_support/stream_support.rs431
-rw-r--r--vendor/wit-bindgen-rt/src/cabi_realloc.c10
-rw-r--r--vendor/wit-bindgen-rt/src/cabi_realloc.obin0 -> 261 bytes
-rw-r--r--vendor/wit-bindgen-rt/src/cabi_realloc.rs11
-rw-r--r--vendor/wit-bindgen-rt/src/lib.rs118
-rw-r--r--vendor/wit-bindgen-rt/src/libwit_bindgen_cabi_realloc.abin0 -> 412 bytes
8 files changed, 1447 insertions, 0 deletions
diff --git a/vendor/wit-bindgen-rt/src/async_support.rs b/vendor/wit-bindgen-rt/src/async_support.rs
new file mode 100644
index 00000000..b60cabaf
--- /dev/null
+++ b/vendor/wit-bindgen-rt/src/async_support.rs
@@ -0,0 +1,515 @@
+#![deny(missing_docs)]
+#![allow(static_mut_refs)]
+
+extern crate std;
+use std::alloc::{self, Layout};
+use std::any::Any;
+use std::boxed::Box;
+use std::collections::{hash_map, HashMap};
+use std::fmt::{self, Debug, Display};
+use std::future::Future;
+use std::pin::Pin;
+use std::ptr;
+use std::string::String;
+use std::sync::Arc;
+use std::task::{Context, Poll, Wake, Waker};
+use std::vec::Vec;
+
+use futures::channel::oneshot;
+use futures::future::FutureExt;
+use futures::stream::{FuturesUnordered, StreamExt};
+use once_cell::sync::Lazy;
+
+mod future_support;
+mod stream_support;
+
+pub use {
+ future_support::{FutureReader, FutureVtable, FutureWriter},
+ stream_support::{StreamReader, StreamVtable, StreamWriter},
+};
+
+pub use futures;
+
+type BoxFuture = Pin<Box<dyn Future<Output = ()> + 'static>>;
+
+/// Represents a task created by either a call to an async-lifted export or a
+/// future run using `block_on` or `poll_future`.
+struct FutureState {
+ /// Number of in-progress async-lowered import calls and/or stream/future reads/writes.
+ todo: usize,
+ /// Remaining work to do (if any) before this task can be considered "done".
+ ///
+ /// Note that we won't tell the host the task is done until this is drained
+ /// and `todo` is zero.
+ tasks: Option<FuturesUnordered<BoxFuture>>,
+}
+
+/// Represents the state of a stream or future.
+#[doc(hidden)]
+pub enum Handle {
+ LocalOpen,
+ LocalReady(Box<dyn Any>, Waker),
+ LocalWaiting(oneshot::Sender<Box<dyn Any>>),
+ LocalClosed,
+ Read,
+ Write,
+}
+
+/// The current task being polled (or null if none).
+static mut CURRENT: *mut FutureState = ptr::null_mut();
+
+/// Map of any in-progress calls to async-lowered imports, keyed by the
+/// identifiers issued by the host.
+static mut CALLS: Lazy<HashMap<i32, oneshot::Sender<u32>>> = Lazy::new(HashMap::new);
+
+/// Any newly-deferred work queued by calls to the `spawn` function while
+/// polling the current task.
+static mut SPAWNED: Vec<BoxFuture> = Vec::new();
+
+/// The states of all currently-open streams and futures.
+static mut HANDLES: Lazy<HashMap<u32, Handle>> = Lazy::new(HashMap::new);
+
+#[doc(hidden)]
+pub fn with_entry<T>(handle: u32, fun: impl FnOnce(hash_map::Entry<'_, u32, Handle>) -> T) -> T {
+ fun(unsafe { HANDLES.entry(handle) })
+}
+
+fn dummy_waker() -> Waker {
+ struct DummyWaker;
+
+ impl Wake for DummyWaker {
+ fn wake(self: Arc<Self>) {}
+ }
+
+ static WAKER: Lazy<Arc<DummyWaker>> = Lazy::new(|| Arc::new(DummyWaker));
+
+ WAKER.clone().into()
+}
+
+/// Poll the specified task until it either completes or can't make immediate
+/// progress.
+unsafe fn poll(state: *mut FutureState) -> Poll<()> {
+ loop {
+ if let Some(futures) = (*state).tasks.as_mut() {
+ CURRENT = state;
+ let poll = futures.poll_next_unpin(&mut Context::from_waker(&dummy_waker()));
+ CURRENT = ptr::null_mut();
+
+ if SPAWNED.is_empty() {
+ match poll {
+ Poll::Ready(Some(())) => (),
+ Poll::Ready(None) => {
+ (*state).tasks = None;
+ break Poll::Ready(());
+ }
+ Poll::Pending => break Poll::Pending,
+ }
+ } else {
+ futures.extend(SPAWNED.drain(..));
+ }
+ } else {
+ break Poll::Ready(());
+ }
+ }
+}
+
+/// Poll the future generated by a call to an async-lifted export once, calling
+/// the specified closure (presumably backed by a call to `task.return`) when it
+/// generates a value.
+///
+/// This will return a non-null pointer representing the task if it hasn't
+/// completed immediately; otherwise it returns null.
+#[doc(hidden)]
+pub fn first_poll<T: 'static>(
+ future: impl Future<Output = T> + 'static,
+ fun: impl FnOnce(&T) + 'static,
+) -> *mut u8 {
+ let state = Box::into_raw(Box::new(FutureState {
+ todo: 0,
+ tasks: Some(
+ [Box::pin(future.map(|v| fun(&v))) as BoxFuture]
+ .into_iter()
+ .collect(),
+ ),
+ }));
+ match unsafe { poll(state) } {
+ Poll::Ready(()) => ptr::null_mut(),
+ Poll::Pending => state as _,
+ }
+}
+
+/// Await the completion of a call to an async-lowered import.
+#[doc(hidden)]
+pub async unsafe fn await_result(
+ import: unsafe extern "C" fn(*mut u8, *mut u8) -> i32,
+ params_layout: Layout,
+ params: *mut u8,
+ results: *mut u8,
+) {
+ const STATUS_STARTING: u32 = 0;
+ const STATUS_STARTED: u32 = 1;
+ const STATUS_RETURNED: u32 = 2;
+ const STATUS_DONE: u32 = 3;
+
+ let result = import(params, results) as u32;
+ let status = result >> 30;
+ let call = (result & !(0b11 << 30)) as i32;
+
+ if status != STATUS_DONE {
+ assert!(!CURRENT.is_null());
+ (*CURRENT).todo += 1;
+ }
+
+ match status {
+ STATUS_STARTING => {
+ let (tx, rx) = oneshot::channel();
+ CALLS.insert(call, tx);
+ rx.await.unwrap();
+ alloc::dealloc(params, params_layout);
+ }
+ STATUS_STARTED => {
+ alloc::dealloc(params, params_layout);
+ let (tx, rx) = oneshot::channel();
+ CALLS.insert(call, tx);
+ rx.await.unwrap();
+ }
+ STATUS_RETURNED | STATUS_DONE => {
+ alloc::dealloc(params, params_layout);
+ }
+ _ => unreachable!(),
+ }
+}
+
+/// stream/future read/write results defined by the Component Model ABI.
+mod results {
+ pub const BLOCKED: u32 = 0xffff_ffff;
+ pub const CLOSED: u32 = 0x8000_0000;
+ pub const CANCELED: u32 = 0;
+}
+
+/// Await the completion of a future read or write.
+#[doc(hidden)]
+pub async unsafe fn await_future_result(
+ import: unsafe extern "C" fn(u32, *mut u8) -> u32,
+ future: u32,
+ address: *mut u8,
+) -> bool {
+ let result = import(future, address);
+ match result {
+ results::BLOCKED => {
+ assert!(!CURRENT.is_null());
+ (*CURRENT).todo += 1;
+ let (tx, rx) = oneshot::channel();
+ CALLS.insert(future as _, tx);
+ let v = rx.await.unwrap();
+ v == 1
+ }
+ results::CLOSED | results::CANCELED => false,
+ 1 => true,
+ _ => unreachable!(),
+ }
+}
+
+/// Await the completion of a stream read or write.
+#[doc(hidden)]
+pub async unsafe fn await_stream_result(
+ import: unsafe extern "C" fn(u32, *mut u8, u32) -> u32,
+ stream: u32,
+ address: *mut u8,
+ count: u32,
+) -> Option<usize> {
+ let result = import(stream, address, count);
+ match result {
+ results::BLOCKED => {
+ assert!(!CURRENT.is_null());
+ (*CURRENT).todo += 1;
+ let (tx, rx) = oneshot::channel();
+ CALLS.insert(stream as _, tx);
+ let v = rx.await.unwrap();
+ if let results::CLOSED | results::CANCELED = v {
+ None
+ } else {
+ Some(usize::try_from(v).unwrap())
+ }
+ }
+ results::CLOSED | results::CANCELED => None,
+ v => Some(usize::try_from(v).unwrap()),
+ }
+}
+
+/// Call the `subtask.drop` canonical built-in function.
+fn subtask_drop(subtask: u32) {
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ _ = subtask;
+ unreachable!();
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ #[link(wasm_import_module = "$root")]
+ extern "C" {
+ #[link_name = "[subtask-drop]"]
+ fn subtask_drop(_: u32);
+ }
+ unsafe {
+ subtask_drop(subtask);
+ }
+ }
+}
+
+/// Handle a progress notification from the host regarding either a call to an
+/// async-lowered import or a stream/future read/write operation.
+#[doc(hidden)]
+pub unsafe fn callback(ctx: *mut u8, event0: i32, event1: i32, event2: i32) -> i32 {
+ const _EVENT_CALL_STARTING: i32 = 0;
+ const EVENT_CALL_STARTED: i32 = 1;
+ const EVENT_CALL_RETURNED: i32 = 2;
+ const EVENT_CALL_DONE: i32 = 3;
+ const _EVENT_YIELDED: i32 = 4;
+ const EVENT_STREAM_READ: i32 = 5;
+ const EVENT_STREAM_WRITE: i32 = 6;
+ const EVENT_FUTURE_READ: i32 = 7;
+ const EVENT_FUTURE_WRITE: i32 = 8;
+
+ match event0 {
+ EVENT_CALL_STARTED => 0,
+ EVENT_CALL_RETURNED | EVENT_CALL_DONE | EVENT_STREAM_READ | EVENT_STREAM_WRITE
+ | EVENT_FUTURE_READ | EVENT_FUTURE_WRITE => {
+ if let Some(call) = CALLS.remove(&event1) {
+ _ = call.send(event2 as _);
+ }
+
+ let state = ctx as *mut FutureState;
+ let done = poll(state).is_ready();
+
+ if event0 == EVENT_CALL_DONE {
+ subtask_drop(event1 as u32);
+ }
+
+ if matches!(
+ event0,
+ EVENT_CALL_DONE
+ | EVENT_STREAM_READ
+ | EVENT_STREAM_WRITE
+ | EVENT_FUTURE_READ
+ | EVENT_FUTURE_WRITE
+ ) {
+ (*state).todo -= 1;
+ }
+
+ if done && (*state).todo == 0 {
+ drop(Box::from_raw(state));
+ 1
+ } else {
+ 0
+ }
+ }
+ _ => unreachable!(),
+ }
+}
+
+/// Represents the Component Model `error-context` type.
+pub struct ErrorContext {
+ handle: u32,
+}
+
+impl ErrorContext {
+ #[doc(hidden)]
+ pub fn from_handle(handle: u32) -> Self {
+ Self { handle }
+ }
+
+ #[doc(hidden)]
+ pub fn handle(&self) -> u32 {
+ self.handle
+ }
+
+ /// Extract the debug message from a given [`ErrorContext`]
+ pub fn debug_message(&self) -> String {
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ _ = self;
+ unreachable!();
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ #[link(wasm_import_module = "$root")]
+ extern "C" {
+ #[link_name = "[error-context-debug-message;encoding=utf8;realloc=cabi_realloc]"]
+ fn error_context_debug_message(_: u32, _: *mut u8);
+ }
+
+ unsafe {
+ let mut ret = [0u32; 2];
+ error_context_debug_message(self.handle, ret.as_mut_ptr() as *mut _);
+ let len = usize::try_from(ret[1]).unwrap();
+ String::from_raw_parts(usize::try_from(ret[0]).unwrap() as *mut _, len, len)
+ }
+ }
+ }
+}
+
+impl Debug for ErrorContext {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("ErrorContext").finish()
+ }
+}
+
+impl Display for ErrorContext {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Error")
+ }
+}
+
+impl std::error::Error for ErrorContext {}
+
+impl Drop for ErrorContext {
+ fn drop(&mut self) {
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ unreachable!();
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ #[link(wasm_import_module = "$root")]
+ extern "C" {
+ #[link_name = "[error-context-drop]"]
+ fn error_drop(_: u32);
+ }
+ if self.handle != 0 {
+ unsafe { error_drop(self.handle) }
+ }
+ }
+ }
+}
+
+/// Defer the specified future to be run after the current async-lifted export
+/// task has returned a value.
+///
+/// The task will remain in a running state until all spawned futures have
+/// completed.
+pub fn spawn(future: impl Future<Output = ()> + 'static) {
+ unsafe { SPAWNED.push(Box::pin(future)) }
+}
+
+fn task_wait(state: &mut FutureState) {
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ _ = state;
+ unreachable!();
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ #[link(wasm_import_module = "$root")]
+ extern "C" {
+ #[link_name = "[task-wait]"]
+ fn wait(_: *mut i32) -> i32;
+ }
+ let mut payload = [0i32; 2];
+ unsafe {
+ let event0 = wait(payload.as_mut_ptr());
+ callback(state as *mut _ as _, event0, payload[0], payload[1]);
+ }
+ }
+}
+
+/// Run the specified future to completion, returning the result.
+///
+/// This uses `task.wait` to poll for progress on any in-progress calls to
+/// async-lowered imports as necessary.
+// TODO: refactor so `'static` bounds aren't necessary
+pub fn block_on<T: 'static>(future: impl Future<Output = T> + 'static) -> T {
+ let (tx, mut rx) = oneshot::channel();
+ let state = &mut FutureState {
+ todo: 0,
+ tasks: Some(
+ [Box::pin(future.map(move |v| drop(tx.send(v)))) as BoxFuture]
+ .into_iter()
+ .collect(),
+ ),
+ };
+ loop {
+ match unsafe { poll(state) } {
+ Poll::Ready(()) => break rx.try_recv().unwrap().unwrap(),
+ Poll::Pending => task_wait(state),
+ }
+ }
+}
+
+/// Call the `task.yield` canonical built-in function.
+///
+/// This yields control to the host temporarily, allowing other tasks to make
+/// progress. It's a good idea to call this inside a busy loop which does not
+/// otherwise ever yield control the the host.
+pub fn task_yield() {
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ unreachable!();
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ #[link(wasm_import_module = "$root")]
+ extern "C" {
+ #[link_name = "[task-yield]"]
+ fn yield_();
+ }
+ unsafe {
+ yield_();
+ }
+ }
+}
+
+/// Call the `task.backpressure` canonical built-in function.
+///
+/// When `enabled` is `true`, this tells the host to defer any new calls to this
+/// component instance until further notice (i.e. until `task.backpressure` is
+/// called again with `enabled` set to `false`).
+pub fn task_backpressure(enabled: bool) {
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ _ = enabled;
+ unreachable!();
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ #[link(wasm_import_module = "$root")]
+ extern "C" {
+ #[link_name = "[task-backpressure]"]
+ fn backpressure(_: i32);
+ }
+ unsafe {
+ backpressure(if enabled { 1 } else { 0 });
+ }
+ }
+}
+
+/// Call the `error-context.new` canonical built-in function.
+pub fn error_context_new(debug_message: &str) -> ErrorContext {
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ _ = debug_message;
+ unreachable!();
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ #[link(wasm_import_module = "$root")]
+ extern "C" {
+ #[link_name = "[error-context-new;encoding=utf8]"]
+ fn context_new(_: *const u8, _: usize) -> i32;
+ }
+
+ unsafe {
+ let handle = context_new(debug_message.as_ptr(), debug_message.len());
+ // SAFETY: Handles (including error context handles are guaranteed to
+ // fit inside u32 by the Component Model ABI
+ ErrorContext::from_handle(u32::try_from(handle).unwrap())
+ }
+ }
+}
diff --git a/vendor/wit-bindgen-rt/src/async_support/future_support.rs b/vendor/wit-bindgen-rt/src/async_support/future_support.rs
new file mode 100644
index 00000000..8477ec48
--- /dev/null
+++ b/vendor/wit-bindgen-rt/src/async_support/future_support.rs
@@ -0,0 +1,362 @@
+extern crate std;
+
+use {
+ super::Handle,
+ futures::{
+ channel::oneshot,
+ future::{self, FutureExt},
+ },
+ std::{
+ boxed::Box,
+ collections::hash_map::Entry,
+ fmt,
+ future::{Future, IntoFuture},
+ pin::Pin,
+ sync::atomic::{AtomicU32, Ordering::Relaxed},
+ task::{Context, Poll},
+ },
+};
+
+#[doc(hidden)]
+pub struct FutureVtable<T> {
+ pub write: fn(future: u32, value: T) -> Pin<Box<dyn Future<Output = bool>>>,
+ pub read: fn(future: u32) -> Pin<Box<dyn Future<Output = Option<T>>>>,
+ pub cancel_write: fn(future: u32),
+ pub cancel_read: fn(future: u32),
+ pub close_writable: fn(future: u32),
+ pub close_readable: fn(future: u32),
+}
+
+/// Represents the writable end of a Component Model `future`.
+pub struct FutureWriter<T: 'static> {
+ handle: u32,
+ vtable: &'static FutureVtable<T>,
+}
+
+impl<T> fmt::Debug for FutureWriter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("FutureWriter")
+ .field("handle", &self.handle)
+ .finish()
+ }
+}
+
+/// Represents a write operation which may be canceled prior to completion.
+pub struct CancelableWrite<T: 'static> {
+ writer: Option<FutureWriter<T>>,
+ future: Pin<Box<dyn Future<Output = ()>>>,
+}
+
+impl<T> Future for CancelableWrite<T> {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
+ let me = self.get_mut();
+ match me.future.poll_unpin(cx) {
+ Poll::Ready(()) => {
+ me.writer = None;
+ Poll::Ready(())
+ }
+ Poll::Pending => Poll::Pending,
+ }
+ }
+}
+
+impl<T> CancelableWrite<T> {
+ /// Cancel this write if it hasn't already completed, returning the original `FutureWriter`.
+ ///
+ /// This method will panic if the write has already completed.
+ pub fn cancel(mut self) -> FutureWriter<T> {
+ self.cancel_mut()
+ }
+
+ fn cancel_mut(&mut self) -> FutureWriter<T> {
+ let writer = self.writer.take().unwrap();
+ super::with_entry(writer.handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen
+ | Handle::LocalWaiting(_)
+ | Handle::Read
+ | Handle::LocalClosed => unreachable!(),
+ Handle::LocalReady(..) => {
+ entry.insert(Handle::LocalOpen);
+ }
+ Handle::Write => (writer.vtable.cancel_write)(writer.handle),
+ },
+ });
+ writer
+ }
+}
+
+impl<T> Drop for CancelableWrite<T> {
+ fn drop(&mut self) {
+ if self.writer.is_some() {
+ self.cancel_mut();
+ }
+ }
+}
+
+impl<T> FutureWriter<T> {
+ #[doc(hidden)]
+ pub fn new(handle: u32, vtable: &'static FutureVtable<T>) -> Self {
+ Self { handle, vtable }
+ }
+
+ /// Write the specified value to this `future`.
+ pub fn write(self, v: T) -> CancelableWrite<T> {
+ let handle = self.handle;
+ let vtable = self.vtable;
+ CancelableWrite {
+ writer: Some(self),
+ future: super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen => {
+ let mut v = Some(v);
+ Box::pin(future::poll_fn(move |cx| {
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen => {
+ entry.insert(Handle::LocalReady(
+ Box::new(v.take().unwrap()),
+ cx.waker().clone(),
+ ));
+ Poll::Pending
+ }
+ Handle::LocalReady(..) => Poll::Pending,
+ Handle::LocalClosed => Poll::Ready(()),
+ Handle::LocalWaiting(_) | Handle::Read | Handle::Write => {
+ unreachable!()
+ }
+ },
+ })
+ })) as Pin<Box<dyn Future<Output = _>>>
+ }
+ Handle::LocalWaiting(_) => {
+ let Handle::LocalWaiting(tx) = entry.insert(Handle::LocalClosed) else {
+ unreachable!()
+ };
+ _ = tx.send(Box::new(v));
+ Box::pin(future::ready(()))
+ }
+ Handle::LocalClosed => Box::pin(future::ready(())),
+ Handle::Read | Handle::LocalReady(..) => unreachable!(),
+ Handle::Write => Box::pin((vtable.write)(handle, v).map(drop)),
+ },
+ }),
+ }
+ }
+}
+
+impl<T> Drop for FutureWriter<T> {
+ fn drop(&mut self) {
+ super::with_entry(self.handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get_mut() {
+ Handle::LocalOpen | Handle::LocalWaiting(_) | Handle::LocalReady(..) => {
+ entry.insert(Handle::LocalClosed);
+ }
+ Handle::Read => unreachable!(),
+ Handle::Write | Handle::LocalClosed => {
+ entry.remove();
+ (self.vtable.close_writable)(self.handle);
+ }
+ },
+ });
+ }
+}
+
+/// Represents a read operation which may be canceled prior to completion.
+pub struct CancelableRead<T: 'static> {
+ reader: Option<FutureReader<T>>,
+ future: Pin<Box<dyn Future<Output = Option<T>>>>,
+}
+
+impl<T> Future for CancelableRead<T> {
+ type Output = Option<T>;
+
+ fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<T>> {
+ let me = self.get_mut();
+ match me.future.poll_unpin(cx) {
+ Poll::Ready(v) => {
+ me.reader = None;
+ Poll::Ready(v)
+ }
+ Poll::Pending => Poll::Pending,
+ }
+ }
+}
+
+impl<T> CancelableRead<T> {
+ /// Cancel this read if it hasn't already completed, returning the original `FutureReader`.
+ ///
+ /// This method will panic if the read has already completed.
+ pub fn cancel(mut self) -> FutureReader<T> {
+ self.cancel_mut()
+ }
+
+ fn cancel_mut(&mut self) -> FutureReader<T> {
+ let reader = self.reader.take().unwrap();
+ let handle = reader.handle.load(Relaxed);
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen
+ | Handle::LocalReady(..)
+ | Handle::Write
+ | Handle::LocalClosed => unreachable!(),
+ Handle::LocalWaiting(_) => {
+ entry.insert(Handle::LocalOpen);
+ }
+ Handle::Read => (reader.vtable.cancel_read)(handle),
+ },
+ });
+ reader
+ }
+}
+
+impl<T> Drop for CancelableRead<T> {
+ fn drop(&mut self) {
+ if self.reader.is_some() {
+ self.cancel_mut();
+ }
+ }
+}
+
+/// Represents the readable end of a Component Model `future`.
+pub struct FutureReader<T: 'static> {
+ handle: AtomicU32,
+ vtable: &'static FutureVtable<T>,
+}
+
+impl<T> fmt::Debug for FutureReader<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("FutureReader")
+ .field("handle", &self.handle)
+ .finish()
+ }
+}
+
+impl<T> FutureReader<T> {
+ #[doc(hidden)]
+ pub fn new(handle: u32, vtable: &'static FutureVtable<T>) -> Self {
+ Self {
+ handle: AtomicU32::new(handle),
+ vtable,
+ }
+ }
+
+ #[doc(hidden)]
+ pub fn from_handle_and_vtable(handle: u32, vtable: &'static FutureVtable<T>) -> Self {
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(entry) => {
+ entry.insert(Handle::Read);
+ }
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::Write => {
+ entry.insert(Handle::LocalOpen);
+ }
+ Handle::Read
+ | Handle::LocalOpen
+ | Handle::LocalReady(..)
+ | Handle::LocalWaiting(_)
+ | Handle::LocalClosed => {
+ unreachable!()
+ }
+ },
+ });
+
+ Self {
+ handle: AtomicU32::new(handle),
+ vtable,
+ }
+ }
+
+ #[doc(hidden)]
+ pub fn take_handle(&self) -> u32 {
+ let handle = self.handle.swap(u32::MAX, Relaxed);
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen => {
+ entry.insert(Handle::Write);
+ }
+ Handle::Read | Handle::LocalClosed => {
+ entry.remove();
+ }
+ Handle::LocalReady(..) | Handle::LocalWaiting(_) | Handle::Write => unreachable!(),
+ },
+ });
+
+ handle
+ }
+}
+
+impl<T> IntoFuture for FutureReader<T> {
+ type Output = Option<T>;
+ type IntoFuture = CancelableRead<T>;
+
+ /// Convert this object into a `Future` which will resolve when a value is
+ /// written to the writable end of this `future` (yielding a `Some` result)
+ /// or when the writable end is dropped (yielding a `None` result).
+ fn into_future(self) -> Self::IntoFuture {
+ let handle = self.handle.load(Relaxed);
+ let vtable = self.vtable;
+ CancelableRead {
+ reader: Some(self),
+ future: super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::Write | Handle::LocalWaiting(_) => unreachable!(),
+ Handle::Read => Box::pin(async move { (vtable.read)(handle).await })
+ as Pin<Box<dyn Future<Output = _>>>,
+ Handle::LocalOpen => {
+ let (tx, rx) = oneshot::channel();
+ entry.insert(Handle::LocalWaiting(tx));
+ Box::pin(async move { rx.await.ok().map(|v| *v.downcast().unwrap()) })
+ }
+ Handle::LocalClosed => Box::pin(future::ready(None)),
+ Handle::LocalReady(..) => {
+ let Handle::LocalReady(v, waker) = entry.insert(Handle::LocalClosed) else {
+ unreachable!()
+ };
+ waker.wake();
+ Box::pin(future::ready(Some(*v.downcast().unwrap())))
+ }
+ },
+ }),
+ }
+ }
+}
+
+impl<T> Drop for FutureReader<T> {
+ fn drop(&mut self) {
+ match self.handle.load(Relaxed) {
+ u32::MAX => {}
+ handle => {
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get_mut() {
+ Handle::LocalReady(..) => {
+ let Handle::LocalReady(_, waker) = entry.insert(Handle::LocalClosed)
+ else {
+ unreachable!()
+ };
+ waker.wake();
+ }
+ Handle::LocalOpen | Handle::LocalWaiting(_) => {
+ entry.insert(Handle::LocalClosed);
+ }
+ Handle::Read | Handle::LocalClosed => {
+ entry.remove();
+ (self.vtable.close_readable)(handle);
+ }
+ Handle::Write => unreachable!(),
+ },
+ });
+ }
+ }
+ }
+}
diff --git a/vendor/wit-bindgen-rt/src/async_support/stream_support.rs b/vendor/wit-bindgen-rt/src/async_support/stream_support.rs
new file mode 100644
index 00000000..d80b96d6
--- /dev/null
+++ b/vendor/wit-bindgen-rt/src/async_support/stream_support.rs
@@ -0,0 +1,431 @@
+extern crate std;
+
+use {
+ super::Handle,
+ futures::{
+ channel::oneshot,
+ future::{self, FutureExt},
+ sink::Sink,
+ stream::Stream,
+ },
+ std::{
+ boxed::Box,
+ collections::hash_map::Entry,
+ convert::Infallible,
+ fmt,
+ future::Future,
+ iter,
+ mem::{self, MaybeUninit},
+ pin::Pin,
+ sync::atomic::{AtomicU32, Ordering::Relaxed},
+ task::{Context, Poll},
+ vec::Vec,
+ },
+};
+
+fn ceiling(x: usize, y: usize) -> usize {
+ (x / y) + if x % y == 0 { 0 } else { 1 }
+}
+
+#[doc(hidden)]
+pub struct StreamVtable<T> {
+ pub write: fn(future: u32, values: &[T]) -> Pin<Box<dyn Future<Output = usize> + '_>>,
+ pub read: fn(
+ future: u32,
+ values: &mut [MaybeUninit<T>],
+ ) -> Pin<Box<dyn Future<Output = Option<usize>> + '_>>,
+ pub cancel_write: fn(future: u32),
+ pub cancel_read: fn(future: u32),
+ pub close_writable: fn(future: u32),
+ pub close_readable: fn(future: u32),
+}
+
+struct CancelWriteOnDrop<T: 'static> {
+ handle: Option<u32>,
+ vtable: &'static StreamVtable<T>,
+}
+
+impl<T> Drop for CancelWriteOnDrop<T> {
+ fn drop(&mut self) {
+ if let Some(handle) = self.handle.take() {
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen
+ | Handle::LocalWaiting(_)
+ | Handle::Read
+ | Handle::LocalClosed => unreachable!(),
+ Handle::LocalReady(..) => {
+ entry.insert(Handle::LocalOpen);
+ }
+ Handle::Write => (self.vtable.cancel_write)(handle),
+ },
+ });
+ }
+ }
+}
+
+/// Represents the writable end of a Component Model `stream`.
+pub struct StreamWriter<T: 'static> {
+ handle: u32,
+ future: Option<Pin<Box<dyn Future<Output = ()> + 'static>>>,
+ vtable: &'static StreamVtable<T>,
+}
+
+impl<T> StreamWriter<T> {
+ #[doc(hidden)]
+ pub fn new(handle: u32, vtable: &'static StreamVtable<T>) -> Self {
+ Self {
+ handle,
+ future: None,
+ vtable,
+ }
+ }
+
+ /// Cancel the current pending write operation.
+ ///
+ /// This will panic if no such operation is pending.
+ pub fn cancel(&mut self) {
+ assert!(self.future.is_some());
+ self.future = None;
+ }
+}
+
+impl<T> fmt::Debug for StreamWriter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("StreamWriter")
+ .field("handle", &self.handle)
+ .finish()
+ }
+}
+
+impl<T> Sink<Vec<T>> for StreamWriter<T> {
+ type Error = Infallible;
+
+ fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
+ let me = self.get_mut();
+
+ if let Some(future) = &mut me.future {
+ match future.as_mut().poll(cx) {
+ Poll::Ready(_) => {
+ me.future = None;
+ Poll::Ready(Ok(()))
+ }
+ Poll::Pending => Poll::Pending,
+ }
+ } else {
+ Poll::Ready(Ok(()))
+ }
+ }
+
+ fn start_send(self: Pin<&mut Self>, item: Vec<T>) -> Result<(), Self::Error> {
+ assert!(self.future.is_none());
+ super::with_entry(self.handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen => {
+ let handle = self.handle;
+ let mut item = Some(item);
+ let mut cancel_on_drop = Some(CancelWriteOnDrop::<T> {
+ handle: Some(handle),
+ vtable: self.vtable,
+ });
+ self.get_mut().future = Some(Box::pin(future::poll_fn(move |cx| {
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen => {
+ if let Some(item) = item.take() {
+ entry.insert(Handle::LocalReady(
+ Box::new(item),
+ cx.waker().clone(),
+ ));
+ Poll::Pending
+ } else {
+ cancel_on_drop.take().unwrap().handle = None;
+ Poll::Ready(())
+ }
+ }
+ Handle::LocalReady(..) => Poll::Pending,
+ Handle::LocalClosed => {
+ cancel_on_drop.take().unwrap().handle = None;
+ Poll::Ready(())
+ }
+ Handle::LocalWaiting(_) | Handle::Read | Handle::Write => {
+ unreachable!()
+ }
+ },
+ })
+ })));
+ }
+ Handle::LocalWaiting(_) => {
+ let Handle::LocalWaiting(tx) = entry.insert(Handle::LocalOpen) else {
+ unreachable!()
+ };
+ _ = tx.send(Box::new(item));
+ }
+ Handle::LocalClosed => (),
+ Handle::Read | Handle::LocalReady(..) => unreachable!(),
+ Handle::Write => {
+ let handle = self.handle;
+ let vtable = self.vtable;
+ let mut cancel_on_drop = CancelWriteOnDrop::<T> {
+ handle: Some(handle),
+ vtable,
+ };
+ self.get_mut().future = Some(Box::pin(async move {
+ (vtable.write)(handle, &item).await;
+ cancel_on_drop.handle = None;
+ drop(cancel_on_drop);
+ }));
+ }
+ },
+ });
+ Ok(())
+ }
+
+ fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
+ self.poll_ready(cx)
+ }
+
+ fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
+ self.poll_ready(cx)
+ }
+}
+
+impl<T> Drop for StreamWriter<T> {
+ fn drop(&mut self) {
+ self.future = None;
+
+ super::with_entry(self.handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get_mut() {
+ Handle::LocalOpen | Handle::LocalWaiting(_) | Handle::LocalReady(..) => {
+ entry.insert(Handle::LocalClosed);
+ }
+ Handle::Read => unreachable!(),
+ Handle::Write | Handle::LocalClosed => {
+ entry.remove();
+ (self.vtable.close_writable)(self.handle);
+ }
+ },
+ });
+ }
+}
+
+struct CancelReadOnDrop<T: 'static> {
+ handle: Option<u32>,
+ vtable: &'static StreamVtable<T>,
+}
+
+impl<T> Drop for CancelReadOnDrop<T> {
+ fn drop(&mut self) {
+ if let Some(handle) = self.handle.take() {
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen
+ | Handle::LocalReady(..)
+ | Handle::Write
+ | Handle::LocalClosed => unreachable!(),
+ Handle::LocalWaiting(_) => {
+ entry.insert(Handle::LocalOpen);
+ }
+ Handle::Read => (self.vtable.cancel_read)(handle),
+ },
+ });
+ }
+ }
+}
+
+/// Represents the readable end of a Component Model `stream`.
+pub struct StreamReader<T: 'static> {
+ handle: AtomicU32,
+ future: Option<Pin<Box<dyn Future<Output = Option<Vec<T>>> + 'static>>>,
+ vtable: &'static StreamVtable<T>,
+}
+
+impl<T> StreamReader<T> {
+ /// Cancel the current pending read operation.
+ ///
+ /// This will panic if no such operation is pending.
+ pub fn cancel(&mut self) {
+ assert!(self.future.is_some());
+ self.future = None;
+ }
+}
+
+impl<T> fmt::Debug for StreamReader<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("StreamReader")
+ .field("handle", &self.handle)
+ .finish()
+ }
+}
+
+impl<T> StreamReader<T> {
+ #[doc(hidden)]
+ pub fn new(handle: u32, vtable: &'static StreamVtable<T>) -> Self {
+ Self {
+ handle: AtomicU32::new(handle),
+ future: None,
+ vtable,
+ }
+ }
+
+ #[doc(hidden)]
+ pub fn from_handle_and_vtable(handle: u32, vtable: &'static StreamVtable<T>) -> Self {
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(entry) => {
+ entry.insert(Handle::Read);
+ }
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::Write => {
+ entry.insert(Handle::LocalOpen);
+ }
+ Handle::Read
+ | Handle::LocalOpen
+ | Handle::LocalReady(..)
+ | Handle::LocalWaiting(_)
+ | Handle::LocalClosed => {
+ unreachable!()
+ }
+ },
+ });
+
+ Self {
+ handle: AtomicU32::new(handle),
+ future: None,
+ vtable,
+ }
+ }
+
+ #[doc(hidden)]
+ pub fn take_handle(&self) -> u32 {
+ let handle = self.handle.swap(u32::MAX, Relaxed);
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::LocalOpen => {
+ entry.insert(Handle::Write);
+ }
+ Handle::Read | Handle::LocalClosed => {
+ entry.remove();
+ }
+ Handle::LocalReady(..) | Handle::LocalWaiting(_) | Handle::Write => unreachable!(),
+ },
+ });
+
+ handle
+ }
+}
+
+impl<T> Stream for StreamReader<T> {
+ type Item = Vec<T>;
+
+ fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
+ let me = self.get_mut();
+
+ if me.future.is_none() {
+ me.future = Some(super::with_entry(
+ me.handle.load(Relaxed),
+ |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get() {
+ Handle::Write | Handle::LocalWaiting(_) => unreachable!(),
+ Handle::Read => {
+ let handle = me.handle.load(Relaxed);
+ let vtable = me.vtable;
+ let mut cancel_on_drop = CancelReadOnDrop::<T> {
+ handle: Some(handle),
+ vtable,
+ };
+ Box::pin(async move {
+ let mut buffer = iter::repeat_with(MaybeUninit::uninit)
+ .take(ceiling(64 * 1024, mem::size_of::<T>().max(1)))
+ .collect::<Vec<_>>();
+
+ let result =
+ if let Some(count) = (vtable.read)(handle, &mut buffer).await {
+ buffer.truncate(count);
+ Some(unsafe {
+ mem::transmute::<Vec<MaybeUninit<T>>, Vec<T>>(buffer)
+ })
+ } else {
+ None
+ };
+ cancel_on_drop.handle = None;
+ drop(cancel_on_drop);
+ result
+ }) as Pin<Box<dyn Future<Output = _>>>
+ }
+ Handle::LocalOpen => {
+ let (tx, rx) = oneshot::channel();
+ entry.insert(Handle::LocalWaiting(tx));
+ let mut cancel_on_drop = CancelReadOnDrop::<T> {
+ handle: Some(me.handle.load(Relaxed)),
+ vtable: me.vtable,
+ };
+ Box::pin(async move {
+ let result =
+ rx.map(|v| v.ok().map(|v| *v.downcast().unwrap())).await;
+ cancel_on_drop.handle = None;
+ drop(cancel_on_drop);
+ result
+ })
+ }
+ Handle::LocalClosed => Box::pin(future::ready(None)),
+ Handle::LocalReady(..) => {
+ let Handle::LocalReady(v, waker) = entry.insert(Handle::LocalOpen)
+ else {
+ unreachable!()
+ };
+ waker.wake();
+ Box::pin(future::ready(Some(*v.downcast().unwrap())))
+ }
+ },
+ },
+ ));
+ }
+
+ match me.future.as_mut().unwrap().as_mut().poll(cx) {
+ Poll::Ready(v) => {
+ me.future = None;
+ Poll::Ready(v)
+ }
+ Poll::Pending => Poll::Pending,
+ }
+ }
+}
+
+impl<T> Drop for StreamReader<T> {
+ fn drop(&mut self) {
+ self.future = None;
+
+ match self.handle.load(Relaxed) {
+ u32::MAX => {}
+ handle => {
+ super::with_entry(handle, |entry| match entry {
+ Entry::Vacant(_) => unreachable!(),
+ Entry::Occupied(mut entry) => match entry.get_mut() {
+ Handle::LocalReady(..) => {
+ let Handle::LocalReady(_, waker) = entry.insert(Handle::LocalClosed)
+ else {
+ unreachable!()
+ };
+ waker.wake();
+ }
+ Handle::LocalOpen | Handle::LocalWaiting(_) => {
+ entry.insert(Handle::LocalClosed);
+ }
+ Handle::Read | Handle::LocalClosed => {
+ entry.remove();
+ (self.vtable.close_readable)(handle);
+ }
+ Handle::Write => unreachable!(),
+ },
+ });
+ }
+ }
+ }
+}
diff --git a/vendor/wit-bindgen-rt/src/cabi_realloc.c b/vendor/wit-bindgen-rt/src/cabi_realloc.c
new file mode 100644
index 00000000..46e59ec8
--- /dev/null
+++ b/vendor/wit-bindgen-rt/src/cabi_realloc.c
@@ -0,0 +1,10 @@
+// This file is generated by ./ci/rebuild-libcabi-realloc.sh
+
+#include <stdint.h>
+
+extern void *cabi_realloc_wit_bindgen_0_39_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_39_0(ptr, old_size, align, new_size);
+}
diff --git a/vendor/wit-bindgen-rt/src/cabi_realloc.o b/vendor/wit-bindgen-rt/src/cabi_realloc.o
new file mode 100644
index 00000000..ea5f3988
--- /dev/null
+++ b/vendor/wit-bindgen-rt/src/cabi_realloc.o
Binary files differ
diff --git a/vendor/wit-bindgen-rt/src/cabi_realloc.rs b/vendor/wit-bindgen-rt/src/cabi_realloc.rs
new file mode 100644
index 00000000..5a2fd72f
--- /dev/null
+++ b/vendor/wit-bindgen-rt/src/cabi_realloc.rs
@@ -0,0 +1,11 @@
+// This file is generated by ./ci/rebuild-libcabi-realloc.sh
+
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn cabi_realloc_wit_bindgen_0_39_0(
+ old_ptr: *mut u8,
+ old_len: usize,
+ align: usize,
+ new_len: usize,
+) -> *mut u8 {
+ crate::cabi_realloc(old_ptr, old_len, align, new_len)
+}
diff --git a/vendor/wit-bindgen-rt/src/lib.rs b/vendor/wit-bindgen-rt/src/lib.rs
new file mode 100644
index 00000000..0f285836
--- /dev/null
+++ b/vendor/wit-bindgen-rt/src/lib.rs
@@ -0,0 +1,118 @@
+#![no_std]
+
+extern crate alloc;
+
+// Re-export `bitflags` so that we can reference it from macros.
+#[cfg(feature = "bitflags")]
+#[doc(hidden)]
+pub use bitflags;
+
+/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
+#[cfg(not(target_env = "p2"))]
+mod cabi_realloc;
+
+/// This function is called from generated bindings and will be deleted by
+/// the linker. The purpose of this function is to force a reference to the
+/// symbol `cabi_realloc` to make its way through to the final linker
+/// command line. That way `wasm-ld` will pick it up, see it needs to be
+/// exported, and then export it.
+///
+/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
+pub fn maybe_link_cabi_realloc() {
+ #[cfg(all(target_family = "wasm", not(target_env = "p2")))]
+ {
+ extern "C" {
+ fn cabi_realloc(
+ old_ptr: *mut u8,
+ old_len: usize,
+ align: usize,
+ new_len: usize,
+ ) -> *mut u8;
+ }
+ // Force the `cabi_realloc` symbol to be referenced from here. This
+ // is done with a `#[used]` Rust `static` to ensure that this
+ // reference makes it all the way to the linker before it's
+ // considered for garbage collection. When the linker sees it it'll
+ // remove this `static` here (due to it not actually being needed)
+ // but the linker will have at that point seen the `cabi_realloc`
+ // symbol and it should get exported.
+ #[used]
+ static _NAME_DOES_NOT_MATTER: unsafe extern "C" fn(
+ *mut u8,
+ usize,
+ usize,
+ usize,
+ ) -> *mut u8 = cabi_realloc;
+ }
+}
+
+/// NB: this function is called by a generated function in the
+/// `cabi_realloc` module above. It's otherwise never explicitly called.
+///
+/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
+#[cfg(not(target_env = "p2"))]
+pub unsafe fn cabi_realloc(
+ old_ptr: *mut u8,
+ old_len: usize,
+ align: usize,
+ new_len: usize,
+) -> *mut u8 {
+ use self::alloc::alloc::{self, Layout};
+
+ let layout;
+ let ptr = if old_len == 0 {
+ if new_len == 0 {
+ return align as *mut u8;
+ }
+ layout = Layout::from_size_align_unchecked(new_len, align);
+ alloc::alloc(layout)
+ } else {
+ debug_assert_ne!(new_len, 0, "non-zero old_len requires non-zero new_len!");
+ layout = Layout::from_size_align_unchecked(old_len, align);
+ alloc::realloc(old_ptr, layout, new_len)
+ };
+ if ptr.is_null() {
+ // Print a nice message in debug mode, but in release mode don't
+ // pull in so many dependencies related to printing so just emit an
+ // `unreachable` instruction.
+ if cfg!(debug_assertions) {
+ alloc::handle_alloc_error(layout);
+ } else {
+ #[cfg(target_arch = "wasm32")]
+ core::arch::wasm32::unreachable();
+ #[cfg(not(target_arch = "wasm32"))]
+ unreachable!();
+ }
+ }
+ return ptr;
+}
+
+/// Provide a hook for generated export functions to run static constructors at
+/// most once.
+///
+/// wit-bindgen-rust generates a call to this function at the start of all
+/// component export functions. Importantly, it is not called as part of
+/// `cabi_realloc`, which is a *core* export func, but should not execute ctors.
+#[cfg(target_arch = "wasm32")]
+pub fn run_ctors_once() {
+ static mut RUN: bool = false;
+ unsafe {
+ if !RUN {
+ // This function is synthesized by `wasm-ld` to run all static
+ // constructors. wasm-ld will either provide an implementation
+ // of this symbol, or synthesize a wrapper around each
+ // exported function to (unconditionally) run ctors. By using
+ // this function, the linked module is opting into "manually"
+ // running ctors.
+ extern "C" {
+ fn __wasm_call_ctors();
+ }
+ __wasm_call_ctors();
+ RUN = true;
+ }
+ }
+}
+
+/// Support for using the Component Model Async ABI
+#[cfg(feature = "async")]
+pub mod async_support;
diff --git a/vendor/wit-bindgen-rt/src/libwit_bindgen_cabi_realloc.a b/vendor/wit-bindgen-rt/src/libwit_bindgen_cabi_realloc.a
new file mode 100644
index 00000000..709cea46
--- /dev/null
+++ b/vendor/wit-bindgen-rt/src/libwit_bindgen_cabi_realloc.a
Binary files differ