//! Auto-generated bindings for WASI interfaces.
//!
//! This module contains the output of the [`bindgen!`] macro when run over
//! the `wasi:cli/imports` world.
//!
//! [`bindgen!`]: https://docs.rs/wasmtime/latest/wasmtime/component/macro.bindgen.html
//!
//! # Examples
//!
//! If you have a WIT world which refers to WASI interfaces you probably want to
//! use this modules's bindings rather than generate fresh bindings. That can be
//! done using the `with` option to [`bindgen!`]:
//!
//! ```rust
//! use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
//! use wasmtime::{Result, Engine, Config};
//! use wasmtime::component::{Linker, HasSelf, ResourceTable};
//!
//! wasmtime::component::bindgen!({
//!     inline: "
//!         package example:wasi;
//!
//!         // An example of extending the `wasi:cli/command` world with a
//!         // custom host interface.
//!         world my-world {
//!             include wasi:cli/command@0.3.0;
//!
//!             import custom-host;
//!         }
//!
//!         interface custom-host {
//!             my-custom-function: func();
//!         }
//!     ",
//!     path: "src/p3/wit",
//!     with: {
//!         "wasi": wasmtime_wasi::p3::bindings,
//!     },
//!     require_store_data_send: true,
//! });
//!
//! struct MyState {
//!     ctx: WasiCtx,
//!     table: ResourceTable,
//! }
//!
//! impl example::wasi::custom_host::Host for MyState {
//!     fn my_custom_function(&mut self) {
//!         // ..
//!     }
//! }
//!
//! impl WasiView for MyState {
//!     fn ctx(&mut self) -> WasiCtxView<'_> {
//!         WasiCtxView{
//!             ctx: &mut self.ctx,
//!             table: &mut self.table,
//!         }
//!     }
//! }
//!
//! fn main() -> Result<()> {
//!     let mut config = Config::default();
//!     config.wasm_component_model_async(true);
//!     let engine = Engine::new(&config)?;
//!     let mut linker: Linker<MyState> = Linker::new(&engine);
//!     wasmtime_wasi::p3::add_to_linker(&mut linker)?;
//!     example::wasi::custom_host::add_to_linker::<_, HasSelf<_>>(&mut linker, |state| state)?;
//!
//!     // .. use `Linker` to instantiate component ...
//!
//!     Ok(())
//! }
//! ```

mod generated {
    wasmtime::component::bindgen!({
        path: "src/p3/wit",
        world: "wasi:cli/command",
        imports: {
            "wasi:cli/stdin": store | tracing | trappable,
            "wasi:cli/stdout": store | tracing | trappable,
            "wasi:cli/stderr": store | tracing | trappable,
            "wasi:filesystem/types.[method]descriptor.read-via-stream": store | tracing | trappable,
            "wasi:filesystem/types.[method]descriptor.write-via-stream": store | tracing | trappable,
            "wasi:filesystem/types.[method]descriptor.append-via-stream": store | tracing | trappable,
            "wasi:filesystem/types.[method]descriptor.read-directory": store | tracing | trappable,
            "wasi:sockets/types.[method]tcp-socket.bind": async | tracing | trappable,
            "wasi:sockets/types.[method]tcp-socket.listen":  store | tracing | trappable,
            "wasi:sockets/types.[method]tcp-socket.send": store | tracing | trappable,
            "wasi:sockets/types.[method]tcp-socket.receive": store | tracing | trappable,
            "wasi:sockets/types.[method]udp-socket.bind": async | tracing | trappable,
            "wasi:sockets/types.[method]udp-socket.connect": async | tracing | trappable,
            default: tracing | trappable,
        },
        exports: { default: async | store },
        with: {
            "wasi:cli/terminal-input.terminal-input": crate::p3::cli::TerminalInput,
            "wasi:cli/terminal-output.terminal-output": crate::p3::cli::TerminalOutput,
            "wasi:filesystem/types.descriptor": crate::filesystem::Descriptor,
            "wasi:sockets/types.tcp-socket": crate::sockets::TcpSocket,
            "wasi:sockets/types.udp-socket": crate::sockets::UdpSocket,
        },
        trappable_error_type: {
            "wasi:filesystem/types.error-code" => crate::p3::filesystem::FilesystemError,
            "wasi:sockets/types.error-code" => crate::p3::sockets::SocketError,
        },
    });
}
pub use self::generated::LinkOptions;
pub use self::generated::exports;
pub use self::generated::wasi::*;

