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}