1#![doc = include_str!("../README.md")]
2#![deny(warnings, missing_docs)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![cfg_attr(docsrs, allow(unused_attributes))]
5
6use agnostic_lite::{RuntimeLite, cfg_smol, cfg_tokio};
7use futures_util::Future;
8use std::net::SocketAddr;
9
10pub use agnostic_lite as runtime;
11
12#[cfg_attr(windows, path = "windows.rs")]
14#[cfg_attr(unix, path = "unix.rs")]
15#[cfg_attr(not(any(unix, windows)), path = "unknown.rs")]
16pub mod os;
17
18#[cfg(any(feature = "smol", feature = "tokio"))]
19macro_rules! impl_as_raw_fd {
20 ($name:ident.$field:ident) => {
21 #[cfg(unix)]
22 impl $crate::os::AsRawFd for $name {
23 fn as_raw_fd(&self) -> $crate::os::RawFd {
24 self.$field.as_raw_fd()
25 }
26 }
27
28 #[cfg(windows)]
29 impl $crate::os::AsRawSocket for $name {
30 fn as_raw_socket(&self) -> $crate::os::RawSocket {
31 self.$field.as_raw_socket()
32 }
33 }
34 };
35}
36
37#[cfg(any(feature = "tokio", feature = "smol"))]
38macro_rules! impl_as_fd {
39 ($name:ident.$field:ident) => {
40 #[cfg(unix)]
41 impl $crate::os::AsFd for $name {
42 fn as_fd(&self) -> $crate::os::BorrowedFd<'_> {
43 self.$field.as_fd()
44 }
45 }
46
47 #[cfg(windows)]
48 impl $crate::os::AsSocket for $name {
49 fn as_socket(&self) -> $crate::os::BorrowedSocket<'_> {
50 self.$field.as_socket()
51 }
52 }
53 };
54}
55
56#[cfg(any(feature = "tokio", feature = "smol"))]
57macro_rules! impl_as {
58 ($name:ident.$field:ident) => {
59 impl_as_raw_fd!($name.$field);
60 impl_as_fd!($name.$field);
61 };
62}
63
64#[cfg(any(feature = "smol", feature = "tokio"))]
65macro_rules! call {
66 ($this:ident.$field:ident.$method:ident($buf:ident)) => {{
67 paste::paste! {
68 $this.$field.$method($buf).await
69 }
70 }};
71 (@send_to $this:ident.$field:ident($buf:ident, $target:ident)) => {{
72 paste::paste! {
73 let mut addrs = $crate::ToSocketAddrs::<Self::Runtime>::to_socket_addrs(&$target).await?;
74 if let ::core::option::Option::Some(addr) = addrs.next() {
75 $this.$field.send_to($buf, addr).await
76 } else {
77 return ::core::result::Result::Err(::std::io::Error::new(
78 ::std::io::ErrorKind::InvalidInput,
79 "invalid socket address",
80 ));
81 }
82 }
83 }};
84}
85
86pub use agnostic_io as io;
88
89mod to_socket_addrs;
90
91#[cfg(test)]
92mod tests;
93
94#[macro_use]
95mod tcp;
96#[macro_use]
97mod udp;
98
99pub use tcp::*;
100pub use udp::*;
101
102#[cfg(feature = "smol")]
103#[macro_use]
104mod async_io;
105
106cfg_tokio!(
107 pub mod tokio;
111);
112
113cfg_smol!(
114 pub mod smol;
118);
119
120#[doc(hidden)]
121#[cfg(unix)]
122pub trait Fd: os::AsFd + os::AsRawFd {
123 fn __as(&self) -> os::BorrowedFd<'_> {
124 self.as_fd()
125 }
126
127 fn __as_raw(&self) -> os::RawFd {
128 self.as_raw_fd()
129 }
130}
131
132#[cfg(unix)]
133impl<T> Fd for T where T: os::AsFd + os::AsRawFd {}
134
135#[doc(hidden)]
136#[cfg(windows)]
137pub trait Fd: os::AsRawSocket + os::AsSocket {
138 fn __as(&self) -> os::BorrowedSocket<'_> {
139 self.as_socket()
140 }
141
142 fn __as_raw(&self) -> os::RawSocket {
143 self.as_raw_socket()
144 }
145}
146
147#[cfg(windows)]
148impl<T> Fd for T where T: os::AsRawSocket + os::AsSocket {}
149
150#[cfg(not(any(unix, windows)))]
151pub trait Fd {}
152
153#[cfg(not(any(unix, windows)))]
154impl<T> Fd for T {}
155
156pub trait ToSocketAddrs<R>: Send + Sync {
162 type Iter: Iterator<Item = SocketAddr> + Send + 'static;
164 type Future: Future<Output = io::Result<Self::Iter>> + Send + 'static;
166
167 fn to_socket_addrs(&self) -> Self::Future
174 where
175 R: RuntimeLite;
176}
177
178pub trait Net: Unpin + Send + Sync + 'static {
180 type Runtime: RuntimeLite;
182
183 type TcpListener: TcpListener<Stream = Self::TcpStream, Runtime = Self::Runtime>;
185 type TcpStream: TcpStream<Runtime = Self::Runtime>;
187 type UdpSocket: UdpSocket<Runtime = Self::Runtime>;
189}