orb/io/
mod.rs

1//! Asynchronous I/O traits and utilities.
2//!
3//! This module provides traits for performing asynchronous I/O operations
4//! in a runtime-agnostic way. It includes functionality for connecting to
5//! network services, working with file descriptors, and performing async
6//! read/write operations.
7//!
8//! Further more, we have abstract buffered I/O  with [AsyncBufRead], [AsyncBufWrite], and [AsyncBufStream]
9//!
10//! # Design Notes
11//!
12//! We choose to provide `async fn` style IO function instead of `poll_xxx` style functions, because:
13//!
14//! - `async-io` crate don't have `poll_xxx` interfaces
15//! - `poll_xxx` functions is pre-async-await stuff and difficult to use.
16//! - you can always make an async fn with `poll_xxx`
17//!
18//! We choose to abstract [AsyncFd] instead of stream, because:
19//! - All async stream can be converted between std version of stream
20//! - All types of files/streams and be converted between OS raw fd.
21//! - There's slight difference between tokio stream and async-io counterparts.
22//! - What we do here is just wrap any std blocking function with async poller when they are
23//! readable or writeable, similar with `async-io`, as a light-weight implementation.
24
25use std::future::Future;
26use std::io;
27use std::net::SocketAddr;
28use std::net::TcpStream;
29use std::ops::Deref;
30use std::os::fd::{AsFd, AsRawFd};
31use std::os::unix::net::UnixStream;
32use std::path::PathBuf;
33
34mod buf_io;
35pub use buf_io::{AsyncBufRead, AsyncBufStream, AsyncBufWrite, AsyncRead, AsyncWrite};
36
37/// Trait for async I/O operations.
38///
39/// This trait defines the interface for performing asynchronous I/O operations
40/// such as connecting to network services and converting file descriptors to
41/// async handles.
42///
43/// # Associated Types
44///
45/// * `AsyncFd` - The type used to represent async file descriptors
46pub trait AsyncIO: Send + Sync + 'static {
47    /// The type used to represent async file descriptors.
48    ///
49    /// This associated type represents a wrapper around a file descriptor
50    /// that provides async read/write operations.
51    type AsyncFd<T: AsRawFd + AsFd + Send + Sync + 'static>: AsyncFd<T>;
52
53    /// Connect to a TCP address asynchronously.
54    ///
55    /// # NOTE
56    ///
57    /// This is for runtime implementation, for user should use [`TcpStream::<IO>::connect()`](crate::net::TcpStream) instead**.
58    ///
59    /// This method attempts to establish a TCP connection to the specified
60    /// address, returning an async file descriptor that can be used for
61    /// communication.
62    ///
63    /// # Parameters
64    ///
65    /// * `addr` - The socket address to connect to
66    ///
67    /// # Returns
68    ///
69    /// A future that resolves to a `Result` containing either the connected
70    /// async file descriptor or an I/O error.
71    fn connect_tcp(
72        addr: &SocketAddr,
73    ) -> impl Future<Output = io::Result<Self::AsyncFd<TcpStream>>> + Send;
74
75    /// Connect to a Unix socket address asynchronously.
76    ///
77    /// # NOTE
78    ///
79    /// This is for runtime implementation, for user should use [`UnixStream::<IO>::connect()`](crate::net::UnixStream) instead**.
80    ///
81    /// This method attempts to establish a Unix socket connection to the
82    /// specified path, returning an async file descriptor that can be used
83    /// for communication.
84    ///
85    /// # Parameters
86    ///
87    /// * `addr` - The path to the Unix socket
88    ///
89    /// # Returns
90    ///
91    /// A future that resolves to a `Result` containing either the connected
92    /// async file descriptor or an I/O error.
93    fn connect_unix(
94        addr: &PathBuf,
95    ) -> impl Future<Output = io::Result<Self::AsyncFd<UnixStream>>> + Send;
96
97    /// Wrap a readable file object as an async handle
98    ///
99    /// The file descriptor will subscribe for read
100    /// to the runtime poller
101    ///
102    /// # Parameters
103    ///
104    /// * `fd` - The file descriptor to wrap
105    ///
106    /// # Returns
107    ///
108    /// A `Result` containing either the async file descriptor handle or
109    /// an I/O error.
110    ///
111    /// # Safety
112    ///
113    /// The file descriptor must be set to non-blocking mode before calling
114    /// this method.
115    fn to_async_fd_rd<T: AsRawFd + AsFd + Send + Sync + 'static>(
116        fd: T,
117    ) -> io::Result<Self::AsyncFd<T>>;
118
119    /// Wrap a readable/writable file object as an async handle.
120    ///
121    /// The file descriptor will subscribe for read + write
122    /// to the runtime poller
123    ///
124    /// # Parameters
125    ///
126    /// * `fd` - The file descriptor to wrap
127    ///
128    /// # Returns
129    ///
130    /// A `Result` containing either the async file descriptor handle or
131    /// an I/O error.
132    ///
133    /// # Safety
134    ///
135    /// The file descriptor must be set to non-blocking mode before calling
136    /// this method.
137    fn to_async_fd_rw<T: AsRawFd + AsFd + Send + Sync + 'static>(
138        fd: T,
139    ) -> io::Result<Self::AsyncFd<T>>;
140}
141
142/// Trait for async file descriptor operations.
143///
144/// This trait provides methods for performing async read and write operations
145/// on file descriptors.
146///
147/// # Type Parameters
148///
149/// * `T` - The underlying file descriptor type
150pub trait AsyncFd<T: AsRawFd + AsFd + Send + Sync + 'static>:
151    Send + Sync + 'static + Deref<Target = T>
152{
153    /// Perform an async read operation.
154    ///
155    /// This method executes the provided closure asynchronously, allowing
156    /// it to perform read operations on the underlying file descriptor.
157    ///
158    /// # Parameters
159    ///
160    /// * `f` - A closure that performs the actual read operation
161    ///
162    /// # Returns
163    ///
164    /// A future that resolves to the result of the read operation.
165    fn async_read<R>(
166        &self, f: impl FnMut(&T) -> io::Result<R> + Send,
167    ) -> impl Future<Output = io::Result<R>> + Send;
168
169    /// Perform an async write operation.
170    ///
171    /// This method executes the provided closure asynchronously, allowing
172    /// it to perform write operations on the underlying file descriptor.
173    ///
174    /// # Parameters
175    ///
176    /// * `f` - A closure that performs the actual write operation
177    ///
178    /// # Returns
179    ///
180    /// A future that resolves to the result of the write operation.
181    fn async_write<R>(
182        &self, f: impl FnMut(&T) -> io::Result<R> + Send,
183    ) -> impl Future<Output = io::Result<R>> + Send;
184}
185
186impl<F: std::ops::Deref<Target = IO> + Send + Sync + 'static, IO: AsyncIO> AsyncIO for F {
187    type AsyncFd<T: AsRawFd + AsFd + Send + Sync + 'static> = IO::AsyncFd<T>;
188
189    fn connect_tcp(
190        addr: &SocketAddr,
191    ) -> impl Future<Output = io::Result<Self::AsyncFd<TcpStream>>> + Send {
192        IO::connect_tcp(addr)
193    }
194
195    fn connect_unix(
196        addr: &PathBuf,
197    ) -> impl Future<Output = io::Result<Self::AsyncFd<UnixStream>>> + Send {
198        IO::connect_unix(addr)
199    }
200
201    fn to_async_fd_rd<T: AsRawFd + AsFd + Send + Sync + 'static>(
202        fd: T,
203    ) -> io::Result<Self::AsyncFd<T>> {
204        IO::to_async_fd_rd(fd)
205    }
206
207    fn to_async_fd_rw<T: AsRawFd + AsFd + Send + Sync + 'static>(
208        fd: T,
209    ) -> io::Result<Self::AsyncFd<T>> {
210        IO::to_async_fd_rw(fd)
211    }
212}