|
1 | | -/// A |
| 1 | +/// A trait used as part of [`bindgen!`] to indicate a `Data<'_>` payload that |
| 2 | +/// implements some host bindings traits. |
| 3 | +/// |
| 4 | +/// The purpose of the [`bindgen!`] macro is to define Rust traits that the host |
| 5 | +/// can implement to fulfill WIT functions imported from the host into a |
| 6 | +/// component. The [`bindgen!`] macro then additionally generates a function |
| 7 | +/// which takes a [`Linker`] and an implementation of the traits and fills out |
| 8 | +/// the [`Linker`]. This trait, [`HasData`], is used in this process of filling |
| 9 | +/// out the [`Linker`] for some WIT interfaces. |
| 10 | +/// |
| 11 | +/// Wasmtime's [`Store<T>`] type is the home for all per-instance state. |
| 12 | +/// Notably the `T` here is generic (the Wasmtime library allows any type to be |
| 13 | +/// placed here) and it's also instance-specific as a [`Store<T>`] is typically |
| 14 | +/// allocated one-per-instance. Implementations of host APIs, however, often |
| 15 | +/// want to live in a library and not be tied to any particular `T`. For example |
| 16 | +/// Wasmtime provides the `wasmtime-wasi` crates as an implementation of |
| 17 | +/// standard WASI APIs as a library, but they don't want to fix a particular `T` |
| 18 | +/// in [`Store<T>`] as embedders should be able to fill out their own `T` for |
| 19 | +/// their needs. The purpose of this trait is to enable this situation. |
| 20 | +/// |
| 21 | +/// This trait is used in `add_to_linker` functions generated by [`bindgen!`] in |
| 22 | +/// conjunction with a function pointer. It looks something along the lines of: |
| 23 | +/// |
| 24 | +/// ``` |
| 25 | +/// use wasmtime::component::{Linker, HasData}; |
| 26 | +/// |
| 27 | +/// // generated by bindgen! |
| 28 | +/// trait Host { |
| 29 | +/// // .. |
| 30 | +/// } |
| 31 | +/// |
| 32 | +/// fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>) |
| 33 | +/// where D: HasData, |
| 34 | +/// for<'a> D::Data<'a>: Host, |
| 35 | +/// { |
| 36 | +/// // ... |
| 37 | +/// # let _ = (linker, getter); |
| 38 | +/// } |
| 39 | +/// ``` |
| 40 | +/// |
| 41 | +/// Here the `D` type parameter, bounded by [`HasData`], is an used to specify |
| 42 | +/// the return type of the `getter` function provided here. The `getter` |
| 43 | +/// "projects" from `&mut T` to `D::Data<'_>`, notably enabling it to capture |
| 44 | +/// the lifetime of the `&mut T` passed in as well. |
| 45 | +/// |
| 46 | +/// The `Data` associated type here is further bounded in `add_to_linker` above |
| 47 | +/// as it must implement the traits generated by [`bindgen!`]. This means that |
| 48 | +/// `linker` is filled out with functions that, when called, first `getter` is |
| 49 | +/// invoked and then the actual function delegates to the `Host` trait |
| 50 | +/// implementation in this case. |
| 51 | +/// |
| 52 | +/// The `D` type parameter here isn't actually a runtime value, nor is it stored |
| 53 | +/// anywhere. It's purely used as a means of projecting a "generic associated |
| 54 | +/// type", here where `<'a>` is the generic argument, a lifetime. This means |
| 55 | +/// that the choice of `D` is disconnected from both `T` and `D::Data<'_>` and |
| 56 | +/// can be whatever you like. Sometimes you might need to define an empty struct |
| 57 | +/// in your project to use this, but Wasmtime also provides a convenience |
| 58 | +/// [`HasSelf`] type to avoid the need for this in some common use cases. |
| 59 | +/// |
| 60 | +/// For example, let's say you wanted to invoke the above `add_to_linker` |
| 61 | +/// function where the `T` in [`Store<T>`] directly implements the `Host` trait |
| 62 | +/// itself: |
| 63 | +/// |
| 64 | +/// # Example: `Host for T` using `Store<T>` |
| 65 | +/// |
| 66 | +/// ``` |
| 67 | +/// use wasmtime::component::{Linker, HasSelf}; |
| 68 | +/// # use wasmtime::component::HasData; |
| 69 | +/// # |
| 70 | +/// # trait Host { } |
| 71 | +/// # impl<T: Host + ?Sized> Host for &mut T {} |
| 72 | +/// # |
| 73 | +/// # fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>) |
| 74 | +/// # where D: HasData, |
| 75 | +/// # for<'a> D::Data<'a>: Host, |
| 76 | +/// # { |
| 77 | +/// # let _ = (linker, getter); |
| 78 | +/// # } |
| 79 | +/// |
| 80 | +/// struct MyStoreState { /* ... */ } |
| 81 | +/// |
| 82 | +/// impl Host for MyStoreState { |
| 83 | +/// // .. |
| 84 | +/// } |
| 85 | +/// |
| 86 | +/// fn fill_out_my_linker(linker: &mut Linker<MyStoreState>) { |
| 87 | +/// add_to_linker::<_, HasSelf<_>>(linker, |x| x) |
| 88 | +/// } |
| 89 | +/// ``` |
| 90 | +/// |
| 91 | +/// Here the `add_to_linker` invocation is annotated with `<_, HasSelf<_>>`. The |
| 92 | +/// first argument gets inferred to `MyStoreState`, and the second argument gets |
| 93 | +/// inferred to `HasSelf<MyStoreState>` This means that the projection function |
| 94 | +/// in this case, here the identity `|x| x`, is typed as |
| 95 | +/// `fn(&mut MyStoreState) -> &mut MyStoreState`. This is because the `HasData` |
| 96 | +/// implementation for `HasSelf<T>` means that we have |
| 97 | +/// `type Data<'a> = &'a mut T`. |
| 98 | +/// |
| 99 | +/// # Example: `Host for MyLibraryState` using `Store<T>` |
| 100 | +/// |
| 101 | +/// Let's say though that you instead are writing a library like WASI where you |
| 102 | +/// don't know the `T` of [`Store<T>`] ahead of time. In such a case you might |
| 103 | +/// hand-write your own `add_to_linker` wrapper that looks like this: |
| 104 | +/// |
| 105 | +/// ``` |
| 106 | +/// use wasmtime::component::{Linker, HasData}; |
| 107 | +/// # |
| 108 | +/// # trait Host { } |
| 109 | +/// # impl<T: Host + ?Sized> Host for &mut T {} |
| 110 | +/// # |
| 111 | +/// # fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>) |
| 112 | +/// # where D: HasData, |
| 113 | +/// # for<'a> D::Data<'a>: Host, |
| 114 | +/// # { |
| 115 | +/// # let _ = (linker, getter); |
| 116 | +/// # } |
| 117 | +/// |
| 118 | +/// // publicly exposed per-instance state for your library, users will |
| 119 | +/// // construct this and store it within the `T` in `Store<T>` |
| 120 | +/// pub struct MyLibraryState { /* ... */ } |
| 121 | +/// |
| 122 | +/// impl Host for MyLibraryState { |
| 123 | +/// // .. |
| 124 | +/// } |
| 125 | +/// |
| 126 | +/// // hand-written publicly exposed convenience function to add this crate's |
| 127 | +/// // component functionality to the provided linker. |
| 128 | +/// pub fn add_my_library_to_linker<T>( |
| 129 | +/// linker: &mut Linker<T>, |
| 130 | +/// f: fn(&mut T) -> &mut MyLibraryState, |
| 131 | +/// ) { |
| 132 | +/// // invoke the bindgen!-generated `add_to_linker` |
| 133 | +/// add_to_linker::<_, MyLibrary>(linker, f); |
| 134 | +/// } |
| 135 | +/// |
| 136 | +/// // Note this need not be publicly exposed, it's just a private internal |
| 137 | +/// // detail. |
| 138 | +/// struct MyLibrary; |
| 139 | +/// |
| 140 | +/// impl HasData for MyLibrary { |
| 141 | +/// type Data<'a> = &'a mut MyLibraryState; |
| 142 | +/// } |
| 143 | +/// ``` |
| 144 | +/// |
| 145 | +/// Here the `MyLibrary` type, private to this crate, has a `HasData` |
| 146 | +/// implementation which indicates that implementations of the |
| 147 | +/// `bindgen!`-generated APIs are done in terms of `MyLibraryState` |
| 148 | +/// specifically. The `add_my_library_to_linker` takes an externally-provided |
| 149 | +/// `f` closure which projects from `&mut T`, whatever data the store is using, |
| 150 | +/// to `MyLibraryState` which must be stored within the store itself. |
| 151 | +/// |
| 152 | +/// # Example: `Host for MyLibraryState<'_>` using `Store<T>` |
| 153 | +/// |
| 154 | +/// Let's say you're like the above scenario where you're writing a library but |
| 155 | +/// instead of being able to wrap up all your state for each trait |
| 156 | +/// implementation in a structure it's spread across a few structures. These |
| 157 | +/// structures may be stored in different locations inside of `Store<T>` which |
| 158 | +/// makes it difficult to wrap up in a single type and return that. Here you can |
| 159 | +/// make use of "view" types to collect a number of disjoint borrows into one |
| 160 | +/// structure: |
| 161 | +/// |
| 162 | +/// ``` |
| 163 | +/// use wasmtime::component::{Linker, HasData}; |
| 164 | +/// # |
| 165 | +/// # trait Host { } |
| 166 | +/// # impl<T: Host + ?Sized> Host for &mut T {} |
| 167 | +/// # |
| 168 | +/// # fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>) |
| 169 | +/// # where D: HasData, |
| 170 | +/// # for<'a> D::Data<'a>: Host, |
| 171 | +/// # { |
| 172 | +/// # let _ = (linker, getter); |
| 173 | +/// # } |
| 174 | +/// # struct StateA; |
| 175 | +/// # struct StateB; |
| 176 | +/// |
| 177 | +/// // Like before, this is publicly exposed, and this is a "bag of pointers" to |
| 178 | +/// // all the pieces of state necessary to implement `Host` below. |
| 179 | +/// pub struct MyLibraryState<'a> { |
| 180 | +/// pub state_a: &'a mut StateA, |
| 181 | +/// pub state_b: &'a mut StateB, |
| 182 | +/// } |
| 183 | +/// |
| 184 | +/// impl Host for MyLibraryState<'_> { |
| 185 | +/// // .. |
| 186 | +/// } |
| 187 | +/// |
| 188 | +/// pub fn add_my_library_to_linker<T>( |
| 189 | +/// linker: &mut Linker<T>, |
| 190 | +/// f: fn(&mut T) -> MyLibraryState<'_>, |
| 191 | +/// ) { |
| 192 | +/// // invoke the bindgen!-generated `add_to_linker` |
| 193 | +/// add_to_linker::<_, MyLibrary>(linker, f); |
| 194 | +/// } |
| 195 | +/// |
| 196 | +/// struct MyLibrary; |
| 197 | +/// |
| 198 | +/// impl HasData for MyLibrary { |
| 199 | +/// type Data<'a> = MyLibraryState<'a>; |
| 200 | +/// } |
| 201 | +/// ``` |
| 202 | +/// |
| 203 | +/// This is similar to the above example but shows using a lifetime parameter on |
| 204 | +/// a structure instead of using a pointer-with-a-lifetime only. Otherwise |
| 205 | +/// though this'll end up working out the same way. |
| 206 | +/// |
| 207 | +/// # Example: `Host for U: MyLibrary` using `Store<T>` |
| 208 | +/// |
| 209 | +/// Let's say you're in a situation where you're a library which wants to create |
| 210 | +/// a "simpler" trait than the `Host`-generated traits from [`bindgen!`] and |
| 211 | +/// then you want to implement `Host` in terms of this trait. This requires a |
| 212 | +/// bit more boilerplate as well as a new custom structure, but doing so looks |
| 213 | +/// like this: |
| 214 | +/// |
| 215 | +/// ``` |
| 216 | +/// use wasmtime::component::{Linker, HasData}; |
| 217 | +/// # |
| 218 | +/// # trait Host { } |
| 219 | +/// # impl<T: Host + ?Sized> Host for &mut T {} |
| 220 | +/// # |
| 221 | +/// # fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>) |
| 222 | +/// # where D: HasData, |
| 223 | +/// # for<'a> D::Data<'a>: Host, |
| 224 | +/// # { |
| 225 | +/// # let _ = (linker, getter); |
| 226 | +/// # } |
| 227 | +/// |
| 228 | +/// // This is your public trait which external users need to implement. This |
| 229 | +/// // can encapsulate any "core" functionality needed to implement |
| 230 | +/// // bindgen!-generated traits such as `Host` below. |
| 231 | +/// pub trait MyLibraryTrait { |
| 232 | +/// // ... |
| 233 | +/// } |
| 234 | +/// |
| 235 | +/// // You'll need to provide a "forwarding" implementation of this trait from |
| 236 | +/// // `&mut T` to `T` to get the below implementation to compile. |
| 237 | +/// impl<T: MyLibraryTrait + ?Sized> MyLibraryTrait for &mut T { |
| 238 | +/// // ... |
| 239 | +/// } |
| 240 | +/// |
| 241 | +/// // This is a bit of a "hack" and an unfortunate workaround, but is currently |
| 242 | +/// // used to work within the confines of orphan rules and such. This is |
| 243 | +/// // publicly exposed as the function provided below must provide access to |
| 244 | +/// // this. |
| 245 | +/// pub struct MyLibraryImpl<T>(pub T); |
| 246 | +/// |
| 247 | +/// // Here you'd implement all of `Host` in terms of `MyLibraryTrait`. |
| 248 | +/// // Functions with `&mut self` would use `self.0` to access the functionality |
| 249 | +/// // in `MyLibraryTrait`. |
| 250 | +/// impl<T: MyLibraryTrait> Host for MyLibraryImpl<T> { |
| 251 | +/// // .. |
| 252 | +/// } |
| 253 | +/// |
| 254 | +/// // optional: this avoids the need for `self.0` accessors in `Host` above, |
| 255 | +/// // but this otherwise isn't required. |
| 256 | +/// impl<T: MyLibraryTrait> MyLibraryTrait for MyLibraryImpl<T> { |
| 257 | +/// // .. |
| 258 | +/// } |
| 259 | +/// |
| 260 | +/// // Note the second type parameter on this method, `U`, which is the user's |
| 261 | +/// // implementation of `MyLibraryTrait`. Note that this additionally must |
| 262 | +/// // be bounded with `'static` here. |
| 263 | +/// pub fn add_my_library_to_linker<T, U>( |
| 264 | +/// linker: &mut Linker<T>, |
| 265 | +/// f: fn(&mut T) -> MyLibraryImpl<&mut U>, |
| 266 | +/// ) |
| 267 | +/// where U: MyLibraryTrait + 'static, |
| 268 | +/// { |
| 269 | +/// add_to_linker::<_, MyLibrary<U>>(linker, f); |
| 270 | +/// } |
| 271 | +/// |
| 272 | +/// // An adjusted definition of `MyLibrary` relative to the previous example, |
| 273 | +/// // still private, which hooks up all the types used here. |
| 274 | +/// struct MyLibrary<U>(U); |
| 275 | +/// |
| 276 | +/// impl<U: 'static> HasData for MyLibrary<U> { |
| 277 | +/// type Data<'a> = MyLibraryImpl<&'a mut U>; |
| 278 | +/// } |
| 279 | +/// ``` |
| 280 | +/// |
| 281 | +/// This iteration of implementing component-interfaces-as-a-library is |
| 282 | +/// unfortunately relatively verbose an unintuitive at this time. We're always |
| 283 | +/// keen on improving this though, so if you've got ideas of how to improve this |
| 284 | +/// please let us know! |
| 285 | +/// |
| 286 | +/// [`bindgen!`]: super::bindgen |
| 287 | +/// [`Linker`]: super::Linker |
| 288 | +/// [`Store<T>`]: crate::Store |
2 | 289 | pub trait HasData: 'static { |
3 | | - /// TODO |
| 290 | + /// The data associated with this trait implementation, chiefly used as a |
| 291 | + /// generic associated type to allow plumbing the `'a` lifetime into the |
| 292 | + /// definition here. |
| 293 | + /// |
| 294 | + /// See the trait documentation for more examples. |
4 | 295 | type Data<'a>; |
5 | 296 | } |
6 | 297 |
|
7 | | -/// TODO |
| 298 | +/// A convenience implementation of the [`HasData`] trait when the data |
| 299 | +/// associated with an implementation is `&mut T`. |
| 300 | +/// |
| 301 | +/// For more examples on using this see the [`HasData`] trait. |
8 | 302 | pub struct HasSelf<T: ?Sized>(core::marker::PhantomData<T>); |
9 | 303 |
|
10 | 304 | impl<T: ?Sized + 'static> HasData for HasSelf<T> { |
|
0 commit comments