Skip to content

Commit ec84c8e

Browse files
authored
Re-add bindings for old bindings generators. (#869)
1 parent d876603 commit ec84c8e

File tree

2 files changed

+299
-4
lines changed

2 files changed

+299
-4
lines changed

crates/guest-rust/src/lib.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,10 @@ pub use bitflags;
312312
#[cfg(feature = "realloc")]
313313
mod cabi_realloc;
314314

315+
mod pre_wit_bindgen_0_20_0;
316+
315317
#[doc(hidden)]
316318
pub mod rt {
317-
318-
extern crate alloc;
319-
320319
/// This function is called from generated bindings and will be deleted by
321320
/// the linker. The purpose of this function is to force a reference to the
322321
/// symbol `cabi_realloc` to make its way through to the final linker
@@ -365,7 +364,7 @@ pub mod rt {
365364
align: usize,
366365
new_len: usize,
367366
) -> *mut u8 {
368-
use self::alloc::alloc::{self, Layout};
367+
use alloc::Layout;
369368

370369
let layout;
371370
let ptr = if old_len == 0 {
@@ -394,4 +393,6 @@ pub mod rt {
394393
}
395394
return ptr;
396395
}
396+
397+
pub use crate::pre_wit_bindgen_0_20_0::*;
397398
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
//! NB: These functions are not used any more by the latest version of the
2+
//! bindings generator for Rust. These functions are provided for historical
3+
//! compatibility with previous bindings generators before the 0.20.0 version
4+
//! of wit-bindgen.
5+
//!
6+
//! Once `cargo component` has updated to `wit-bindgen` 0.20.0+ and has been
7+
//! there for awhile this file should be removed.
8+
9+
extern crate alloc as alloc_crate;
10+
11+
use alloc_crate::alloc::Layout;
12+
use alloc_crate::boxed::Box;
13+
use alloc_crate::string::String;
14+
use alloc_crate::vec::Vec;
15+
use core::fmt;
16+
use core::marker;
17+
use core::ops::{Deref, DerefMut};
18+
use core::sync::atomic::{AtomicU32, Ordering::Relaxed};
19+
20+
pub use alloc_crate::{alloc, boxed, string, vec};
21+
22+
/// Provide a hook for generated export functions to run static
23+
/// constructors at most once. wit-bindgen-rust generates a call to this
24+
/// function at the start of all component export functions. Importantly,
25+
/// it is not called as part of `cabi_realloc`, which is a *core* export
26+
/// func, but may not execute ctors, because the environment ctor in
27+
/// wasi-libc (before rust 1.69.0) calls an import func, which is not
28+
/// permitted by the Component Model when inside realloc.
29+
///
30+
/// We intend to remove this once rust 1.69.0 stabilizes.
31+
#[cfg(target_arch = "wasm32")]
32+
pub fn run_ctors_once() {
33+
static mut RUN: bool = false;
34+
unsafe {
35+
if !RUN {
36+
// This function is synthesized by `wasm-ld` to run all static
37+
// constructors. wasm-ld will either provide an implementation
38+
// of this symbol, or synthesize a wrapper around each
39+
// exported function to (unconditionally) run ctors. By using
40+
// this function, the linked module is opting into "manually"
41+
// running ctors.
42+
extern "C" {
43+
fn __wasm_call_ctors();
44+
}
45+
__wasm_call_ctors();
46+
RUN = true;
47+
}
48+
}
49+
}
50+
51+
pub unsafe fn dealloc(ptr: i32, size: usize, align: usize) {
52+
if size == 0 {
53+
return;
54+
}
55+
let layout = Layout::from_size_align_unchecked(size, align);
56+
alloc_crate::alloc::dealloc(ptr as *mut u8, layout);
57+
}
58+
59+
macro_rules! as_traits {
60+
($(($trait_:ident $func:ident $ty:ident <=> $($tys:ident)*))*) => ($(
61+
pub fn $func<T: $trait_>(t: T) -> $ty {
62+
t.$func()
63+
}
64+
65+
pub trait $trait_ {
66+
fn $func(self) -> $ty;
67+
}
68+
69+
impl<'a, T: Copy + $trait_> $trait_ for &'a T {
70+
fn $func(self) -> $ty{
71+
(*self).$func()
72+
}
73+
}
74+
75+
$(
76+
impl $trait_ for $tys {
77+
#[inline]
78+
fn $func(self) -> $ty {
79+
self as $ty
80+
}
81+
}
82+
)*
83+
84+
)*)
85+
}
86+
87+
as_traits! {
88+
(AsI64 as_i64 i64 <=> i64 u64)
89+
(AsI32 as_i32 i32 <=> i32 u32 i16 u16 i8 u8 char usize)
90+
(AsF32 as_f32 f32 <=> f32)
91+
(AsF64 as_f64 f64 <=> f64)
92+
}
93+
94+
pub unsafe fn string_lift(bytes: Vec<u8>) -> String {
95+
if cfg!(debug_assertions) {
96+
String::from_utf8(bytes).unwrap()
97+
} else {
98+
String::from_utf8_unchecked(bytes)
99+
}
100+
}
101+
102+
pub unsafe fn invalid_enum_discriminant<T>() -> T {
103+
if cfg!(debug_assertions) {
104+
panic!("invalid enum discriminant")
105+
} else {
106+
core::hint::unreachable_unchecked()
107+
}
108+
}
109+
110+
pub unsafe fn char_lift(val: u32) -> char {
111+
if cfg!(debug_assertions) {
112+
core::char::from_u32(val).unwrap()
113+
} else {
114+
core::char::from_u32_unchecked(val)
115+
}
116+
}
117+
118+
pub unsafe fn bool_lift(val: u8) -> bool {
119+
if cfg!(debug_assertions) {
120+
match val {
121+
0 => false,
122+
1 => true,
123+
_ => panic!("invalid bool discriminant"),
124+
}
125+
} else {
126+
core::mem::transmute::<u8, bool>(val)
127+
}
128+
}
129+
130+
type RawRep<T> = Option<T>;
131+
132+
/// A type which represents a component model resource, either imported or
133+
/// exported into this component.
134+
///
135+
/// This is a low-level wrapper which handles the lifetime of the resource
136+
/// (namely this has a destructor). The `T` provided defines the component model
137+
/// intrinsics that this wrapper uses.
138+
///
139+
/// One of the chief purposes of this type is to provide `Deref` implementations
140+
/// to access the underlying data when it is owned.
141+
///
142+
/// This type is primarily used in generated code for exported and imported
143+
/// resources.
144+
#[repr(transparent)]
145+
pub struct Resource<T: WasmResource> {
146+
// NB: This would ideally be `u32` but it is not. The fact that this has
147+
// interior mutability is not exposed in the API of this type except for the
148+
// `take_handle` method which is supposed to in theory be private.
149+
//
150+
// This represents, almost all the time, a valid handle value. When it's
151+
// invalid it's stored as `u32::MAX`.
152+
handle: AtomicU32,
153+
_marker: marker::PhantomData<Box<T>>,
154+
}
155+
156+
/// A trait which all wasm resources implement, namely providing the ability to
157+
/// drop a resource.
158+
///
159+
/// This generally is implemented by generated code, not user-facing code.
160+
pub unsafe trait WasmResource {
161+
/// Invokes the `[resource-drop]...` intrinsic.
162+
unsafe fn drop(handle: u32);
163+
}
164+
165+
/// A trait which extends [`WasmResource`] used for Rust-defined resources, or
166+
/// those exported from this component.
167+
///
168+
/// This generally is implemented by generated code, not user-facing code.
169+
pub unsafe trait RustResource: WasmResource {
170+
/// Invokes the `[resource-new]...` intrinsic.
171+
unsafe fn new(rep: usize) -> u32;
172+
/// Invokes the `[resource-rep]...` intrinsic.
173+
unsafe fn rep(handle: u32) -> usize;
174+
}
175+
176+
impl<T: WasmResource> Resource<T> {
177+
#[doc(hidden)]
178+
pub unsafe fn from_handle(handle: u32) -> Self {
179+
debug_assert!(handle != u32::MAX);
180+
Self {
181+
handle: AtomicU32::new(handle),
182+
_marker: marker::PhantomData,
183+
}
184+
}
185+
186+
/// Takes ownership of the handle owned by `resource`.
187+
///
188+
/// Note that this ideally would be `into_handle` taking `Resource<T>` by
189+
/// ownership. The code generator does not enable that in all situations,
190+
/// unfortunately, so this is provided instead.
191+
///
192+
/// Also note that `take_handle` is in theory only ever called on values
193+
/// owned by a generated function. For example a generated function might
194+
/// take `Resource<T>` as an argument but then call `take_handle` on a
195+
/// reference to that argument. In that sense the dynamic nature of
196+
/// `take_handle` should only be exposed internally to generated code, not
197+
/// to user code.
198+
#[doc(hidden)]
199+
pub fn take_handle(resource: &Resource<T>) -> u32 {
200+
resource.handle.swap(u32::MAX, Relaxed)
201+
}
202+
203+
#[doc(hidden)]
204+
pub fn handle(resource: &Resource<T>) -> u32 {
205+
resource.handle.load(Relaxed)
206+
}
207+
208+
/// Creates a new Rust-defined resource from the underlying representation
209+
/// `T`.
210+
///
211+
/// This will move `T` onto the heap to create a single pointer to represent
212+
/// it which is then wrapped up in a component model resource.
213+
pub fn new(val: T) -> Resource<T>
214+
where
215+
T: RustResource,
216+
{
217+
let rep = Box::into_raw(Box::new(Some(val))) as usize;
218+
unsafe {
219+
let handle = T::new(rep);
220+
Resource::from_handle(handle)
221+
}
222+
}
223+
224+
#[doc(hidden)]
225+
pub unsafe fn dtor(rep: usize)
226+
where
227+
T: RustResource,
228+
{
229+
let _ = Box::from_raw(rep as *mut RawRep<T>);
230+
}
231+
232+
/// Takes back ownership of the object, dropping the resource handle.
233+
pub fn into_inner(resource: Self) -> T
234+
where
235+
T: RustResource,
236+
{
237+
unsafe {
238+
let rep = T::rep(resource.handle.load(Relaxed));
239+
RawRep::take(&mut *(rep as *mut RawRep<T>)).unwrap()
240+
}
241+
}
242+
243+
#[doc(hidden)]
244+
pub unsafe fn lift_borrow<'a>(rep: usize) -> &'a T
245+
where
246+
T: RustResource,
247+
{
248+
RawRep::as_ref(&*(rep as *const RawRep<T>)).unwrap()
249+
}
250+
}
251+
252+
impl<T: RustResource> Deref for Resource<T> {
253+
type Target = T;
254+
255+
fn deref(&self) -> &T {
256+
unsafe {
257+
let rep = T::rep(self.handle.load(Relaxed));
258+
RawRep::as_ref(&*(rep as *const RawRep<T>)).unwrap()
259+
}
260+
}
261+
}
262+
263+
impl<T: RustResource> DerefMut for Resource<T> {
264+
fn deref_mut(&mut self) -> &mut T {
265+
unsafe {
266+
let rep = T::rep(self.handle.load(Relaxed));
267+
RawRep::as_mut(&mut *(rep as *mut RawRep<T>)).unwrap()
268+
}
269+
}
270+
}
271+
272+
impl<T: WasmResource> fmt::Debug for Resource<T> {
273+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274+
f.debug_struct("Resource")
275+
.field("handle", &self.handle)
276+
.finish()
277+
}
278+
}
279+
280+
impl<T: WasmResource> Drop for Resource<T> {
281+
fn drop(&mut self) {
282+
unsafe {
283+
match self.handle.load(Relaxed) {
284+
// If this handle was "taken" then don't do anything in the
285+
// destructor.
286+
u32::MAX => {}
287+
288+
// ... but otherwise do actually destroy it with the imported
289+
// component model intrinsic as defined through `T`.
290+
other => T::drop(other),
291+
}
292+
}
293+
}
294+
}

0 commit comments

Comments
 (0)