derive_tokio_io/lib.rs
1//! Derive [`AsyncRead`] and [`AsyncWrite`].
2//!
3//! # Usage
4//!
5//! If the struct has only one field, [`AsyncRead`] and [`AsyncWrite`] are derived
6//! for that field.
7//!
8//! ```rust
9//! use derive_tokio_io::{AsyncRead, AsyncWrite};
10//! use tokio::net::TcpStream;
11//!
12//! #[derive(AsyncRead, AsyncWrite)]
13//! struct Wrapper {
14//! stream: TcpStream,
15//! }
16//! ```
17//!
18//! Generics are supported.
19//!
20//! ```rust
21//! use derive_tokio_io::{AsyncRead, AsyncWrite};
22//!
23//! #[derive(AsyncRead, AsyncWrite)]
24//! struct Wrapper<IO> {
25//! stream: IO,
26//! }
27//! ```
28//!
29//! If the struct has multiple fields, `#[async_read]` and `#[async_write]`
30//! must be used once for any field.
31//!
32//! ```rust
33//! use derive_tokio_io::{AsyncRead, AsyncWrite};
34//!
35//! #[derive(AsyncRead, AsyncWrite)]
36//! struct Wrapper<R, W> {
37//! #[async_read]
38//! reader: R,
39//! #[async_write]
40//! writer: W,
41//! }
42//! ```
43//!
44//! Everything works the same way for tuple structs.
45//!
46//! ```rust
47//! use derive_tokio_io::{AsyncRead, AsyncWrite};
48//!
49//! #[derive(AsyncRead, AsyncWrite)]
50//! struct Wrapper<R, W>(
51//! #[async_read]
52//! R,
53//! #[async_write]
54//! W,
55//! );
56//! ```
57//!
58//! [`AsyncRead`]: https://docs.rs/tokio/1/tokio/io/trait.AsyncRead.html
59//! [`AsyncWrite`]: https://docs.rs/tokio/1/tokio/io/trait.AsyncWrite.html
60
61use async_read::expand_async_read;
62use async_write::expand_async_write;
63use proc_macro::TokenStream;
64use syn::{parse_macro_input, DeriveInput};
65
66mod async_read;
67mod async_write;
68mod parse;
69
70/// Derive an implementation of [`AsyncRead`].
71///
72/// # Example
73///
74/// ```rust
75/// # use derive_tokio_io::AsyncRead;
76/// #[derive(AsyncRead)]
77/// struct ReadWrapper<R> {
78/// reader: R,
79/// }
80/// ```
81///
82/// ```rust
83/// # use derive_tokio_io::AsyncRead;
84/// #[derive(AsyncRead)]
85/// struct ReadWrapper<R> {
86/// #[async_read]
87/// reader: R,
88/// some_field: String,
89/// }
90/// ```
91///
92/// [`AsyncRead`]: https://docs.rs/tokio/1/tokio/io/trait.AsyncRead.html
93#[proc_macro_derive(AsyncRead, attributes(async_read))]
94pub fn derive_async_read(input: TokenStream) -> TokenStream {
95 let input = parse_macro_input!(input as DeriveInput);
96
97 expand_async_read(input)
98 .unwrap_or_else(syn::Error::into_compile_error)
99 .into()
100}
101
102/// Derive an implementation of [`AsyncWrite`].
103///
104/// # Example
105///
106/// ```rust
107/// # use derive_tokio_io::AsyncWrite;
108/// #[derive(AsyncWrite)]
109/// struct WriteWrapper<W> {
110/// writer: W,
111/// }
112/// ```
113///
114/// ```rust
115/// # use derive_tokio_io::AsyncWrite;
116/// #[derive(AsyncWrite)]
117/// struct WriteWrapper<W> {
118/// #[async_write]
119/// writer: W,
120/// some_field: String,
121/// }
122/// ```
123///
124/// [`AsyncWrite`]: https://docs.rs/tokio/1/tokio/io/trait.AsyncWrite.html
125#[proc_macro_derive(AsyncWrite, attributes(async_write))]
126pub fn derive_async_write(input: TokenStream) -> TokenStream {
127 let input = parse_macro_input!(input as DeriveInput);
128
129 expand_async_write(input)
130 .unwrap_or_else(syn::Error::into_compile_error)
131 .into()
132}
133
134#[cfg(test)]
135mod tests {
136 #[test]
137 fn ui() {
138 let t = trybuild::TestCases::new();
139 t.pass("tests/pass/*.rs");
140 }
141}