/// A trait used as part of [`bindgen!`] to indicate a `Data<'_>` payload that
/// implements some host bindings traits.
///
/// The purpose of the [`bindgen!`] macro is to define Rust traits that the host
/// can implement to fulfill WIT functions imported from the host into a
/// component. The [`bindgen!`] macro then additionally generates a function
/// which takes a [`Linker`] and an implementation of the traits and fills out
/// the [`Linker`]. This trait, [`HasData`], is used in this process of filling
/// out the [`Linker`] for some WIT interfaces.
///
/// Wasmtime's [`Store<T>`] type is the home for all per-instance state.
/// Notably the `T` here is generic (the Wasmtime library allows any type to be
/// placed here) and it's also instance-specific as a [`Store<T>`] is typically
/// allocated one-per-instance. Implementations of host APIs, however, often
/// want to live in a library and not be tied to any particular `T`. For example
/// Wasmtime provides the `wasmtime-wasi` crates as an implementation of
/// standard WASI APIs as a library, but they don't want to fix a particular `T`
/// in [`Store<T>`] as embedders should be able to fill out their own `T` for
/// their needs. The purpose of this trait is to enable this situation.
///
/// This trait is used in `add_to_linker` functions generated by [`bindgen!`] in
/// conjunction with a function pointer. It looks something along the lines of:
///
/// ```
/// use wasmtime::component::{Linker, HasData};
///
/// // generated by bindgen!
/// trait Host {
///     // ..
/// }
///
/// fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>)
///     where D: HasData,
///           for<'a> D::Data<'a>: Host,
/// {
///     // ...
/// # let _ = (linker, getter);
/// }
/// ```
///
/// Here the `D` type parameter, bounded by [`HasData`], is used to specify
/// the return type of the `getter` function provided here. The `getter`
/// "projects" from `&mut T` to `D::Data<'_>`, notably enabling it to capture
/// the lifetime of the `&mut T` passed in as well.
///
/// The `Data` associated type here is further bounded in `add_to_linker` above
/// as it must implement the traits generated by [`bindgen!`]. This means that
/// `linker` is filled out with functions that, when called, first `getter` is
/// invoked and then the actual function delegates to the `Host` trait
/// implementation in this case.
///
/// The `D` type parameter here isn't actually a runtime value, nor is it stored
/// anywhere. It's purely used as a means of projecting a "generic associated
/// type", here where `<'a>` is the generic argument, a lifetime. This means
/// that the choice of `D` is disconnected from both `T` and `D::Data<'_>` and
/// can be whatever you like. Sometimes you might need to define an empty struct
/// in your project to use this, but Wasmtime also provides a convenience
/// [`HasSelf`] type to avoid the need for this in some common use cases.
///
/// # Example: `Host for T` using `Store<T>`
///
/// Let's say you wanted to invoke the above `add_to_linker` function where the
/// `T` in [`Store<T>`] directly implements the `Host` trait itself:
///
/// ```
/// use wasmtime::component::{Linker, HasSelf};
/// # use wasmtime::component::HasData;
/// #
/// # trait Host { }
/// # impl<T: Host + ?Sized> Host for &mut T {}
/// #
/// # fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>)
/// #     where D: HasData,
/// #           for<'a> D::Data<'a>: Host,
/// # {
/// # let _ = (linker, getter);
/// # }
///
/// struct MyStoreState { /* ... */ }
///
/// impl Host for MyStoreState {
///     // ..
/// }
///
/// fn fill_out_my_linker(linker: &mut Linker<MyStoreState>) {
///     add_to_linker::<_, HasSelf<_>>(linker, |x| x)
/// }
/// ```
///
/// Here the `add_to_linker` invocation is annotated with `<_, HasSelf<_>>`. The
/// first argument gets inferred to `MyStoreState`, and the second argument gets
/// inferred to `HasSelf<MyStoreState>` This means that the projection function
/// in this case, here the identity `|x| x`, is typed as
/// `fn(&mut MyStoreState) -> &mut MyStoreState`. This is because the `HasData`
/// implementation for `HasSelf<T>` means that we have
/// `type Data<'a> = &'a mut T`.
///
/// # Example: `Host for MyLibraryState` using `Store<T>`
///
/// Let's say though that you instead are writing a library like WASI where you
/// don't know the `T` of [`Store<T>`] ahead of time. In such a case you might
/// hand-write your own `add_to_linker` wrapper that looks like this:
///
/// ```
/// use wasmtime::component::{Linker, HasData};
/// #
/// # trait Host { }
/// # impl<T: Host + ?Sized> Host for &mut T {}
/// #
/// # fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>)
/// #     where D: HasData,
/// #           for<'a> D::Data<'a>: Host,
/// # {
/// # let _ = (linker, getter);
/// # }
///
/// // publicly exposed per-instance state for your library, users will
/// // construct this and store it within the `T` in `Store<T>`
/// pub struct MyLibraryState { /* ... */ }
///
/// impl Host for MyLibraryState {
///     // ..
/// }
///
/// // hand-written publicly exposed convenience function to add this crate's
/// // component functionality to the provided linker.
/// pub fn add_my_library_to_linker<T>(
///     linker: &mut Linker<T>,
///     f: fn(&mut T) -> &mut MyLibraryState,
/// ) {
///     // invoke the bindgen!-generated `add_to_linker`
///     add_to_linker::<_, MyLibrary>(linker, f);
/// }
///
/// // Note this need not be publicly exposed, it's just a private internal
/// // detail.
/// struct MyLibrary;
///
/// impl HasData for MyLibrary {
///     type Data<'a> = &'a mut MyLibraryState;
/// }
/// ```
///
/// Here the `MyLibrary` type, private to this crate, has a `HasData`
/// implementation which indicates that implementations of the
/// `bindgen!`-generated APIs are done in terms of `MyLibraryState`
/// specifically. The `add_my_library_to_linker` takes an externally-provided
/// `f` closure which projects from `&mut T`, whatever data the store is using,
/// to `MyLibraryState` which must be stored within the store itself.
///
/// # Example: `Host for MyLibraryState<'_>` using `Store<T>`
///
/// Let's say you're like the above scenario where you're writing a library but
/// instead of being able to wrap up all your state for each trait
/// implementation in a structure it's spread across a few structures. These
/// structures may be stored in different locations inside of `Store<T>` which
/// makes it difficult to wrap up in a single type and return that. Here you can
/// make use of "view" types to collect a number of disjoint borrows into one
/// structure:
///
/// ```
/// use wasmtime::component::{Linker, HasData};
/// #
/// # trait Host { }
/// # impl<T: Host + ?Sized> Host for &mut T {}
/// #
/// # fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>)
/// #     where D: HasData,
/// #           for<'a> D::Data<'a>: Host,
/// # {
/// # let _ = (linker, getter);
/// # }
/// # struct StateA;
/// # struct StateB;
///
/// // Like before, this is publicly exposed, and this is a "bag of pointers" to
/// // all the pieces of state necessary to implement `Host` below.
/// pub struct MyLibraryState<'a> {
///     pub state_a: &'a mut StateA,
///     pub state_b: &'a mut StateB,
/// }
///
/// impl Host for MyLibraryState<'_> {
///     // ..
/// }
///
/// pub fn add_my_library_to_linker<T>(
///     linker: &mut Linker<T>,
///     f: fn(&mut T) -> MyLibraryState<'_>,
/// ) {
///     // invoke the bindgen!-generated `add_to_linker`
///     add_to_linker::<_, MyLibrary>(linker, f);
/// }
///
/// struct MyLibrary;
///
/// impl HasData for MyLibrary {
///     type Data<'a> = MyLibraryState<'a>;
/// }
/// ```
///
/// This is similar to the above example but shows using a lifetime parameter on
/// a structure instead of using a pointer-with-a-lifetime only. Otherwise
/// though this'll end up working out the same way.
///
/// # Example: `Host for U: MyLibrary` using `Store<T>`
///
/// Let's say you're in a situation where you're a library which wants to create
/// a "simpler" trait than the `Host`-generated traits from [`bindgen!`] and
/// then you want to implement `Host` in terms of this trait. This requires a
/// bit more boilerplate as well as a new custom structure, but doing so looks
/// like this:
///
/// ```
/// use wasmtime::component::{Linker, HasData};
/// #
/// # trait Host { }
/// # impl<T: Host + ?Sized> Host for &mut T {}
/// #
/// # fn add_to_linker<T, D>(linker: &mut Linker<T>, getter: fn(&mut T) -> D::Data<'_>)
/// #     where D: HasData,
/// #           for<'a> D::Data<'a>: Host,
/// # {
/// # let _ = (linker, getter);
/// # }
///
/// // This is your public trait which external users need to implement. This
/// // can encapsulate any "core" functionality needed to implement
/// // bindgen!-generated traits such as `Host` below.
/// pub trait MyLibraryTrait {
///     // ...
/// }
///
/// // You'll need to provide a "forwarding" implementation of this trait from
/// // `&mut T` to `T` to get the below implementation to compile.
/// impl<T: MyLibraryTrait + ?Sized> MyLibraryTrait for &mut T {
///     // ...
/// }
///
/// // This is a bit of a "hack" and an unfortunate workaround, but is currently
/// // used to work within the confines of orphan rules and such. This is
/// // publicly exposed as the function provided below must provide access to
/// // this.
/// pub struct MyLibraryImpl<T>(pub T);
///
/// // Here you'd implement all of `Host` in terms of `MyLibraryTrait`.
/// // Functions with `&mut self` would use `self.0` to access the functionality
/// // in `MyLibraryTrait`.
/// impl<T: MyLibraryTrait> Host for MyLibraryImpl<T> {
///     // ..
/// }
///
/// // optional: this avoids the need for `self.0` accessors in `Host` above,
/// // but this otherwise isn't required.
/// impl<T: MyLibraryTrait> MyLibraryTrait for MyLibraryImpl<T> {
///     // ..
/// }
///
/// // Note the second type parameter on this method, `U`, which is the user's
/// // implementation of `MyLibraryTrait`. Note that this additionally must
/// // be bounded with `'static` here.
/// pub fn add_my_library_to_linker<T, U>(
///     linker: &mut Linker<T>,
///     f: fn(&mut T) -> MyLibraryImpl<&mut U>,
/// )
///     where U: MyLibraryTrait + 'static,
/// {
///     add_to_linker::<_, MyLibrary<U>>(linker, f);
/// }
///
/// // An adjusted definition of `MyLibrary` relative to the previous example,
/// // still private, which hooks up all the types used here.
/// struct MyLibrary<U>(U);
///
/// impl<U: 'static> HasData for MyLibrary<U> {
///     type Data<'a> = MyLibraryImpl<&'a mut U>;
/// }
/// ```
///
/// This iteration of implementing component-interfaces-as-a-library is
/// unfortunately relatively verbose and unintuitive at this time. We're always
/// keen on improving this though, so if you've got ideas of how to improve this
/// please let us know!
///
/// [`bindgen!`]: super::bindgen
/// [`Linker`]: super::Linker
/// [`Store<T>`]: crate::Store
pub trait HasData: 'static {
    /// The data associated with this trait implementation, chiefly used as a
    /// generic associated type to allow plumbing the `'a` lifetime into the
    /// definition here.
    ///
    /// See the trait documentation for more examples.
    type Data<'a>;
}

/// A convenience implementation of the [`HasData`] trait when the data
/// associated with an implementation is `&mut T`.
///
/// For more examples on using this see the [`HasData`] trait.
pub struct HasSelf<T: ?Sized>(core::marker::PhantomData<T>);

impl<T: ?Sized + 'static> HasData for HasSelf<T> {
    type Data<'a> = &'a mut T;
}
