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, repeat_in_parenthesis, type_has_generic,
19    };
20
21    // We need a guaranteed valid implementation of this trait for each trait we support.
22    #[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    // This one has buggy bounds in the rust stdlib
52    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 enum types, identifying annotated fields. Next macro: __process_derive__
135    ( __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 named structs, identifying annotated fields. Next macro: __process_derive__
172    ( __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 tuple structs, identifying annotated fields. Next macro: __process_derive__
187    ( __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 the identified annotated fields. Next macro: __generate__ $generator
202    // Note that the input here is:
203    //   (case) index [attr] (type : name)
204    ( (__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 the impl block for Read. Next macro: __impl__
223    ( __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 the impl block for Write. Next macro: __impl__
233    ( __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 the impl block for AsyncRead. Next macro: __impl__
247    ( __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 the impl block for AsyncWrite. Next macro: __impl__
262    ( __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    // std::os::{AsFd, AsRawFd}, std::os::windows::io::{AsHandle, AsRawHandle}
311    ( __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    // std::os::{AsFd, AsRawFd}, std::os::windows::io::{AsSocket, AsRawSocket}
343    ( __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    // Duplicate the $generics block. Next macro: __impl_2__
375    ( __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    // Final macro. Generate the impl block.
380    ( __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                // Add a where clause for each stream type. If it contains a generic, constrain it otherwise
384                // use a placeholder type that implements the trait for certain.
385                $(
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 a named field to an access pattern.
398    ( __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 a tuple field to an access pattern.
408    ( __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        // needle, haystack, default
445        {
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}