agnostic_net/
lib.rs

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_async_std, cfg_smol, cfg_tokio};
7use futures_util::Future;
8use std::net::SocketAddr;
9
10pub use agnostic_lite as runtime;
11
12/// Operating system specific types and traits.
13#[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 = "async-std", 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 = "async-std", 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
86/// Traits, helpers, and type definitions for asynchronous I/O functionality.
87pub 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(any(feature = "smol", feature = "async-std"))]
103#[macro_use]
104mod async_io;
105
106cfg_tokio!(
107  /// Network abstractions for [`tokio`] runtime
108  ///
109  /// [`tokio`]: https://docs.rs/tokio
110  pub mod tokio;
111);
112
113cfg_smol!(
114  /// Network abstractions for [`smol`] runtime
115  ///
116  /// [`smol`]: https://docs.rs/smol
117  pub mod smol;
118);
119
120cfg_async_std!(
121  /// Network abstractions for [`async-std`] runtime
122  ///
123  /// [`async-std`]: https://docs.rs/async-std
124  pub mod async_std;
125);
126
127#[doc(hidden)]
128#[cfg(unix)]
129pub trait Fd: os::AsFd + os::AsRawFd {
130  fn __as(&self) -> os::BorrowedFd<'_> {
131    self.as_fd()
132  }
133
134  fn __as_raw(&self) -> os::RawFd {
135    self.as_raw_fd()
136  }
137}
138
139#[cfg(unix)]
140impl<T> Fd for T where T: os::AsFd + os::AsRawFd {}
141
142#[doc(hidden)]
143#[cfg(windows)]
144pub trait Fd: os::AsRawSocket + os::AsSocket {
145  fn __as(&self) -> os::BorrowedSocket<'_> {
146    self.as_socket()
147  }
148
149  fn __as_raw(&self) -> os::RawSocket {
150    self.as_raw_socket()
151  }
152}
153
154#[cfg(windows)]
155impl<T> Fd for T where T: os::AsRawSocket + os::AsSocket {}
156
157#[cfg(not(any(unix, windows)))]
158pub trait Fd {}
159
160#[cfg(not(any(unix, windows)))]
161impl<T> Fd for T {}
162
163/// Converts or resolves without blocking base on your async runtime to one or more `SocketAddr` values.
164///
165/// # DNS
166///
167/// Implementations of `ToSocketAddrs<R>` for string types require a DNS lookup.
168pub trait ToSocketAddrs<R>: Send + Sync {
169  /// Returned iterator over socket addresses which this type may correspond to.
170  type Iter: Iterator<Item = SocketAddr> + Send + 'static;
171  /// The future type used to resolve addresses.
172  type Future: Future<Output = io::Result<Self::Iter>> + Send + 'static;
173
174  /// Converts this object to an iterator of resolved `SocketAddr`s.
175  ///
176  /// The returned iterator may not actually yield any values depending on the outcome of any
177  /// resolution performed.
178  ///
179  /// Note that this function may block a backend thread while resolution is performed.
180  fn to_socket_addrs(&self) -> Self::Future
181  where
182    R: RuntimeLite;
183}
184
185/// An abstraction layer for the async runtime's network.
186pub trait Net: Unpin + Send + Sync + 'static {
187  /// The runtime type
188  type Runtime: RuntimeLite;
189
190  /// The [`TcpListener`] implementation
191  type TcpListener: TcpListener<Stream = Self::TcpStream, Runtime = Self::Runtime>;
192  /// The [`TcpStream`] implementation
193  type TcpStream: TcpStream<Runtime = Self::Runtime>;
194  /// The [`UdpSocket`] implementation
195  type UdpSocket: UdpSocket<Runtime = Self::Runtime>;
196}