derive_io/
lib.rs

1#![doc = include_str!("../README.md")]
2
3#[cfg(feature = "std")]
4pub use derive_io_macros::{AsFileDescriptor, AsSocketDescriptor, BufRead, 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_bufread_parse as derive_io_bufread_parse;
16    pub use crate::__derive_io_read_parse as derive_io_read_parse;
17    pub use crate::__derive_io_write_parse as derive_io_write_parse;
18    pub use derive_io_macros::{
19        extract_meta, find_annotated, find_annotated_multi, if_meta, repeat_in_parenthesis,
20        type_has_generic,
21    };
22
23    // We need a guaranteed valid implementation of this trait for each trait we support.
24    #[doc(hidden)]
25    pub trait IsSupported<T> {
26        type Type;
27    }
28
29    impl IsSupported<&'static dyn std::io::Read> for () {
30        type Type = Box<dyn std::io::Read + Unpin>;
31    }
32
33    impl IsSupported<&'static dyn std::io::BufRead> for () {
34        type Type = Box<dyn std::io::BufRead + Unpin>;
35    }
36
37    impl IsSupported<&'static dyn std::io::Write> for () {
38        type Type = Box<dyn std::io::Write + Unpin>;
39    }
40
41    #[cfg(feature = "tokio")]
42    impl IsSupported<&'static dyn tokio::io::AsyncRead> for () {
43        type Type = Box<dyn tokio::io::AsyncRead + Unpin>;
44    }
45
46    #[cfg(feature = "tokio")]
47    impl IsSupported<&'static dyn tokio::io::AsyncWrite> for () {
48        type Type = Box<dyn tokio::io::AsyncWrite + Unpin>;
49    }
50
51    #[cfg(unix)]
52    impl IsSupported<&'static dyn std::os::fd::AsFd> for () {
53        type Type = Box<dyn std::os::fd::AsFd + Unpin>;
54    }
55
56    #[cfg(unix)]
57    // This one has buggy bounds in the rust stdlib
58    impl IsSupported<&'static dyn std::os::fd::AsRawFd> for () {
59        type Type = std::os::fd::RawFd;
60    }
61
62    #[cfg(windows)]
63    impl IsSupported<&'static dyn std::os::windows::io::AsHandle> for () {
64        type Type = std::os::windows::io::OwnedHandle;
65    }
66
67    #[cfg(windows)]
68    impl IsSupported<&'static dyn std::os::windows::io::AsRawHandle> for () {
69        type Type = std::os::windows::io::OwnedHandle;
70    }
71
72    #[cfg(windows)]
73    impl IsSupported<&'static dyn std::os::windows::io::AsSocket> for () {
74        type Type = std::os::windows::io::OwnedSocket;
75    }
76
77    #[cfg(windows)]
78    impl IsSupported<&'static dyn std::os::windows::io::AsRawSocket> for () {
79        type Type = std::os::windows::io::OwnedSocket;
80    }
81}
82
83#[doc(hidden)]
84#[macro_export]
85macro_rules! __derive_io_read_parse {
86    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
87        const _: &str = stringify!( generics = $generics, where = $($where)* );
88        $crate::__derive_impl!(__parse_type__ Read $generics ($($where)*) read $($input)*);
89    };
90}
91
92#[doc(hidden)]
93#[macro_export]
94macro_rules! __derive_io_bufread_parse {
95    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
96        const _: &str = stringify!( generics = $generics, where = $($where)* );
97        $crate::__derive_impl!(__parse_type__ BufRead $generics ($($where)*) read $($input)*);
98    };
99}
100
101#[doc(hidden)]
102#[macro_export]
103macro_rules! __derive_io_write_parse {
104    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
105        const _: &str = stringify!( generics = $generics, where = $($where)* );
106        $crate::__derive_impl!(__parse_type__ Write $generics ($($where)*) write $($input)*);
107    };
108}
109
110#[doc(hidden)]
111#[macro_export]
112macro_rules! __derive_io_async_read_parse {
113    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
114        const _: &str = stringify!( generics = $generics, where = $($where)* );
115        $crate::__derive_impl!(__parse_type__ AsyncRead $generics ($($where)*) read $($input)*);
116    };
117}
118
119#[doc(hidden)]
120#[macro_export]
121macro_rules! __derive_io_async_write_parse {
122    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
123        const _: &str = stringify!( generics = $generics, where = $($where)* );
124        $crate::__derive_impl!(__parse_type__ AsyncWrite $generics ($($where)*) write $($input)*);
125    };
126}
127
128#[doc(hidden)]
129#[macro_export]
130macro_rules! __derive_io_as_file_descriptor_parse {
131    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
132        const _: &str = stringify!( generics = $generics, where = $($where)* );
133        $crate::__derive_impl!(__parse_type__ AsFileDescriptor $generics ($($where)*) descriptor $($input)*);
134    };
135}
136
137#[doc(hidden)]
138#[macro_export]
139macro_rules! __derive_io_as_socket_descriptor_parse {
140    ( ($($input:tt)*) $generics:tt ($($where:tt)*) ) => {
141        const _: &str = stringify!( generics = $generics, where = $($where)* );
142        $crate::__derive_impl!(__parse_type__ AsSocketDescriptor $generics ($($where)*) descriptor $($input)*);
143    };
144}
145
146#[doc(hidden)]
147#[macro_export]
148macro_rules! __derive_impl {
149    // Parse enum types, identifying annotated fields. Next macro: __process_derive__
150    ( __parse_type__ $generator:ident $generics:tt $where:tt $attr:ident
151        $(#[$eattr:meta])* $vis:vis enum $name:ident {
152            $( $(#[$iattr:meta])* $field:ident
153                $( ( $($(#[$tuple_attr:meta])* $tuple_type:ty),* $(,)?) )?
154                $( { $($(#[$struct_attr:meta])* $struct_name:ident : $struct_type:ty),* $(,)? } )?
155            ),*
156            $(,)?
157        }
158    ) => {
159        $crate::__support::find_annotated_multi!(
160            ($crate::__derive_impl)
161            (__process_derive__ $generator $attr $generics $where enum $name)
162            $attr
163            {
164                compile_error!(concat!("No #[", stringify!($attr), "] field found"));
165            }
166            $(
167                (
168                    (Self::$field)
169                    $(
170                        $(
171                            (($([$tuple_attr])*)
172                            (type $tuple_type))
173                        )*
174                    )?
175                    $(
176                        $(
177                            (($([$struct_attr])*)
178                            (type $struct_type:($struct_name)))
179                        )*
180                    )?
181                )
182            )*
183        );
184    };
185
186    // Parse named 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])* $fvis:vis $fname:ident : $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)
198                $( (($([$fattr])*) (type $ftype: ($fname))) )*
199                (($([$sattr])*) (: (this)))
200            )
201        );
202    };
203
204    // Parse tuple structs, identifying annotated fields. Next macro: __process_derive__
205    ( __parse_type__ $generator:ident $generics:tt $where:tt $attr:ident
206        $(#[$sattr:meta])* $vis:vis struct $name:ident ( $( $(#[$fattr:meta])* $fvis:vis $ftype:ty ),* $(,)? );
207    ) => {
208        $crate::__support::find_annotated_multi!(
209            ($crate::__derive_impl)
210            (__process_derive__ $generator $attr $generics $where struct $name)
211            $attr
212            {
213                compile_error!(concat!("No #[", stringify!($attr), "] field found"));
214            }
215            ((Self)
216                $( (($([$fattr])*) (type $ftype)) )*
217            )
218        );
219    };
220
221    // Process the identified annotated fields. Next macro: __generate__ $generator
222    // Note that the input here is:
223    //   (case) index [attr] (type : name)
224    ( (__process_derive__ $generator:ident $attr:ident $generics:tt $where:tt $type:ident $name:ident) (
225        $( ( ($case:path) $index:literal $fattr:tt ( $( type $ftype:ty )? $( : ($fname:ident) )? ) ) )*
226    )) => {
227        const _: &str = stringify!( $type $name {
228            $(
229                # $fattr ($case) => $crate::__derive_impl!(__expand__ $attr ($case) $index $($ftype)? $(: $fname)?)
230            )*
231        });
232
233        $crate::__derive_impl!(__generate__ $generator $attr $generics $where ($($($ftype)?)*)
234            $type $name {
235                $(
236                    # $fattr ($case) => $crate::__derive_impl!(__expand__ $attr ($case) $index $($ftype)? $(: $fname)?)
237                )*
238            }
239        );
240    };
241
242    // Generate the impl block for Read. Next macro: __impl__
243    ( __generate__ Read $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
244        $crate::__derive_impl!(__impl__ ::std::io::Read : $name $generics $where $ftypes #[read] {
245            fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
246                let $this = self;
247                $crate::__derive_impl!(__foreach__ mut $this (::std::io::Read read($this, buf)) $struct)
248            }
249        });
250    };
251
252    // Generate the impl block for BufRead. Next macro: __impl__
253    ( __generate__ BufRead $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
254        $crate::__derive_impl!(__impl__ ::std::io::BufRead : $name $generics $where $ftypes #[read] {
255            fn fill_buf(&mut self) -> ::std::io::Result<&[u8]> {
256                let $this = self;
257                $crate::__derive_impl!(__foreach__ mut $this (::std::io::BufRead fill_buf($this)) $struct)
258            }
259
260            fn consume(&mut self, amt: usize) {
261                let $this = self;
262                $crate::__derive_impl!(__foreach__ mut $this (::std::io::BufRead consume($this, amt)) $struct)
263            }
264
265            // Not yet stable!
266            // fn has_data_left(&mut self) -> ::std::io::Result<bool> {
267            //     let $this = self;
268            //     $crate::__derive_impl!(__foreach__ mut $this (::std::io::BufRead has_data_left($this)) $struct)
269            // }
270
271            fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> ::std::io::Result<usize> {
272                let $this = self;
273                $crate::__derive_impl!(__foreach__ mut $this (::std::io::BufRead read_until($this, byte, buf)) $struct)
274            }
275
276            fn skip_until(&mut self, byte: u8) -> ::std::io::Result<usize> {
277                let $this = self;
278                $crate::__derive_impl!(__foreach__ mut $this (::std::io::BufRead skip_until($this, byte)) $struct)
279            }
280
281            fn read_line(&mut self, buf: &mut String) -> ::std::io::Result<usize> {
282                let $this = self;
283                $crate::__derive_impl!(__foreach__ mut $this (::std::io::BufRead read_line($this, buf)) $struct)
284            }
285
286            // Unimplemented because we cannot construct our own `Split`
287            // fn split(self, byte: u8) -> ::std::io::Split<Self> {
288            //     let $this = self;
289            //     $crate::__derive_impl!(__foreach__ take $this (::std::io::BufRead split($this, byte)) $struct)
290            // }
291
292            // Unimplemented because we cannot construct our own `Lines`
293            // fn lines(self) -> ::std::io::Lines<Self> {
294            //     let $this = self;
295            //     $crate::__derive_impl!(__foreach__ take $this (::std::io::BufRead lines($this)) $struct)
296            // }
297        });
298    };
299
300    // Generate the impl block for Write. Next macro: __impl__
301    ( __generate__ Write $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
302        $crate::__derive_impl!(__impl__ ::std::io::Write : $name $generics $where $ftypes #[write] {
303            fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
304                let $this = self;
305                $crate::__derive_impl!(__foreach__ mut $this (::std::io::Write write($this, buf)) $struct)
306            }
307            fn flush(&mut self) -> ::std::io::Result<()> {
308                let $this = self;
309                $crate::__derive_impl!(__foreach__ mut $this (::std::io::Write flush($this)) $struct)
310            }
311        });
312    };
313
314    // Generate the impl block for AsyncRead. Next macro: __impl__
315    ( __generate__ AsyncRead $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
316        $crate::__derive_impl!(__impl__ ::tokio::io::AsyncRead : $name $generics $where $ftypes #[read] {
317            #[inline]
318            fn poll_read(
319                mut self: ::std::pin::Pin<&mut Self>,
320                cx: &mut ::std::task::Context<'_>,
321                buf: &mut ::tokio::io::ReadBuf<'_>,
322            ) -> ::std::task::Poll<::std::io::Result<()>> {
323                let $this = self;
324                $crate::__derive_impl!(__foreach_pin__ mut $this (::tokio::io::AsyncRead poll_read($this, cx, buf)) $struct)
325            }
326        });
327    };
328
329    // Generate the impl block for AsyncWrite. Next macro: __impl__
330    ( __generate__ AsyncWrite $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
331        $crate::__derive_impl!(__impl__ ::tokio::io::AsyncWrite : $name $generics $where $ftypes #[write] {
332            #[inline]
333            fn poll_write(
334                self: ::std::pin::Pin<&mut Self>,
335                cx: &mut ::std::task::Context<'_>,
336                buf: &[u8],
337            ) -> ::std::task::Poll<::std::io::Result<usize>> {
338                let $this = self;
339                $crate::__derive_impl!(__foreach_pin__ mut $this (::tokio::io::AsyncWrite poll_write($this, cx, buf)) $struct)
340            }
341
342            #[inline]
343            fn poll_flush(
344                self: ::std::pin::Pin<&mut Self>,
345                cx: &mut ::std::task::Context<'_>,
346            ) -> ::std::task::Poll<::std::io::Result<()>> {
347                let $this = self;
348                $crate::__derive_impl!(__foreach_pin__ mut$this (::tokio::io::AsyncWrite poll_flush($this, cx)) $struct)
349            }
350
351            #[inline]
352            fn poll_shutdown(
353                self: ::std::pin::Pin<&mut Self>,
354                cx: &mut ::std::task::Context<'_>,
355            ) -> ::std::task::Poll<::std::io::Result<()>> {
356                let $this = self;
357                $crate::__derive_impl!(__foreach_pin__ mut $this (::tokio::io::AsyncWrite poll_shutdown($this, cx)) $struct)
358            }
359
360            #[inline]
361            fn is_write_vectored(&self) -> bool {
362                let $this = self;
363                $crate::__derive_impl!(__foreach__ ref $this (::tokio::io::AsyncWrite is_write_vectored($this)) $struct)
364            }
365
366            #[inline]
367            fn poll_write_vectored(
368                self: ::std::pin::Pin<&mut Self>,
369                cx: &mut ::std::task::Context<'_>,
370                bufs: &[::std::io::IoSlice<'_>],
371            ) -> ::std::task::Poll<::std::io::Result<usize>> {
372                let $this = self;
373                $crate::__derive_impl!(__foreach_pin__ mut $this (::tokio::io::AsyncWrite poll_write_vectored($this, cx, bufs)) $struct)
374            }
375        });
376    };
377
378    // std::os::fd::{AsFd, AsRawFd}, std::os::windows::io::{AsHandle, AsRawHandle}
379    ( __generate__ AsFileDescriptor $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
380        #[cfg(unix)]
381        $crate::__derive_impl!(__impl__ ::std::os::fd::AsFd : $name $generics $where $ftypes #[read] {
382            fn as_fd(&self) -> ::std::os::fd::BorrowedFd<'_> {
383                let $this = self;
384                $crate::__derive_impl!(__foreach__ ref $this (::std::os::fd::AsFd as_fd($this)) $struct)
385            }
386        });
387        #[cfg(unix)]
388        $crate::__derive_impl!(__impl__ ::std::os::fd::AsRawFd : $name $generics $where $ftypes #[read] {
389            fn as_raw_fd(&self) -> ::std::os::fd::RawFd {
390                let $this = self;
391                $crate::__derive_impl!(__foreach__ ref $this (::std::os::fd::AsRawFd as_raw_fd($this)) $struct)
392            }
393        });
394        #[cfg(windows)]
395        $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsRawHandle : $name $generics $where $ftypes #[read] {
396            fn as_raw_handle(&self) -> ::std::os::windows::io::RawHandle {
397                let $this = self;
398                $crate::__derive_impl!(__foreach__ ref $this (::std::os::windows::io::AsRawHandle as_raw_handle($this)) $struct)
399            }
400        });
401        #[cfg(windows)]
402        $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsHandle : $name $generics $where $ftypes #[read] {
403            fn as_handle(&self) -> ::std::os::windows::io::BorrowedHandle<'_> {
404                let $this = self;
405                $crate::__derive_impl!(__foreach__ ref $this (::std::os::windows::io::AsHandle as_handle($this)) $struct)
406            }
407        });
408    };
409
410    // std::os::fd::{AsFd, AsRawFd}, std::os::windows::io::{AsSocket, AsRawSocket}
411    ( __generate__ AsSocketDescriptor $this:ident $generics:tt $where:tt $ftypes:tt $type:ident $name:ident $struct:tt) => {
412        #[cfg(unix)]
413        $crate::__derive_impl!(__impl__ ::std::os::fd::AsFd : $name $generics $where $ftypes #[read] {
414            fn as_fd(&self) -> ::std::os::fd::BorrowedFd<'_> {
415                let $this = self;
416                $crate::__derive_impl!(__foreach__ ref $this (::std::os::fd::AsFd as_fd($this)) $struct)
417            }
418        });
419        #[cfg(unix)]
420        $crate::__derive_impl!(__impl__ ::std::os::fd::AsRawFd : $name $generics $where $ftypes #[read] {
421            fn as_raw_fd(&self) -> ::std::os::fd::RawFd {
422                let $this = self;
423                $crate::__derive_impl!(__foreach__ ref $this (::std::os::fd::AsRawFd as_raw_fd($this)) $struct)
424            }
425        });
426        #[cfg(windows)]
427        $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsSocket : $name $generics $where $ftypes #[read] {
428            fn as_socket(&self) -> ::std::os::windows::io::BorrowedSocket<'_> {
429                let $this = self;
430                $crate::__derive_impl!(__foreach__ ref $this (::std::os::windows::io::AsSocket as_socket($this)) $struct)
431            }
432        });
433        #[cfg(windows)]
434        $crate::__derive_impl!(__impl__ ::std::os::windows::io::AsRawSocket : $name $generics $where $ftypes #[read] {
435            fn as_raw_socket(&self) -> ::std::os::windows::io::RawSocket {
436                let $this = self;
437                $crate::__derive_impl!(__foreach__ ref $this (::std::os::windows::io::AsRawSocket as_raw_socket($this)) $struct)
438            }
439        });
440    };
441
442    // Duplicate the $generics block. Next macro: __impl_2__
443    ( __impl__ $trait:path : $name:ident $generics:tt ($($where:tt)*) ($($ftype:path)*) #[$attr:ident] $block:tt) => {
444        $crate::__derive_impl!(__impl_2__ $trait : $name $generics $generics ($($where)*) ($($ftype)*) #[$attr] $block);
445    };
446
447    // Final macro. Generate the impl block.
448    ( __impl_2__ $trait:path : $name:ident $generics:tt ( $( ($($generic:tt)*) ),* ) ($($where:tt)*) ($($ftype:path)*) #[$attr:ident] $block:tt) => {
449        impl <$($($generic)*),*> $trait for $name <$($($generic)*),*>
450            where
451                // Add a where clause for each stream type. If it contains a generic, constrain it otherwise
452                // use a placeholder type that implements the trait for certain.
453                $(
454                    $crate::__support::type_has_generic!(
455                        ($ftype)
456                        $generics
457                        ($ftype)
458                        (<() as $crate::__support::IsSupported::<&'static dyn $trait>>::Type)
459                    ) : $trait,
460                )*
461                $($where)*
462        $block
463    };
464
465    // Expand a self access pattern.
466    ( __expand__ $this:ident ($case:path) $index:literal : this) => {
467        {
468            $this
469        }
470     };
471
472    // Expand a named field to an access pattern.
473    ( __expand__ $this:ident ($case:path) $index:literal $ftype:ty : $fname:tt) => {
474        {
475            let $case { $fname, .. } = $this else {
476                unreachable!()
477            };
478            $fname
479        }
480     };
481
482    // Expand a tuple field to an access pattern.
483    ( __expand__ $this:ident ($case:path) $index:literal $ftype:ty) => {
484        {
485            let $crate::__support::repeat_in_parenthesis!(($case) $index (_,) ($this, .. )) = $this else {
486                unreachable!()
487            };
488            $this
489        }
490    };
491
492    ( __foreach__ $refmut:tt $this:ident $fn:tt {$(
493        # $attr:tt ($case:path) => $access:expr
494    )*}) =>{
495        {
496            match $this {
497                $( $case {..} => {
498                    $crate::__derive_impl!(__validate_macro__ # $attr);
499                    $crate::__support::if_meta!(
500                        as_ref
501                        $attr
502                        ({
503                            let $this = $access.as_ref();
504                            $crate::__derive_impl!(__foreach_inner__ $refmut # $attr $fn)
505                        })
506                        ($crate::__support::if_meta!(
507                            deref
508                            $attr
509                            ({
510                                let $this = ::std::ops::Deref::deref($access);
511                                $crate::__derive_impl!(__foreach_inner__ $refmut # $attr $fn)
512                            })
513                            ($crate::__support::if_meta!(
514                                duck
515                                $attr
516                                ({
517                                    let $this = $access;
518                                    $crate::__derive_impl!(__foreach_inner_duck__ unpin $refmut # $attr $fn)
519                                })
520                                ({
521                                    let $this = $access;
522                                    $crate::__derive_impl!(__foreach_inner__ $refmut # $attr $fn)
523                                })
524                            ))
525                        ))
526                    )
527                } )*
528            }
529        }
530    };
531
532    ( __foreach_pin__ $refmut:tt $this:ident $fn:tt {$(
533        # $attr:tt ($case:path) => $access:expr
534    )*}) =>{
535        {
536            match &*$this {
537                $( $case {..} => {
538                    $crate::__derive_impl!(__validate_macro__ # $attr);
539                    $crate::__support::if_meta!(
540                        as_ref
541                        $attr
542                        ({
543                            // NOTE: as_ref requires Unpin for safety
544                            let mut $this = $this.get_mut();
545                            let mut $this = ::std::pin::Pin::new($access);
546                            let $this = ::std::pin::Pin::new($this.get_mut().as_mut());
547                            $crate::__derive_impl!(__foreach_inner__ $refmut # $attr $fn)
548                        })
549                        ($crate::__support::if_meta!(
550                            deref
551                            $attr
552                            ({
553                                // NOTE: as_mut requires Unpin for safety
554                                let mut $this = $this.get_mut();
555                                let mut $this = ::std::ops::DerefMut::deref_mut($access);
556                                let $this = ::std::pin::Pin::new($this);
557                                $crate::__derive_impl!(__foreach_inner__ $refmut # $attr $fn)
558                            })
559                            ($crate::__support::if_meta!(
560                                duck
561                                $attr
562                                ({
563                                    // NOTE: duck typing requires Unpin for safety
564                                    let mut $this = $this.get_mut();
565                                    let mut $this = ::std::pin::Pin::new($access);
566                                    $crate::__derive_impl!(__foreach_inner_duck__ pin $refmut # $attr $fn)
567                                })
568                                ({
569                                    // SAFETY: we are mapping this pin to a
570                                    // nested field which must be `Unpin`.
571                                    // Because we are delegating to methods that
572                                    // never uses mutable references that aren't
573                                    // pinned, this is safe.
574                                    let mut $this = (unsafe { $this.get_unchecked_mut() });
575                                    let mut $this = (unsafe { ::std::pin::Pin::new_unchecked($access) });
576                                    $crate::__derive_impl!(__foreach_inner__ $refmut # $attr $fn)
577                                })
578                            ))
579                        ))
580                    )
581                } )*
582            }
583        }
584    };
585
586    ( __foreach_inner__ $refmut:tt # $attr:tt ( $( :: $fn_part:ident )+ $fn_final:ident ( $($arg:expr),* ) ) ) => {
587        // needle, haystack, default
588        {
589            $crate::__support::extract_meta!(
590                $fn_final
591                $attr
592                ($(::$fn_part)+ :: $fn_final )
593            ) ($($arg),*)
594        }
595    };
596
597    ( __foreach_inner_duck__ unpin ref # $attr:tt ( $( :: $fn_part:ident )+ $fn_final:ident ( $arg0:expr $(, $arg:expr)* ) ) ) => {
598        // needle, haystack, default
599        {
600            $crate::__support::extract_meta!(
601                $fn_final
602                $attr
603                ( Self :: $fn_final( ($arg0) $(, $arg)*) )
604            )
605        }
606    };
607
608    ( __foreach_inner_duck__ unpin mut # $attr:tt ( $( :: $fn_part:ident )+ $fn_final:ident ( $arg0:expr $(, $arg:expr)* ) ) ) => {
609        // needle, haystack, default
610        {
611            $crate::__support::extract_meta!(
612                $fn_final
613                $attr
614                ( Self :: $fn_final( ($arg0) $(, $arg)*) )
615            )
616        }
617    };
618
619    ( __foreach_inner_duck__ $pin:tt ref # $attr:tt ( $( :: $fn_part:ident )+ $fn_final:ident ( $arg0:expr $(, $arg:expr)* ) ) ) => {
620        {
621            // I don't think anyone uses these...
622            unimplemented!("pin ref duck type is not yet supported");
623        }
624    };
625
626    ( __foreach_inner_duck__ $pin:tt mut # $attr:tt ( $( :: $fn_part:ident )+ $fn_final:ident ( $arg0:expr $(, $arg:expr)* ) ) ) => {
627        {
628            // Choose the correct pointer for the receiver via trait.
629            #[allow(non_camel_case_types)]
630            trait __Derive_Io_Coerce<T, U> {
631                fn __derive_io_coerce(this: T) -> U;
632            }
633            impl<'a, T> __Derive_Io_Coerce<::std::pin::Pin<&'a mut T>, &'a mut T> for ::std::pin::Pin<&'a mut T> where T: Unpin {
634                fn __derive_io_coerce(this: ::std::pin::Pin<&'a mut T>) -> &'a mut T {
635                    this.get_mut()
636                }
637            }
638            impl<'a, T> __Derive_Io_Coerce<::std::pin::Pin<&'a mut T>, ::std::pin::Pin<&'a mut T>> for ::std::pin::Pin<&'a mut T> {
639                fn __derive_io_coerce(this: ::std::pin::Pin<&'a mut T>) -> ::std::pin::Pin<&'a mut T> {
640                    this
641                }
642            }
643
644            let self_type = $arg0;
645            let self_type = <::std::pin::Pin<&mut Self> as __Derive_Io_Coerce<_, _>>::__derive_io_coerce(self_type);
646
647            // needle, haystack, default
648            let callable = $crate::__support::extract_meta!(
649                $fn_final
650                $attr
651                (Self :: $fn_final)
652            );
653
654            callable(self_type $(, $arg)*)
655        }
656    };
657
658    ( __validate_macro__ #[read]) => {
659    };
660
661    ( __validate_macro__ #[read($( as_ref )? $(,)? $( deref )? $(,)? $( duck )? $(,)? $( poll_read=$poll_read:ident )? )]) => {
662    };
663
664    ( __validate_macro__ #[write]) => {
665    };
666
667    ( __validate_macro__ #[write($($key:ident $(=$value:ident)?),* $(,)?)]) => {
668        $crate::__derive_impl!(__validate_macro_deep__ #[write($($key $(=$value)?),*)]);
669    };
670
671    ( __validate_macro_deep__ #[write(
672        $( as_ref )? $(,)?
673        $( deref )? $(,)?
674        $( duck )? $(,)?
675        $( poll_write=$poll_write:ident )? $(,)?
676        $( poll_flush=$poll_flush:ident )? $(,)?
677        $( poll_shutdown=$poll_shutdown:ident )? $(,)?
678        $( is_write_vectored=$is_write_vectored:ident )? $(,)?
679        $( poll_write_vectored=$poll_write_vectored:ident )?
680    )]) => {
681    };
682
683    ( __validate_macro_deep__ # $($rest:tt)*) => {
684        compile_error!(concat!("Invalid #", stringify!($($rest)*), " attribute"));
685    };
686
687    ( __validate_macro__ #[descriptor]) => {
688    };
689
690    ( __validate_macro__ #[descriptor(as_ref)]) => {
691    };
692
693    ( __validate_macro__ #[descriptor(deref)]) => {
694    };
695
696    ( __validate_macro__ # $attr:tt) => {
697        compile_error!(concat!("Invalid #", stringify!($attr), " attribute"));
698    };
699}