1#![doc = include_str!("../README.md")]
2
3#[cfg(feature = "std")]
4pub use derive_io_macros::{AsFileDescriptor, AsSocketDescriptor, Read, Write};
5
6#[cfg(feature = "tokio")]
7pub use derive_io_macros::{AsyncRead, AsyncWrite};
8
9#[doc(hidden)]
10pub mod __support {
11 pub use crate::__derive_io_as_file_descriptor_parse as derive_io_as_file_descriptor_parse;
12 pub use crate::__derive_io_as_socket_descriptor_parse as derive_io_as_socket_descriptor_parse;
13 pub use crate::__derive_io_async_read_parse as derive_io_async_read_parse;
14 pub use crate::__derive_io_async_write_parse as derive_io_async_write_parse;
15 pub use crate::__derive_io_read_parse as derive_io_read_parse;
16 pub use crate::__derive_io_write_parse as derive_io_write_parse;
17 pub use derive_io_macros::{
18 extract_meta, find_annotated, find_annotated_multi, repeat_in_parenthesis, type_has_generic,
19 };
20
21 #[doc(hidden)]
23 pub trait IsSupported<T> {
24 type Type;
25 }
26
27 impl IsSupported<&'static dyn std::io::Read> for () {
28 type Type = Box<dyn std::io::Read + Unpin>;
29 }
30
31 impl IsSupported<&'static dyn std::io::Write> for () {
32 type Type = Box<dyn std::io::Write + Unpin>;
33 }
34
35 #[cfg(feature = "tokio")]
36 impl IsSupported<&'static dyn tokio::io::AsyncRead> for () {
37 type Type = Box<dyn tokio::io::AsyncRead + Unpin>;
38 }
39
40 #[cfg(feature = "tokio")]
41 impl IsSupported<&'static dyn tokio::io::AsyncWrite> for () {
42 type Type = Box<dyn tokio::io::AsyncWrite + Unpin>;
43 }
44
45 #[cfg(unix)]
46 impl IsSupported<&'static dyn std::os::fd::AsFd> for () {
47 type Type = Box<dyn std::os::fd::AsFd + Unpin>;
48 }
49
50 #[cfg(unix)]
51 impl IsSupported<&'static dyn std::os::fd::AsRawFd> for () {
53 type Type = std::os::fd::RawFd;
54 }
55
56 #[cfg(windows)]
57 impl IsSupported<&'static dyn std::os::windows::io::AsHandle> for () {
58 type Type = std::os::windows::io::OwnedHandle;
59 }
60
61 #[cfg(windows)]
62 impl IsSupported<&'static dyn std::os::windows::io::AsRawHandle> for () {
63 type Type = std::os::windows::io::OwnedHandle;
64 }
65
66 #[cfg(windows)]
67 impl IsSupported<&'static dyn std::os::windows::io::AsSocket> for () {
68 type Type = std::os::windows::io::OwnedSocket;
69 }
70
71 #[cfg(windows)]
72 impl IsSupported<&'static dyn std::os::windows::io::AsRawSocket> for () {
73 type Type = std::os::windows::io::OwnedSocket;
74 }
75}
76
77#[doc(hidden)]
78#[macro_export]
79macro_rules! __derive_io_read_parse {
80 ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
81 const _: &str = stringify!( generics = $generics, where = $($where)* );
82 $crate::__derive_impl!(__parse_type__ Read $generics ($($where)*) read $($input)*);
83 };
84}
85
86#[doc(hidden)]
87#[macro_export]
88macro_rules! __derive_io_write_parse {
89 ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
90 const _: &str = stringify!( generics = $generics, where = $($where)* );
91 $crate::__derive_impl!(__parse_type__ Write $generics ($($where)*) write $($input)*);
92 };
93}
94
95#[doc(hidden)]
96#[macro_export]
97macro_rules! __derive_io_async_read_parse {
98 ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
99 const _: &str = stringify!( generics = $generics, where = $($where)* );
100 $crate::__derive_impl!(__parse_type__ AsyncRead $generics ($($where)*) read $($input)*);
101 };
102}
103
104#[doc(hidden)]
105#[macro_export]
106macro_rules! __derive_io_async_write_parse {
107 ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
108 const _: &str = stringify!( generics = $generics, where = $($where)* );
109 $crate::__derive_impl!(__parse_type__ AsyncWrite $generics ($($where)*) write $($input)*);
110 };
111}
112
113#[doc(hidden)]
114#[macro_export]
115macro_rules! __derive_io_as_file_descriptor_parse {
116 ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
117 const _: &str = stringify!( generics = $generics, where = $($where)* );
118 $crate::__derive_impl!(__parse_type__ AsFileDescriptor $generics ($($where)*) descriptor $($input)*);
119 };
120}
121
122#[doc(hidden)]
123#[macro_export]
124macro_rules! __derive_io_as_socket_descriptor_parse {
125 ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
126 const _: &str = stringify!( generics = $generics, where = $($where)* );
127 $crate::__derive_impl!(__parse_type__ AsSocketDescriptor $generics ($($where)*) descriptor $($input)*);
128 };
129}
130
131#[doc(hidden)]
132#[macro_export]
133macro_rules! __derive_impl {
134 ( __parse_type__ $generator:ident $generics:tt $where:tt $attr:ident
136 $(#[$eattr:meta])* $vis:vis enum $name:ident {
137 $( $(#[$iattr:meta])* $field:ident
138 $( ( $($(#[$tuple_attr:meta])* $tuple_type:ty),* $(,)?) )?
139 $( { $($(#[$struct_attr:meta])* $struct_name:ident : $struct_type:ty),* $(,)? } )?
140 ),*
141 $(,)?
142 }
143 ) => {
144 $crate::__support::find_annotated_multi!(
145 ($crate::__derive_impl)
146 (__process_derive__ $generator $attr $generics $where enum $name)
147 $attr
148 {
149 compile_error!(concat!("No #[", stringify!($attr), "] field found"));
150 }
151 $(
152 (
153 (Self::$field)
154 $(
155 $(
156 (($([$tuple_attr])*)
157 ($tuple_type))
158 )*
159 )?
160 $(
161 $(
162 (($([$struct_attr])*)
163 ($struct_type:($struct_name)))
164 )*
165 )?
166 )
167 )*
168 );
169 };
170
171 ( __parse_type__ $generator:ident $generics:tt $where:tt $attr:ident
173 $(#[$sattr:meta])* $vis:vis struct $name:ident { $( $(#[$fattr:meta])* $fname:ident : $ftype:ty ),* $(,)? }
174 ) => {
175 $crate::__support::find_annotated_multi!(
176 ($crate::__derive_impl)
177 (__process_derive__ $generator $attr $generics $where struct $name)
178 $attr
179 {
180 compile_error!(concat!("No #[", stringify!($attr), "] field found"));
181 }
182 ((Self) $( (($([$fattr])*) ($ftype: ($fname))) )*)
183 );
184 };
185
186 ( __parse_type__ $generator:ident $generics:tt $where:tt $attr:ident
188 $(#[$sattr:meta])* $vis:vis struct $name:ident ( $( $(#[$fattr:meta])* $ftype:ty ),* $(,)? );
189 ) => {
190 $crate::__support::find_annotated_multi!(
191 ($crate::__derive_impl)
192 (__process_derive__ $generator $attr $generics $where struct $name)
193 $attr
194 {
195 compile_error!(concat!("No #[", stringify!($attr), "] field found"));
196 }
197 ((Self) $( (($([$fattr])*) ($ftype)) )*)
198 );
199 };
200
201 ( (__process_derive__ $generator:ident $attr:ident $generics:tt $where:tt $type:ident $name:ident) (
205 $( ( ($case:path) $index:literal $fattr:tt ($ftype:ty $( : ($fname:ident) )?) ) )*
206 )) => {
207 const _: &str = stringify!( $type $name {
208 $(
209 # $fattr ($case) => $crate::__derive_impl!(__expand__ $attr ($case) $index $ftype $(: $fname)?)
210 )*
211 });
212
213 $crate::__derive_impl!(__generate__ $generator $attr $generics $where ($($ftype)*)
214 $type $name {
215 $(
216 # $fattr ($case) => $crate::__derive_impl!(__expand__ $attr ($case) $index $ftype $(: $fname)?)
217 )*
218 }
219 );
220 };
221
222 ( __generate__ Read $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
224 $crate::__derive_impl!(__impl__ ::std::io::Read : $name $generics $where $ftypes #[read] {
225 fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
226 let $this = self;
227 $crate::__derive_impl!(__foreach__ $this (::std::io::Read read($this, buf)) $struct)
228 }
229 });
230 };
231
232 ( __generate__ Write $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
234 $crate::__derive_impl!(__impl__ ::std::io::Write : $name $generics $where $ftypes #[write] {
235 fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
236 let $this = self;
237 $crate::__derive_impl!(__foreach__ $this (::std::io::Write write($this, buf)) $struct)
238 }
239 fn flush(&mut self) -> ::std::io::Result<()> {
240 let $this = self;
241 $crate::__derive_impl!(__foreach__ $this (::std::io::Write flush($this)) $struct)
242 }
243 });
244 };
245
246 ( __generate__ AsyncRead $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
248 $crate::__derive_impl!(__impl__ ::tokio::io::AsyncRead : $name $generics $where $ftypes #[read] {
249 #[inline]
250 fn poll_read(
251 mut self: ::std::pin::Pin<&mut Self>,
252 cx: &mut ::std::task::Context<'_>,
253 buf: &mut ::tokio::io::ReadBuf<'_>,
254 ) -> ::std::task::Poll<::std::io::Result<()>> {
255 let $this = self;
256 $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncRead poll_read($this, cx, buf)) $struct)
257 }
258 });
259 };
260
261 ( __generate__ AsyncWrite $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
263 $crate::__derive_impl!(__impl__ ::tokio::io::AsyncWrite : $name $generics $where $ftypes #[write] {
264 #[inline]
265 fn poll_write(
266 self: ::std::pin::Pin<&mut Self>,
267 cx: &mut ::std::task::Context<'_>,
268 buf: &[u8],
269 ) -> ::std::task::Poll<::std::io::Result<usize>> {
270 let $this = self;
271 $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncWrite poll_write($this, cx, buf)) $struct)
272 }
273
274 #[inline]
275 fn poll_flush(
276 self: ::std::pin::Pin<&mut Self>,
277 cx: &mut ::std::task::Context<'_>,
278 ) -> ::std::task::Poll<::std::io::Result<()>> {
279 let $this = self;
280 $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncWrite poll_flush($this, cx)) $struct)
281 }
282
283 #[inline]
284 fn poll_shutdown(
285 self: ::std::pin::Pin<&mut Self>,
286 cx: &mut ::std::task::Context<'_>,
287 ) -> ::std::task::Poll<::std::io::Result<()>> {
288 let $this = self;
289 $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncWrite poll_shutdown($this, cx)) $struct)
290 }
291
292 #[inline]
293 fn is_write_vectored(&self) -> bool {
294 let $this = self;
295 $crate::__derive_impl!(__foreach__ $this (::tokio::io::AsyncWrite is_write_vectored($this)) $struct)
296 }
297
298 #[inline]
299 fn poll_write_vectored(
300 self: ::std::pin::Pin<&mut Self>,
301 cx: &mut ::std::task::Context<'_>,
302 bufs: &[::std::io::IoSlice<'_>],
303 ) -> ::std::task::Poll<::std::io::Result<usize>> {
304 let $this = self;
305 $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncWrite poll_write_vectored($this, cx, bufs)) $struct)
306 }
307 });
308 };
309
310 ( __generate__ AsFileDescriptor $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
312 #[cfg(unix)]
313 $crate::__derive_impl!(__impl__ ::std::os::fd::AsFd : $name $generics $where $ftypes #[read] {
314 fn as_fd(&self) -> ::std::os::fd::BorrowedFd<'_> {
315 let $this = self;
316 $crate::__derive_impl!(__foreach__ $this (::std::os::fd::AsFd as_fd($this)) $struct)
317 }
318 });
319 #[cfg(unix)]
320 $crate::__derive_impl!(__impl__ ::std::os::fd::AsRawFd : $name $generics $where $ftypes #[read] {
321 fn as_raw_fd(&self) -> ::std::os::fd::RawFd {
322 let $this = self;
323 $crate::__derive_impl!(__foreach__ $this (::std::os::fd::AsRawFd as_raw_fd($this)) $struct)
324 }
325 });
326 #[cfg(windows)]
327 $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsRawHandle : $name $generics $where $ftypes #[read] {
328 fn as_raw_handle(&self) -> ::std::os::windows::io::RawHandle {
329 let $this = self;
330 $crate::__derive_impl!(__foreach__ $this (::std::os::windows::io::AsRawHandle as_raw_handle($this)) $struct)
331 }
332 });
333 #[cfg(windows)]
334 $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsHandle : $name $generics $where $ftypes #[read] {
335 fn as_handle(&self) -> ::std::os::windows::io::BorrowedHandle<'_> {
336 let $this = self;
337 $crate::__derive_impl!(__foreach__ $this (::std::os::windows::io::AsHandle as_handle($this)) $struct)
338 }
339 });
340 };
341
342 ( __generate__ AsSocketDescriptor $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
344 #[cfg(unix)]
345 $crate::__derive_impl!(__impl__ ::std::os::fd::AsFd : $name $generics $where $ftypes #[read] {
346 fn as_fd(&self) -> ::std::os::fd::BorrowedFd<'_> {
347 let $this = self;
348 $crate::__derive_impl!(__foreach__ $this (::std::os::fd::AsFd as_fd($this)) $struct)
349 }
350 });
351 #[cfg(unix)]
352 $crate::__derive_impl!(__impl__ ::std::os::fd::AsRawFd : $name $generics $where $ftypes #[read] {
353 fn as_raw_fd(&self) -> ::std::os::fd::RawFd {
354 let $this = self;
355 $crate::__derive_impl!(__foreach__ $this (::std::os::fd::AsRawFd as_raw_fd($this)) $struct)
356 }
357 });
358 #[cfg(windows)]
359 $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsSocket : $name $generics $where $ftypes #[read] {
360 fn as_socket(&self) -> ::std::os::windows::io::BorrowedSocket<'_> {
361 let $this = self;
362 $crate::__derive_impl!(__foreach__ $this (::std::os::windows::io::AsSocket as_socket($this)) $struct)
363 }
364 });
365 #[cfg(windows)]
366 $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsRawSocket : $name $generics $where $ftypes #[read] {
367 fn as_raw_socket(&self) -> ::std::os::windows::io::RawSocket {
368 let $this = self;
369 $crate::__derive_impl!(__foreach__ $this (::std::os::windows::io::AsRawSocket as_raw_socket($this)) $struct)
370 }
371 });
372 };
373
374 ( __impl__ $trait:path : $name:ident $generics:tt ($($where:tt)*) ($($ftype:path)*) #[$attr:ident] $block:tt) => {
376 $crate::__derive_impl!(__impl_2__ $trait : $name $generics $generics ($($where)*) ($($ftype)*) #[$attr] $block);
377 };
378
379 ( __impl_2__ $trait:path : $name:ident $generics:tt ( $( ($($generic:tt)*) ),* ) ($($where:tt)*) ($($ftype:path)*) #[$attr:ident] $block:tt) => {
381 impl <$($($generic)*),*> $trait for $name <$($($generic)*),*>
382 where
383 $(
386 $crate::__support::type_has_generic!(
387 ($ftype)
388 $generics
389 ($ftype)
390 (<() as $crate::__support::IsSupported::<&'static dyn $trait>>::Type)
391 ) : $trait,
392 )*
393 $($where)*
394 $block
395 };
396
397 ( __expand__ $this:ident ($case:path) $index:literal $ftype:ty : $fname:tt) => {
399 {
400 let $case { $fname, .. } = $this else {
401 unreachable!()
402 };
403 $fname
404 }
405 };
406
407 ( __expand__ $this:ident ($case:path) $index:literal $ftype:ty) => {
409 {
410 let $crate::__support::repeat_in_parenthesis!(($case) $index (_,) ($this, .. )) = $this else {
411 unreachable!()
412 };
413 $this
414 }
415 };
416
417 ( __foreach__ $this:ident $fn:tt {$(
418 # $attr:tt ($case:path) => $access:expr
419 )*}) =>{
420 {
421 match $this {
422 $( $case {..} => { let $this = $access; $crate::__derive_impl!(__foreach_inner__ # $attr $fn) } )*
423 }
424 }
425 };
426
427 ( __foreach_pin__ $this:ident $fn:tt {$(
428 # $attr:tt ($case:path) => $access:expr
429 )*}) =>{
430 {
431 let mut $this = unsafe { $this.get_unchecked_mut() };
432 match $this {
433 $(
434 $case {..} => {
435 let $this = unsafe { ::std::pin::Pin::new_unchecked($access) };
436 $crate::__derive_impl!(__foreach_inner__ # $attr $fn)
437 }
438 )*
439 }
440 }
441 };
442
443 ( __foreach_inner__ # $attr:tt ( $( :: $fn_part:ident )+ $fn_final:ident ( $($arg:expr),* ) ) ) => {
444 {
446 $crate::__derive_impl!(__validate_macro__ # $attr);
447 $crate::__support::extract_meta!(
448 $fn_final
449 $attr
450 ($(::$fn_part)+ :: $fn_final )
451 ) ($($arg),*)
452 }
453 };
454
455 ( __validate_macro__ #[read]) => {
456 };
457
458 ( __validate_macro__ #[read(poll_read=$poll_read:ident)]) => {
459 };
460
461 ( __validate_macro__ #[write]) => {
462 };
463
464 ( __validate_macro__ #[write($($key:ident=$value:ident),*)]) => {
465 $crate::__derive_impl!(__validate_macro_deep__ #[write($($key=$value),*)]);
466 };
467
468 ( __validate_macro_deep__ #[write(
469 $( poll_write=$poll_write:ident )? $(,)?
470 $( poll_flush=$poll_flush:ident )? $(,)?
471 $( poll_shutdown=$poll_shutdown:ident )? $(,)?
472 $( is_write_vectored=$is_write_vectored:ident )? $(,)?
473 $( poll_write_vectored=$poll_write_vectored:ident )?
474 )]) => {
475 };
476
477 ( __validate_macro_deep__ # $($rest:tt)*) => {
478 compile_error!(concat!("Invalid #", stringify!($($rest)*), " attribute"));
479 };
480
481 ( __validate_macro__ #[descriptor]) => {
482 };
483
484 ( __validate_macro__ # $attr:tt) => {
485 compile_error!(concat!("Invalid #", stringify!($attr), " attribute"));
486 };
487}