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 #[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]
32pub 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]
52pub 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]
81pub 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#[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)]
136macro_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};