tokio_splice2/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(feature = "feat-nightly", feature(cold_path))]
3#![cfg_attr(debug_assertions, allow(clippy::unreachable))]
4
5pub mod context;
6pub mod io;
7pub mod pipe;
8#[cfg(feature = "feat-rate-limit")]
9pub mod rate;
10pub mod traffic;
11pub mod utils;
12
13#[cfg(not(feature = "feat-rate-limit"))]
14pub mod rate {
15    //! TCP rate limiter implementation.
16    //!
17    //! This module provides a no-op implementation of the rate limiter if the
18    //! `feat-rate-limit` feature is not enabled.
19
20    #[allow(unused)]
21    pub(crate) const RATE_LIMITER_ENABLED: bool = true;
22    #[allow(unused)]
23    pub(crate) const RATE_LIMITER_DISABLED: bool = false;
24}
25
26pub use context::SpliceIoCtx;
27pub use io::{AsyncReadFd, AsyncWriteFd, IsFile, IsNotFile, SpliceBidiIo, SpliceIo};
28#[cfg(feature = "feat-rate-limit")]
29pub use rate::RateLimit;
30
31#[inline]
32/// Copies data from `r` to `w` using `splice(2)`.
33///
34/// See [`SpliceIoCtx::prepare`] and [`SpliceIo::execute`] for more details; see
35/// the [crate-level documentation](crate) for known limitations.
36///
37/// ## Errors
38///
39/// * Create pipe failed.
40pub async fn copy<R, W>(r: &mut R, w: &mut W) -> std::io::Result<traffic::TrafficResult>
41where
42    R: io::AsyncReadFd + IsNotFile + Unpin,
43    W: io::AsyncWriteFd + IsNotFile + Unpin,
44{
45    Ok(context::SpliceIoCtx::prepare()?
46        .into_io()
47        .execute(r, w)
48        .await)
49}
50
51#[inline]
52/// Copies data from file `r` to `w` using `splice(2)`.
53///
54/// See [`SpliceIoCtx::prepare_reading_file`] for more details; see the
55/// [crate-level documentation](crate) for known limitations.
56///
57/// ## Errors
58///
59/// * Create pipe failed.
60/// * Invalid file length or offset.
61pub async fn sendfile<R, W>(
62    r: &mut R,
63    w: &mut W,
64    f_len: u64,
65    f_offset_start: Option<u64>,
66    f_offset_end: Option<u64>,
67) -> std::io::Result<traffic::TrafficResult>
68where
69    R: io::AsyncReadFd + IsFile + Unpin,
70    W: io::AsyncWriteFd + IsNotFile + Unpin,
71{
72    Ok(
73        context::SpliceIoCtx::prepare_reading_file(f_len, f_offset_start, f_offset_end)?
74            .into_io()
75            .execute(r, w)
76            .await,
77    )
78}
79
80#[inline]
81/// Copies data in both directions between `sl` and `sr`.
82///
83/// This function returns a future that will read from both streams, writing any
84/// data read to the opposing stream. This happens in both directions
85/// concurrently.
86///
87/// See [`SpliceIoCtx::prepare`] and [`SpliceBidiIo::execute`] for more details;
88/// see the [crate-level documentation](crate) for known limitations.
89///
90/// ## Errors
91///
92/// * Create pipe failed.
93pub async fn copy_bidirectional<A, B>(
94    sl: &mut A,
95    sr: &mut B,
96) -> std::io::Result<traffic::TrafficResult>
97where
98    A: io::AsyncReadFd + io::AsyncWriteFd + IsNotFile + Unpin,
99    B: io::AsyncReadFd + io::AsyncWriteFd + IsNotFile + Unpin,
100{
101    Ok(io::SpliceBidiIo {
102        io_sl2sr: context::SpliceIoCtx::prepare()?.into_io(),
103        io_sr2sl: context::SpliceIoCtx::prepare()?.into_io(),
104    }
105    .execute(sl, sr)
106    .await)
107}
108
109// === Tracing macros for logging ===
110
111#[allow(unused)]
112macro_rules! trace {
113    ($($tt:tt)*) => {{
114        #[cfg(any(feature = "feat-tracing-trace", all(debug_assertions, feature = "feat-tracing")))]
115        tracing::trace!($($tt)*);
116    }};
117}
118
119#[allow(unused)]
120macro_rules! debug {
121    ($($tt:tt)*) => {{
122        #[cfg(feature = "feat-tracing")]
123        tracing::debug!($($tt)*);
124    }};
125}
126
127#[allow(unused)]
128macro_rules! info {
129    ($($tt:tt)*) => {{
130        #[cfg(feature = "feat-tracing")]
131        tracing::info!($($tt)*);
132    }};
133}
134
135#[allow(unused)]
136// Avoid name conflicts with `warn` in the standard library.
137macro_rules! warning {
138    ($($tt:tt)*) => {{
139        #[cfg(feature = "feat-tracing")]
140        tracing::warn!($($tt)*);
141    }};
142}
143
144#[allow(unused)]
145macro_rules! error {
146    ($($tt:tt)*) => {{
147        #[cfg(feature = "feat-tracing")]
148        tracing::error!($($tt)*);
149    }};
150}
151
152#[allow(unused)]
153macro_rules! enter_tracing_span {
154    ($($tt:tt)*) => {
155        #[cfg(any(
156            feature = "feat-tracing-trace",
157            all(debug_assertions, feature = "feat-tracing")
158        ))]
159        let _span = tracing::span!(
160            tracing::Level::TRACE,
161            $($tt)*
162        )
163        .entered();
164    };
165}
166
167#[allow(unused)]
168pub(crate) use {debug, enter_tracing_span, error, info, trace, warning};