async_convert/
lib.rs

1//! Async `TryFrom`/`TryInto` traits.
2//!
3//! # Why
4//!
5//! In async-std we created async versions of `FromStream`, `IntoStream`, and
6//! `Iterator::collect`. These traits represent conversions from one type to
7//! another. But the canonical way of performing this conversion is through the
8//! `TryFrom` and `TryInto` traits.
9//!
10//! For example when deserializing some `MyBody` from a `Request`, you will want
11//! to declare a `TryFrom<Request> for MyBody` which consumes the bytes in the
12//! request and tries to create the body. This operation is fallible, and when
13//! writing async code also needs to be async.
14//!
15//! This crate provides traits for that, through the
16//! [`async_trait`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html)
17//! crate. This is an experiment, but we'll likely want to extend `async-std`
18//! with this at some point too.
19//!
20//! # Examples
21//!
22//! ```
23//! use async_convert::{async_trait, TryFrom};
24//!
25//! struct GreaterThanZero(i32);
26//!
27//! #[async_trait]
28//! impl TryFrom<i32> for GreaterThanZero {
29//!     type Error = &'static str;
30//!
31//!     async fn try_from(value: i32) -> Result<Self, Self::Error> {
32//!         // pretend we're actually doing async IO here instead.
33//!         if value <= 0 {
34//!             Err("GreaterThanZero only accepts value superior than zero!")
35//!         } else {
36//!             Ok(GreaterThanZero(value))
37//!         }
38//!     }
39//! }
40//! ```
41
42#![forbid(unsafe_code, future_incompatible, rust_2018_idioms)]
43#![deny(missing_debug_implementations, nonstandard_style)]
44#![warn(missing_docs, rustdoc::missing_doc_code_examples, unreachable_pub)]
45
46pub use async_trait::async_trait;
47
48/// A shared prelude.
49pub mod prelude {
50    pub use super::TryFrom as _;
51    pub use super::TryInto as _;
52}
53
54/// Simple and safe type conversions that may fail in a controlled
55/// way under some circumstances. It is the reciprocal of [`TryInto`].
56///
57/// This is useful when you are doing a type conversion that may
58/// trivially succeed but may also need special handling.
59/// For example, there is no way to convert an [`i64`] into an [`i32`]
60/// using the [`From`] trait, because an [`i64`] may contain a value
61/// that an [`i32`] cannot represent and so the conversion would lose data.
62/// This might be handled by truncating the [`i64`] to an [`i32`] (essentially
63/// giving the [`i64`]'s value modulo [`i32::MAX`]) or by simply returning
64/// [`i32::MAX`], or by some other method.  The [`From`] trait is intended
65/// for perfect conversions, so the `TryFrom` trait informs the
66/// programmer when a type conversion could go bad and lets them
67/// decide how to handle it.
68#[async_trait]
69pub trait TryFrom<T>: Sized {
70    /// The type returned in the event of a conversion error.
71    type Error;
72
73    /// Performs the conversion.
74    async fn try_from(value: T) -> Result<Self, Self::Error>;
75}
76
77/// An attempted conversion that consumes `self`, which may or may not be
78/// expensive.
79///
80/// Library authors should usually not directly implement this trait,
81/// but should prefer implementing the [`TryFrom`] trait, which offers
82/// greater flexibility and provides an equivalent `TryInto`
83/// implementation for free, thanks to a blanket implementation in the
84/// standard library. For more information on this, see the
85/// documentation for [`Into`].
86///
87/// # Implementing `TryInto`
88///
89/// This suffers the same restrictions and reasoning as implementing
90/// [`Into`], see there for details.
91#[async_trait(?Send)]
92pub trait TryInto<T>: Sized {
93    /// The type returned in the event of a conversion error.
94    type Error;
95
96    /// Performs the conversion.
97    async fn try_into(self) -> Result<T, Self::Error>;
98}
99
100// TryFrom implies TryInto
101#[async_trait(?Send)]
102impl<T, U> TryInto<U> for T
103where
104    U: TryFrom<T>,
105{
106    type Error = U::Error;
107
108    async fn try_into(self) -> Result<U, U::Error> {
109        U::try_from(self).await
110    }
111}