rtx 0.1.0

RTx is a zero-cost runtime-abstraction intended for use by Rust libraries to enable the Freedom of Choice between asynchronous runtimes.
//! A facade that provides an efficient, unified API for async I/O and task management,
//! as well as blocking I/O where applicable.
//! Intended for use by other library crates which need async I/O but want to remain runtime-agnostic,
//! such as [SQLx](https://github.com/launchbadge/sqlx) <sup>(shameless plug)</sup>.
//!
//! ## Usage
//!
//! The types and functions in this crate are meant to be, more or less,
//! drop-in replacements for their counterparts in Tokio and `async-std`.
//! The `rtx` crate will pick the correct runtime to use automatically,
//! assuming the correct features are enabled.
//!
//! The overhead is intended to be as small as possible; if only one runtime feature is enabled,
//! the performance should be identical to using that runtime directly.
//!
//! **Library crates: do not enable the `tokio` or `async-std` features directly.**
//! Instead, either forward those features through your `Cargo.toml`, or instruct
//! your users to depend on `rtx` directly and enable the feature for their chosen runtime.
//!
//! #### Forwarded features example (recommended for best user experience)
//! Add this to your crate's `Cargo.toml`:
//! ```toml,ignore
//! [dependencies]
//! rtx = "0.1"
//!
//! [features]
//! tokio = ["rtx/tokio"]
//! async-std ["rtx/async-std"]
//! ```
//! and then instruct users to enable the `tokio` or `async-std` feature of your crate,
//! corresponding to their chosen runtime.
//!
//! This has the advantage of allowing you to upgrade `rtx` at will without breaking downstream
//! consumers.
//!
//! #### Non-forwarded features example (simpler but less optimal user experience)
//! Simply instruct your users to add this to their `Cargo.toml`:
//!
//! ```toml,ignore
//! [dependencies]
//! ## if using `tokio`
//! rtx = { version = "0.1", features = ["tokio"]
//! ## if using `async-std`
//! rtx = { version = "0.1", features = ["async-std"]
//! ```
//!
//! This simplifies your crate's features at the expense of involving `rtx` in your semantic
//! versioning, as your users will need to keep their `rtx` version in sync with yours, and so
//! non-backwards-compatible upgrades to `rtx`, e.g. `0.1.0` to `0.2.0`, must be considered a
//! breaking change to your crate.
//!
//! ## How it Works
//! Unlike the previous incarnation of this crate, `sqlx-rt`, the runtime features are **not**
//! mutually exclusive.
//!
//! When you call a free function or a constructor-like method of a type,
//! it internally picks the correct underlying function for the context.
//!
//! For example, when you call [`net::TcpStream::connect()`]:
//!
//! * if the `tokio` feature is enabled and a Tokio context is active
//!   <sup><a href="#how-works-1">(1)</a></sup>, it calls `tokio::net::TcpStream::connect()`.
//! * or, if the `async-std` feature is enabled, it calls `async_std::net::TcpStream::connect()`
//!   <sup><a href="#how-works-2">(2)</a></sup>
//! * otherwise, it panics.<sup><a href="#how-works-3">(3)</a></sup>
//!
//! However, once a type has been instantiated in a particular runtime, that instance will only
//! use that runtime. This is to limit branching in hot code paths when both the `tokio`
//! and `async-std` features are enabled<sup><a href="#how-works-4">(4)</a></sup>.
//! **Thus, an instance of a type like [`net::TcpStream`] created in a Tokio runtime
//! will likely panic if sent to and used in a task in the `async-std` runtime.**
//! You should still avoid mixing and matching runtimes if at all possible.
//!
//! Some types also support blocking operations, but those will use separate methods with
//! `_blocking` in the name. If a type is constructed in blocking mode but you attempt to use
//! an async method on it, it will panic. Conversely, calling a blocking method on a type
//! constructed in non-blocking mode may either return `std::io::ErrorKind::WouldBlock` or panic,
//! depending on what makes sense for the context. The exact behavior will be documented on the
//! impl or method in question.
//!
//! <sup id="how-works-1">(1) via `tokio::runtime::Handle::try_current()`</sup>  
//! <sup id="how-works-2">
//!     (2) actually, `async_io::Async::<std::net::TcpStream>::connect()`
//!     because `async-std`'s version doesn't support polling for readiness which we needed for our
//!     use-cases, but [
//!         `async_std::net::TcpStream` is also but a thin facade around the former anyway.
//!     ](https://docs.rs/async-std/1.10.0/src/async_std/net/tcp/stream.rs.html#49-51)
//! </sup>  
//! <sup id="how-works-3">
//!     (3) similar to how Tokio's types panic if a runtime is not available.
//! </sup>  
//! <sup id="how-works-4">
//!     (4) also, not every type has a way to jump back and forth between runtimes.
//!     `TcpStream` can be converted via `std::net::TcpStream` as an intermediate, but most types
//!     won't support something like that.
//! </sup>
//!
//! ### Note: API is Incomplete
//! The current API is the bare minimum to suit our needs. If there's something missing that you
//! need, feel free to open an issue, or ideally a PR.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(
    any(
        not(feature = "blocking"),
        not(feature = "tokio"),
        not(feature = "async-std")
    ),
    allow(unused)
)]
#![warn(future_incompatible)]
#![warn(rust_2018_compatibility)]
#![warn(rust_2018_idioms)]
#![warn(rust_2021_compatibility)]
#![warn(clippy::cargo)]

#[cfg(feature = "tokio")]
extern crate tokio_ as tokio;

#[cfg(feature = "async-std")]
extern crate async_std_ as async_std;

#[macro_use]
mod runtime;

#[cfg(feature = "async")]
mod future;

pub mod io;
pub mod net;

#[cfg(feature = "async")]
pub mod task;