derive_io/
lib.rs

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, if_meta, repeat_in_parenthesis,
19        type_has_generic,
20    };
21
22    // We need a guaranteed valid implementation of this trait for each trait we support.
23    #[doc(hidden)]
24    pub trait IsSupported<T> {
25        type Type;
26    }
27
28    impl IsSupported<&'static dyn std::io::Read> for () {
29        type Type = Box<dyn std::io::Read + Unpin>;
30    }
31
32    impl IsSupported<&'static dyn std::io::Write> for () {
33        type Type = Box<dyn std::io::Write + Unpin>;
34    }
35
36    #[cfg(feature = "tokio")]
37    impl IsSupported<&'static dyn tokio::io::AsyncRead> for () {
38        type Type = Box<dyn tokio::io::AsyncRead + Unpin>;
39    }
40
41    #[cfg(feature = "tokio")]
42    impl IsSupported<&'static dyn tokio::io::AsyncWrite> for () {
43        type Type = Box<dyn tokio::io::AsyncWrite + Unpin>;
44    }
45
46    #[cfg(unix)]
47    impl IsSupported<&'static dyn std::os::fd::AsFd> for () {
48        type Type = Box<dyn std::os::fd::AsFd + Unpin>;
49    }
50
51    #[cfg(unix)]
52    // This one has buggy bounds in the rust stdlib
53    impl IsSupported<&'static dyn std::os::fd::AsRawFd> for () {
54        type Type = std::os::fd::RawFd;
55    }
56
57    #[cfg(windows)]
58    impl IsSupported<&'static dyn std::os::windows::io::AsHandle> for () {
59        type Type = std::os::windows::io::OwnedHandle;
60    }
61
62    #[cfg(windows)]
63    impl IsSupported<&'static dyn std::os::windows::io::AsRawHandle> for () {
64        type Type = std::os::windows::io::OwnedHandle;
65    }
66
67    #[cfg(windows)]
68    impl IsSupported<&'static dyn std::os::windows::io::AsSocket> for () {
69        type Type = std::os::windows::io::OwnedSocket;
70    }
71
72    #[cfg(windows)]
73    impl IsSupported<&'static dyn std::os::windows::io::AsRawSocket> for () {
74        type Type = std::os::windows::io::OwnedSocket;
75    }
76}
77
78#[doc(hidden)]
79#[macro_export]
80macro_rules! __derive_io_read_parse {
81    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
82        const _: &str = stringify!( generics = $generics, where = $($where)* );
83        $crate::__derive_impl!(__parse_type__ Read $generics ($($where)*) read $($input)*);
84    };
85}
86
87#[doc(hidden)]
88#[macro_export]
89macro_rules! __derive_io_write_parse {
90    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
91        const _: &str = stringify!( generics = $generics, where = $($where)* );
92        $crate::__derive_impl!(__parse_type__ Write $generics ($($where)*) write $($input)*);
93    };
94}
95
96#[doc(hidden)]
97#[macro_export]
98macro_rules! __derive_io_async_read_parse {
99    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
100        const _: &str = stringify!( generics = $generics, where = $($where)* );
101        $crate::__derive_impl!(__parse_type__ AsyncRead $generics ($($where)*) read $($input)*);
102    };
103}
104
105#[doc(hidden)]
106#[macro_export]
107macro_rules! __derive_io_async_write_parse {
108    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
109        const _: &str = stringify!( generics = $generics, where = $($where)* );
110        $crate::__derive_impl!(__parse_type__ AsyncWrite $generics ($($where)*) write $($input)*);
111    };
112}
113
114#[doc(hidden)]
115#[macro_export]
116macro_rules! __derive_io_as_file_descriptor_parse {
117    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
118        const _: &str = stringify!( generics = $generics, where = $($where)* );
119        $crate::__derive_impl!(__parse_type__ AsFileDescriptor $generics ($($where)*) descriptor $($input)*);
120    };
121}
122
123#[doc(hidden)]
124#[macro_export]
125macro_rules! __derive_io_as_socket_descriptor_parse {
126    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
127        const _: &str = stringify!( generics = $generics, where = $($where)* );
128        $crate::__derive_impl!(__parse_type__ AsSocketDescriptor $generics ($($where)*) descriptor $($input)*);
129    };
130}
131
132#[doc(hidden)]
133#[macro_export]
134macro_rules! __derive_impl {
135    // Parse enum types, identifying annotated fields. Next macro: __process_derive__
136    ( __parse_type__ $generator:ident $generics:tt $where:tt $attr:ident
137        $(#[$eattr:meta])* $vis:vis enum $name:ident {
138            $( $(#[$iattr:meta])* $field:ident
139                $( ( $($(#[$tuple_attr:meta])* $tuple_type:ty),* $(,)?) )?
140                $( { $($(#[$struct_attr:meta])* $struct_name:ident : $struct_type:ty),* $(,)? } )?
141            ),*
142            $(,)?
143        }
144    ) => {
145        $crate::__support::find_annotated_multi!(
146            ($crate::__derive_impl)
147            (__process_derive__ $generator $attr $generics $where enum $name)
148            $attr
149            {
150                compile_error!(concat!("No #[", stringify!($attr), "] field found"));
151            }
152            $(
153                (
154                    (Self::$field)
155                    $(
156                        $(
157                            (($([$tuple_attr])*)
158                            ($tuple_type))
159                        )*
160                    )?
161                    $(
162                        $(
163                            (($([$struct_attr])*)
164                            ($struct_type:($struct_name)))
165                        )*
166                    )?
167                )
168            )*
169        );
170    };
171
172    // Parse named structs, identifying annotated fields. Next macro: __process_derive__
173    ( __parse_type__ $generator:ident $generics:tt $where:tt $attr:ident
174        $(#[$sattr:meta])* $vis:vis struct $name:ident { $( $(#[$fattr:meta])* $fname:ident : $ftype:ty ),* $(,)? }
175    ) => {
176        $crate::__support::find_annotated_multi!(
177            ($crate::__derive_impl)
178            (__process_derive__ $generator $attr $generics $where struct $name)
179            $attr
180            {
181                compile_error!(concat!("No #[", stringify!($attr), "] field found"));
182            }
183            ((Self) $( (($([$fattr])*) ($ftype: ($fname))) )*)
184        );
185    };
186
187    // Parse tuple structs, identifying annotated fields. Next macro: __process_derive__
188    ( __parse_type__ $generator:ident $generics:tt $where:tt $attr:ident
189        $(#[$sattr:meta])* $vis:vis struct $name:ident ( $( $(#[$fattr:meta])* $ftype:ty ),* $(,)? );
190    ) => {
191        $crate::__support::find_annotated_multi!(
192            ($crate::__derive_impl)
193            (__process_derive__ $generator $attr $generics $where struct $name)
194            $attr
195            {
196                compile_error!(concat!("No #[", stringify!($attr), "] field found"));
197            }
198            ((Self) $( (($([$fattr])*) ($ftype)) )*)
199        );
200    };
201
202    // Process the identified annotated fields. Next macro: __generate__ $generator
203    // Note that the input here is:
204    //   (case) index [attr] (type : name)
205    ( (__process_derive__ $generator:ident $attr:ident $generics:tt $where:tt $type:ident $name:ident) (
206        $( ( ($case:path) $index:literal $fattr:tt ($ftype:ty $( : ($fname:ident) )?) ) )*
207    )) => {
208        const _: &str = stringify!( $type $name {
209            $(
210                # $fattr ($case) => $crate::__derive_impl!(__expand__ $attr ($case) $index $ftype $(: $fname)?)
211            )*
212        });
213
214        $crate::__derive_impl!(__generate__ $generator $attr $generics $where ($($ftype)*)
215            $type $name {
216                $(
217                    # $fattr ($case) => $crate::__derive_impl!(__expand__ $attr ($case) $index $ftype $(: $fname)?)
218                )*
219            }
220        );
221    };
222
223    // Generate the impl block for Read. Next macro: __impl__
224    ( __generate__ Read $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
225        $crate::__derive_impl!(__impl__ ::std::io::Read : $name $generics $where $ftypes #[read] {
226            fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
227                let $this = self;
228                $crate::__derive_impl!(__foreach__ $this (::std::io::Read read($this, buf)) $struct)
229            }
230        });
231    };
232
233    // Generate the impl block for Write. Next macro: __impl__
234    ( __generate__ Write $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
235        $crate::__derive_impl!(__impl__ ::std::io::Write : $name $generics $where $ftypes #[write] {
236            fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
237                let $this = self;
238                $crate::__derive_impl!(__foreach__ $this (::std::io::Write write($this, buf)) $struct)
239            }
240            fn flush(&mut self) -> ::std::io::Result<()> {
241                let $this = self;
242                $crate::__derive_impl!(__foreach__ $this (::std::io::Write flush($this)) $struct)
243            }
244        });
245    };
246
247    // Generate the impl block for AsyncRead. Next macro: __impl__
248    ( __generate__ AsyncRead $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
249        $crate::__derive_impl!(__impl__ ::tokio::io::AsyncRead : $name $generics $where $ftypes #[read] {
250            #[inline]
251            fn poll_read(
252                mut self: ::std::pin::Pin<&mut Self>,
253                cx: &mut ::std::task::Context<'_>,
254                buf: &mut ::tokio::io::ReadBuf<'_>,
255            ) -> ::std::task::Poll<::std::io::Result<()>> {
256                let $this = self;
257                $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncRead poll_read($this, cx, buf)) $struct)
258            }
259        });
260    };
261
262    // Generate the impl block for AsyncWrite. Next macro: __impl__
263    ( __generate__ AsyncWrite $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
264        $crate::__derive_impl!(__impl__ ::tokio::io::AsyncWrite : $name $generics $where $ftypes #[write] {
265            #[inline]
266            fn poll_write(
267                self: ::std::pin::Pin<&mut Self>,
268                cx: &mut ::std::task::Context<'_>,
269                buf: &[u8],
270            ) -> ::std::task::Poll<::std::io::Result<usize>> {
271                let $this = self;
272                $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncWrite poll_write($this, cx, buf)) $struct)
273            }
274
275            #[inline]
276            fn poll_flush(
277                self: ::std::pin::Pin<&mut Self>,
278                cx: &mut ::std::task::Context<'_>,
279            ) -> ::std::task::Poll<::std::io::Result<()>> {
280                let $this = self;
281                $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncWrite poll_flush($this, cx)) $struct)
282            }
283
284            #[inline]
285            fn poll_shutdown(
286                self: ::std::pin::Pin<&mut Self>,
287                cx: &mut ::std::task::Context<'_>,
288            ) -> ::std::task::Poll<::std::io::Result<()>> {
289                let $this = self;
290                $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncWrite poll_shutdown($this, cx)) $struct)
291            }
292
293            #[inline]
294            fn is_write_vectored(&self) -> bool {
295                let $this = self;
296                $crate::__derive_impl!(__foreach__ $this (::tokio::io::AsyncWrite is_write_vectored($this)) $struct)
297            }
298
299            #[inline]
300            fn poll_write_vectored(
301                self: ::std::pin::Pin<&mut Self>,
302                cx: &mut ::std::task::Context<'_>,
303                bufs: &[::std::io::IoSlice<'_>],
304            ) -> ::std::task::Poll<::std::io::Result<usize>> {
305                let $this = self;
306                $crate::__derive_impl!(__foreach_pin__ $this (::tokio::io::AsyncWrite poll_write_vectored($this, cx, bufs)) $struct)
307            }
308        });
309    };
310
311    // std::os::fd::{AsFd, AsRawFd}, std::os::windows::io::{AsHandle, AsRawHandle}
312    ( __generate__ AsFileDescriptor $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
313        #[cfg(unix)]
314        $crate::__derive_impl!(__impl__ ::std::os::fd::AsFd : $name $generics $where $ftypes #[read] {
315            fn as_fd(&self) -> ::std::os::fd::BorrowedFd<'_> {
316                let $this = self;
317                $crate::__derive_impl!(__foreach__ $this (::std::os::fd::AsFd as_fd($this)) $struct)
318            }
319        });
320        #[cfg(unix)]
321        $crate::__derive_impl!(__impl__ ::std::os::fd::AsRawFd : $name $generics $where $ftypes #[read] {
322            fn as_raw_fd(&self) -> ::std::os::fd::RawFd {
323                let $this = self;
324                $crate::__derive_impl!(__foreach__ $this (::std::os::fd::AsRawFd as_raw_fd($this)) $struct)
325            }
326        });
327        #[cfg(windows)]
328        $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsRawHandle : $name $generics $where $ftypes #[read] {
329            fn as_raw_handle(&self) -> ::std::os::windows::io::RawHandle {
330                let $this = self;
331                $crate::__derive_impl!(__foreach__ $this (::std::os::windows::io::AsRawHandle as_raw_handle($this)) $struct)
332            }
333        });
334        #[cfg(windows)]
335        $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsHandle : $name $generics $where $ftypes #[read] {
336            fn as_handle(&self) -> ::std::os::windows::io::BorrowedHandle<'_> {
337                let $this = self;
338                $crate::__derive_impl!(__foreach__ $this (::std::os::windows::io::AsHandle as_handle($this)) $struct)
339            }
340        });
341    };
342
343    // std::os::fd::{AsFd, AsRawFd}, std::os::windows::io::{AsSocket, AsRawSocket}
344    ( __generate__ AsSocketDescriptor $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
345        #[cfg(unix)]
346        $crate::__derive_impl!(__impl__ ::std::os::fd::AsFd : $name $generics $where $ftypes #[read] {
347            fn as_fd(&self) -> ::std::os::fd::BorrowedFd<'_> {
348                let $this = self;
349                $crate::__derive_impl!(__foreach__ $this (::std::os::fd::AsFd as_fd($this)) $struct)
350            }
351        });
352        #[cfg(unix)]
353        $crate::__derive_impl!(__impl__ ::std::os::fd::AsRawFd : $name $generics $where $ftypes #[read] {
354            fn as_raw_fd(&self) -> ::std::os::fd::RawFd {
355                let $this = self;
356                $crate::__derive_impl!(__foreach__ $this (::std::os::fd::AsRawFd as_raw_fd($this)) $struct)
357            }
358        });
359        #[cfg(windows)]
360        $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsSocket : $name $generics $where $ftypes #[read] {
361            fn as_socket(&self) -> ::std::os::windows::io::BorrowedSocket<'_> {
362                let $this = self;
363                $crate::__derive_impl!(__foreach__ $this (::std::os::windows::io::AsSocket as_socket($this)) $struct)
364            }
365        });
366        #[cfg(windows)]
367        $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsRawSocket : $name $generics $where $ftypes #[read] {
368            fn as_raw_socket(&self) -> ::std::os::windows::io::RawSocket {
369                let $this = self;
370                $crate::__derive_impl!(__foreach__ $this (::std::os::windows::io::AsRawSocket as_raw_socket($this)) $struct)
371            }
372        });
373    };
374
375    // Duplicate the $generics block. Next macro: __impl_2__
376    ( __impl__ $trait:path : $name:ident $generics:tt ($($where:tt)*) ($($ftype:path)*) #[$attr:ident] $block:tt) => {
377        $crate::__derive_impl!(__impl_2__ $trait : $name $generics $generics ($($where)*) ($($ftype)*) #[$attr] $block);
378    };
379
380    // Final macro. Generate the impl block.
381    ( __impl_2__ $trait:path : $name:ident $generics:tt ( $( ($($generic:tt)*) ),* ) ($($where:tt)*) ($($ftype:path)*) #[$attr:ident] $block:tt) => {
382        impl <$($($generic)*),*> $trait for $name <$($($generic)*),*>
383            where
384                // Add a where clause for each stream type. If it contains a generic, constrain it otherwise
385                // use a placeholder type that implements the trait for certain.
386                $(
387                    $crate::__support::type_has_generic!(
388                        ($ftype)
389                        $generics
390                        ($ftype)
391                        (<() as $crate::__support::IsSupported::<&'static dyn $trait>>::Type)
392                    ) : $trait,
393                )*
394                $($where)*
395        $block
396    };
397
398    // Expand a named field to an access pattern.
399    ( __expand__ $this:ident ($case:path) $index:literal $ftype:ty : $fname:tt) => {
400        {
401            let $case { $fname, .. } = $this else {
402                unreachable!()
403            };
404            $fname
405        }
406     };
407
408    // Expand a tuple field to an access pattern.
409    ( __expand__ $this:ident ($case:path) $index:literal $ftype:ty) => {
410        {
411            let $crate::__support::repeat_in_parenthesis!(($case) $index (_,) ($this, .. )) = $this else {
412                unreachable!()
413            };
414            $this
415        }
416    };
417
418    ( __foreach__ $this:ident $fn:tt {$(
419        # $attr:tt ($case:path) => $access:expr
420    )*}) =>{
421        {
422            match $this {
423                $( $case {..} => {
424                    $crate::__support::if_meta!(
425                        as_ref
426                        $attr
427                        ({
428                            let $this = $access.as_ref();
429                            $crate::__derive_impl!(__foreach_inner__ # $attr $fn)
430                        })
431                        ($crate::__support::if_meta!(
432                            deref
433                            $attr
434                            ({
435                                let $this = std::ops::Deref::deref($access);
436                                $crate::__derive_impl!(__foreach_inner__ # $attr $fn)
437                            })
438                            ({
439                                let $this = $access;
440                                $crate::__derive_impl!(__foreach_inner__ # $attr $fn)
441                            })
442                        ))
443                    )
444                } )*
445            }
446        }
447    };
448
449    ( __foreach_pin__ $this:ident $fn:tt {$(
450        # $attr:tt ($case:path) => $access:expr
451    )*}) =>{
452        {
453            let mut $this = unsafe { $this.get_unchecked_mut() };
454            match $this {
455                $( $case {..} => {
456                    $crate::__support::if_meta!(
457                        as_ref
458                        $attr
459                        ({
460                            let $this = unsafe { ::std::pin::Pin::new_unchecked($access) };
461                            let $this = ::std::pin::Pin::new($this.get_mut().as_mut());
462                            $crate::__derive_impl!(__foreach_inner__ # $attr $fn)
463                        })
464                        ($crate::__support::if_meta!(
465                            deref
466                            $attr
467                            ({
468                                let $this = unsafe { ::std::pin::Pin::new_unchecked($access) };
469                                let $this = ::std::pin::Pin::new(std::ops::DerefMut::deref_mut($this.get_mut()));
470                                $crate::__derive_impl!(__foreach_inner__ # $attr $fn)
471                            })
472                            ({
473                                let $this = unsafe { ::std::pin::Pin::new_unchecked($access) };
474                                $crate::__derive_impl!(__foreach_inner__ # $attr $fn)
475                            })
476                        ))
477                    )
478                } )*
479            }
480        }
481    };
482
483    ( __foreach_inner__  # $attr:tt ( $( :: $fn_part:ident )+ $fn_final:ident ( $($arg:expr),* ) ) ) => {
484        // needle, haystack, default
485        {
486            $crate::__derive_impl!(__validate_macro__ # $attr);
487            $crate::__support::extract_meta!(
488                $fn_final
489                $attr
490                ($(::$fn_part)+ :: $fn_final )
491            ) ($($arg),*)
492        }
493    };
494
495    ( __validate_macro__ #[read]) => {
496    };
497
498    ( __validate_macro__ #[read($( as_ref )? $(,)? $( deref )? $(,)? $( poll_read=$poll_read:ident )? )]) => {
499    };
500
501    ( __validate_macro__ #[write]) => {
502    };
503
504    ( __validate_macro__ #[write($($key:ident $(=$value:ident)?),* $(,)?)]) => {
505        $crate::__derive_impl!(__validate_macro_deep__ #[write($($key $(=$value)?),*)]);
506    };
507
508    ( __validate_macro_deep__ #[write(
509        $( as_ref )? $(,)?
510        $( deref )? $(,)?
511        $( poll_write=$poll_write:ident )? $(,)?
512        $( poll_flush=$poll_flush:ident )? $(,)?
513        $( poll_shutdown=$poll_shutdown:ident )? $(,)?
514        $( is_write_vectored=$is_write_vectored:ident )? $(,)?
515        $( poll_write_vectored=$poll_write_vectored:ident )?
516    )]) => {
517    };
518
519    ( __validate_macro_deep__ # $($rest:tt)*) => {
520        compile_error!(concat!("Invalid #", stringify!($($rest)*), " attribute"));
521    };
522
523    ( __validate_macro__ #[descriptor]) => {
524    };
525
526    ( __validate_macro__ #[descriptor(as_ref)]) => {
527    };
528
529    ( __validate_macro__ #[descriptor(deref)]) => {
530    };
531
532    ( __validate_macro__ # $attr:tt) => {
533        compile_error!(concat!("Invalid #", stringify!($attr), " attribute"));
534    };
535}