1#![doc(test(
37 no_crate_inject,
38 attr(
39 deny(warnings, rust_2018_idioms, single_use_lifetimes),
40 allow(dead_code, unused_variables)
41 )
42))]
43#![forbid(unsafe_code)]
44#![warn(future_incompatible, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
45#![warn(clippy::all, clippy::default_trait_access)]
46
47#[allow(unused_extern_crates)]
49extern crate proc_macro;
50
51use derive_utils::{derive_trait, quick_derive};
52use proc_macro::TokenStream;
53use quote::{format_ident, quote};
54use syn::{parse_macro_input, parse_quote, Ident};
55
56fn default_crate_name() -> (Ident, Option<String>) {
57 (format_ident!("futures"), None)
58}
59
60#[cfg(feature = "renamed")]
61fn crate_name(crate_names: &[&str]) -> (Ident, Option<String>) {
62 use find_crate::Manifest;
63
64 let manifest = match Manifest::new().ok() {
65 Some(manifest) => manifest,
66 None => return default_crate_name(),
67 };
68
69 manifest
70 .find2(|name, version| {
71 if name == "futures" {
72 let mut pieces = version.split('.');
73 (|| pieces.next()?.parse().ok())() == Some(3)
74 } else {
75 crate_names.iter().any(|s| *s == name)
76 }
77 })
78 .map_or_else(default_crate_name, |package| {
79 if package.is_original() {
80 (format_ident!("{}", package.name), None)
81 } else {
82 (format_ident!("{}", &package.name), Some(package.original_name().to_owned()))
83 }
84 })
85}
86
87#[cfg(not(feature = "renamed"))]
88fn crate_name(_: &[&str]) -> (Ident, Option<String>) {
89 default_crate_name()
90}
91
92#[proc_macro_derive(Future)]
93pub fn derive_future(input: TokenStream) -> TokenStream {
94 quick_derive! {
95 input,
96 ::core::future::Future,
97 trait Future {
98 type Output;
99 #[inline]
100 fn poll(
101 self: ::core::pin::Pin<&mut Self>,
102 cx: &mut ::core::task::Context<'_>,
103 ) -> ::core::task::Poll<Self::Output>;
104 }
105 }
106}
107
108#[proc_macro_derive(Stream)]
109pub fn derive_stream(input: TokenStream) -> TokenStream {
110 let (crate_, _) = crate_name(&["futures", "futures-util", "futures-core"]);
111
112 derive_trait(
113 &parse_macro_input!(input),
114 parse_quote!(::#crate_::stream::Stream),
115 None,
116 parse_quote! {
117 trait Stream {
118 type Item;
119 #[inline]
120 fn poll_next(
121 self: ::core::pin::Pin<&mut Self>,
122 cx: &mut ::core::task::Context<'_>,
123 ) -> ::core::task::Poll<::core::option::Option<Self::Item>>;
124 #[inline]
125 fn size_hint(&self) -> (usize, ::core::option::Option<usize>);
126 }
127 },
128 )
129 .into()
130}
131
132#[proc_macro_derive(Sink)]
133pub fn derive_sink(input: TokenStream) -> TokenStream {
134 let (crate_, original) = crate_name(&["futures", "futures-sink"]);
135 let path = if original.as_ref().map_or(false, |s| s == "futures-sink") {
136 quote!(::#crate_)
137 } else {
138 quote!(::#crate_::sink)
139 };
140
141 derive_trait(&parse_macro_input!(input), parse_quote!(#path::Sink), None, parse_quote! {
142 trait Sink<__Item> {
143 type Error;
144 #[inline]
145 fn poll_ready(
146 self: ::core::pin::Pin<&mut Self>,
147 cx: &mut ::core::task::Context<'_>,
148 ) -> ::core::task::Poll<::core::result::Result<(), Self::Error>>;
149 #[inline]
150 fn start_send(
151 self: ::core::pin::Pin<&mut Self>,
152 item: __Item,
153 ) -> ::core::result::Result<(), Self::Error>;
154 #[inline]
155 fn poll_flush(
156 self: ::core::pin::Pin<&mut Self>,
157 cx: &mut ::core::task::Context<'_>,
158 ) -> ::core::task::Poll<::core::result::Result<(), Self::Error>>;
159 #[inline]
160 fn poll_close(
161 self: ::core::pin::Pin<&mut Self>,
162 cx: &mut ::core::task::Context<'_>,
163 ) -> ::core::task::Poll<::core::result::Result<(), Self::Error>>;
164 }
165 })
166 .into()
167}
168
169#[proc_macro_derive(AsyncRead)]
170pub fn derive_async_read(input: TokenStream) -> TokenStream {
171 let (crate_, original) = crate_name(&["futures", "futures-io"]);
172
173 let path = if original.as_ref().map_or(false, |s| s == "futures-io") {
174 quote!(::#crate_)
175 } else {
176 quote!(::#crate_::io)
177 };
178
179 derive_trait(&parse_macro_input!(input), parse_quote!(#path::AsyncRead), None, parse_quote! {
180 trait AsyncRead {
181 #[inline]
182 fn poll_read(
183 self: ::core::pin::Pin<&mut Self>,
184 cx: &mut ::core::task::Context<'_>,
185 buf: &mut [u8],
186 ) -> ::core::task::Poll<::std::io::Result<usize>>;
187 #[inline]
188 fn poll_read_vectored(
189 self: ::core::pin::Pin<&mut Self>,
190 cx: &mut ::core::task::Context<'_>,
191 bufs: &mut [::std::io::IoSliceMut<'_>],
192 ) -> ::core::task::Poll<::std::io::Result<usize>>;
193 }
194 })
195 .into()
196}
197
198#[proc_macro_derive(AsyncWrite)]
199pub fn derive_async_write(input: TokenStream) -> TokenStream {
200 let (crate_, original) = crate_name(&["futures", "futures-io"]);
201
202 let path = if original.as_ref().map_or(false, |s| s == "futures-io") {
203 quote!(::#crate_)
204 } else {
205 quote!(::#crate_::io)
206 };
207
208 derive_trait(&parse_macro_input!(input), parse_quote!(#path::AsyncWrite), None, parse_quote! {
209 trait AsyncWrite {
210 #[inline]
211 fn poll_write(
212 self: ::core::pin::Pin<&mut Self>,
213 cx: &mut ::core::task::Context<'_>,
214 buf: &[u8],
215 ) -> ::core::task::Poll<::std::io::Result<usize>>;
216 #[inline]
217 fn poll_write_vectored(
218 self: ::core::pin::Pin<&mut Self>,
219 cx: &mut ::core::task::Context<'_>,
220 bufs: &[::std::io::IoSlice<'_>],
221 ) -> ::core::task::Poll<::std::io::Result<usize>>;
222 #[inline]
223 fn poll_flush(
224 self: ::core::pin::Pin<&mut Self>,
225 cx: &mut ::core::task::Context<'_>,
226 ) -> ::core::task::Poll<::std::io::Result<()>>;
227 #[inline]
228 fn poll_close(
229 self: ::core::pin::Pin<&mut Self>,
230 cx: &mut ::core::task::Context<'_>,
231 ) -> ::core::task::Poll<::std::io::Result<()>>;
232 }
233 })
234 .into()
235}
236
237#[proc_macro_derive(AsyncSeek)]
238pub fn derive_async_seek(input: TokenStream) -> TokenStream {
239 let (crate_, original) = crate_name(&["futures", "futures-io"]);
240
241 let path = if original.as_ref().map_or(false, |s| s == "futures-io") {
242 quote!(::#crate_)
243 } else {
244 quote!(::#crate_::io)
245 };
246
247 derive_trait(&parse_macro_input!(input), parse_quote!(#path::AsyncSeek), None, parse_quote! {
248 trait AsyncSeek {
249 #[inline]
250 fn poll_seek(
251 self: ::core::pin::Pin<&mut Self>,
252 cx: &mut ::core::task::Context<'_>,
253 pos: ::std::io::SeekFrom,
254 ) -> ::core::task::Poll<::std::io::Result<u64>>;
255 }
256 })
257 .into()
258}
259
260#[proc_macro_derive(AsyncBufRead)]
261pub fn derive_async_buf_read(input: TokenStream) -> TokenStream {
262 let (crate_, original) = crate_name(&["futures", "futures-io"]);
263
264 let path = if original.as_ref().map_or(false, |s| s == "futures-io") {
265 quote!(::#crate_)
266 } else {
267 quote!(::#crate_::io)
268 };
269
270 derive_trait(
271 &parse_macro_input!(input),
272 parse_quote!(#path::AsyncBufRead),
273 None,
274 parse_quote! {
275 trait AsyncBufRead {
276 #[inline]
277 fn poll_fill_buf<'__a>(
278 self: ::core::pin::Pin<&'__a mut Self>,
279 cx: &mut ::core::task::Context<'_>,
280 ) -> ::core::task::Poll<::std::io::Result<&'__a [u8]>>;
281 #[inline]
282 fn consume(self: ::core::pin::Pin<&mut Self>, amt: usize);
283 }
284 },
285 )
286 .into()
287}