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_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 = "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
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(feature = "smol")]
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
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
156/// Converts or resolves without blocking base on your async runtime to one or more `SocketAddr` values.
157///
158/// # DNS
159///
160/// Implementations of `ToSocketAddrs<R>` for string types require a DNS lookup.
161pub trait ToSocketAddrs<R>: Send + Sync {
162  /// Returned iterator over socket addresses which this type may correspond to.
163  type Iter: Iterator<Item = SocketAddr> + Send + 'static;
164  /// The future type used to resolve addresses.
165  type Future: Future<Output = io::Result<Self::Iter>> + Send + 'static;
166
167  /// Converts this object to an iterator of resolved `SocketAddr`s.
168  ///
169  /// The returned iterator may not actually yield any values depending on the outcome of any
170  /// resolution performed.
171  ///
172  /// Note that this function may block a backend thread while resolution is performed.
173  fn to_socket_addrs(&self) -> Self::Future
174  where
175    R: RuntimeLite;
176}
177
178/// An abstraction layer for the async runtime's network.
179pub trait Net: Unpin + Send + Sync + 'static {
180  /// The runtime type
181  type Runtime: RuntimeLite;
182
183  /// The [`TcpListener`] implementation
184  type TcpListener: TcpListener<Stream = Self::TcpStream, Runtime = Self::Runtime>;
185  /// The [`TcpStream`] implementation
186  type TcpStream: TcpStream<Runtime = Self::Runtime>;
187  /// The [`UdpSocket`] implementation
188  type UdpSocket: UdpSocket<Runtime = Self::Runtime>;
189}