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 #[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 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_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_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_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_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__ 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__ 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__ 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__ 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 ( __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 ( __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 ( __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 ( __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 $(
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__ $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__ $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 {
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}