/// Bindings to execute and run a `wasi:cli/command`.
///
/// This structure is automatically generated by `bindgen!`.
///
/// This can be used for a more "typed" view of executing a command component
/// through the [`Command::wasi_cli_run`] method plus
/// [`Guest::call_run`](exports::wasi::cli::run::Guest::call_run).
///
/// # Examples
///
/// ```no_run
/// use wasmtime::{Engine, Result, Store, Config};
/// use wasmtime::component::{Component, Linker, ResourceTable};
/// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
/// use wasmtime_wasi::p3::bindings::Command;
///
/// // This example is an example shim of executing a component based on the
/// // command line arguments provided to this program.
/// #[tokio::main]
/// async fn main() -> Result<()> {
///     let args = std::env::args().skip(1).collect::<Vec<_>>();
///
///     // Configure and create `Engine`
///     let mut config = Config::new();
///     config.wasm_component_model_async(true);
///     let engine = Engine::new(&config)?;
///
///     // Configure a `Linker` with WASI, compile a component based on
///     // command line arguments, and then pre-instantiate it.
///     let mut linker = Linker::<MyState>::new(&engine);
///     wasmtime_wasi::p3::add_to_linker(&mut linker)?;
///     let component = Component::from_file(&engine, &args[0])?;
///
///
///     // Configure a `WasiCtx` based on this program's environment. Then
///     // build a `Store` to instantiate into.
///     let mut builder = WasiCtx::builder();
///     builder.inherit_stdio().inherit_env().args(&args);
///     let mut store = Store::new(
///         &engine,
///         MyState {
///             ctx: builder.build(),
///             table: ResourceTable::default(),
///         },
///     );
///
///     // Instantiate the component and we're off to the races.
///     let command = Command::instantiate_async(&mut store, &component, &linker).await?;
///     let program_result = store.run_concurrent(async move |store| {
///         command.wasi_cli_run().call_run(store).await
///     }).await??;
///     match program_result {
///         Ok(()) => Ok(()),
///         Err(()) => std::process::exit(1),
///     }
/// }
///
/// struct MyState {
///     ctx: WasiCtx,
///     table: ResourceTable,
/// }
///
/// impl WasiView for MyState {
///     fn ctx(&mut self) -> WasiCtxView<'_> {
///         WasiCtxView{
///             ctx: &mut self.ctx,
///             table: &mut self.table,
///         }
///     }
/// }
/// ```
///
/// ---
pub use self::generated::Command;

/// Pre-instantiated analog of [`Command`]
///
/// This can be used to front-load work such as export lookup before
/// instantiation.
///
/// # Examples
///
/// ```no_run
/// use wasmtime::{Engine, Result, Store, Config};
/// use wasmtime::component::{Linker, Component, ResourceTable};
/// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
/// use wasmtime_wasi::p3::bindings::CommandPre;
///
/// // This example is an example shim of executing a component based on the
/// // command line arguments provided to this program.
/// #[tokio::main]
/// async fn main() -> Result<()> {
///     let args = std::env::args().skip(1).collect::<Vec<_>>();
///
///     // Configure and create `Engine`
///     let mut config = Config::new();
///     config.wasm_component_model_async(true);
///     let engine = Engine::new(&config)?;
///
///     // Configure a `Linker` with WASI, compile a component based on
///     // command line arguments, and then pre-instantiate it.
///     let mut linker = Linker::<MyState>::new(&engine);
///     wasmtime_wasi::p3::add_to_linker(&mut linker)?;
///     let component = Component::from_file(&engine, &args[0])?;
///     let pre = CommandPre::new(linker.instantiate_pre(&component)?)?;
///
///
///     // Configure a `WasiCtx` based on this program's environment. Then
///     // build a `Store` to instantiate into.
///     let mut builder = WasiCtx::builder();
///     builder.inherit_stdio().inherit_env().args(&args);
///     let mut store = Store::new(
///         &engine,
///         MyState {
///             ctx: builder.build(),
///             table: ResourceTable::default(),
///         },
///     );
///
///     // Instantiate the component and we're off to the races.
///     let command = pre.instantiate_async(&mut store).await?;
///     // TODO: Construct an accessor from `store` to call `run`
///     // https://github.com/bytecodealliance/wasmtime/issues/11249
///     //let program_result = command.wasi_cli_run().call_run(&mut store).await?;
///     let program_result = todo!();
///     match program_result {
///         Ok(()) => Ok(()),
///         Err(()) => std::process::exit(1),
///     }
/// }
///
/// struct MyState {
///     ctx: WasiCtx,
///     table: ResourceTable,
/// }
///
/// impl WasiView for MyState {
///     fn ctx(&mut self) -> WasiCtxView<'_> {
///         WasiCtxView{
///             ctx: &mut self.ctx,
///             table: &mut self.table,
///         }
///     }
/// }
/// ```
///
/// ---
// TODO: Make this public, once `CommandPre` can be used for
// calling exports
// https://github.com/bytecodealliance/wasmtime/issues/11249
#[doc(hidden)]
pub use self::generated::CommandPre;

pub use self::generated::CommandIndices;
