zbin/lib.rs
1//! Binary data trait for compio async IO.
2//!
3//! compio uses io_uring/IOCP for async IO, which requires buffer ownership transfer.
4//! The kernel holds the buffer during IO, so we must pass owned data, not references.
5//!
6//! # compio IoBuf constraint
7//!
8//! compio requires [`IoBuf`] trait for async write. Types that impl `IoBuf`:
9//! - `Vec<u8>`, `Box<[u8]>`, `&'static [u8]`, `&'static str`
10//! - `Rc<[u8]>`, `Arc<[u8]>` (zero-copy, compio native support)
11//! - `Bytes` (with `bytes` feature)
12//!
13//! # Bin trait
14//!
15//! This trait bridges various input types to compio's ownership model:
16//! - `as_slice()`: for sync operations (CRC calc, inline write)
17//! - `io()`: transfer ownership to kernel, returns `Self::Io: IoBuf`
18//!
19//! # Zero-copy Table
20//!
21//! | Type | Io | Note |
22//! |------|-----|------|
23//! | `Vec<u8>`, `Box<[u8]>` | self | zero-copy |
24//! | `Rc<[u8]>`, `Arc<[u8]>` | self | zero-copy (compio impl) |
25//! | `Bytes` | self | zero-copy |
26//! | `&Rc`, `&Arc`, `&Bytes` | clone | O(1) ref-count +1 |
27//! | `String` | `Vec<u8>` | into_bytes() |
28//! | `&[u8]`, `&str`, `&[u8; N]` | `Box<[u8]>` | copy |
29//! | `Cow<[u8]>`, `Cow<str>` | `Vec<u8>` | into_owned |
30//!
31//! ---
32//!
33//! 用于 compio 异步 IO 的二进制数据 trait。
34//!
35//! compio 使用 io_uring/IOCP 实现异步 IO,需要转移缓冲区所有权。
36//! 内核在 IO 期间持有缓冲区,因此必须传递拥有所有权的数据,而非引用。
37//!
38//! # compio IoBuf 约束
39//!
40//! compio 异步写入需要 [`IoBuf`] trait。实现了 `IoBuf` 的类型:
41//! - `Vec<u8>`, `Box<[u8]>`, `&'static [u8]`, `&'static str`
42//! - `Rc<[u8]>`, `Arc<[u8]>`(零拷贝,compio 原生支持)
43//! - `Bytes`(需 `bytes` feature)
44//!
45//! # Bin trait
46//!
47//! 此 trait 将各种输入类型桥接到 compio 的所有权模型:
48//! - `as_slice()`: 用于同步操作(CRC 计算、内联写入)
49//! - `io()`: 将所有权转移给内核,返回 `Self::Io: IoBuf`
50//!
51//! # 零拷贝表
52//!
53//! | 类型 | Io | 说明 |
54//! |------|-----|------|
55//! | `Vec<u8>`, `Box<[u8]>` | self | 零拷贝 |
56//! | `Rc<[u8]>`, `Arc<[u8]>` | self | 零拷贝(compio 实现)|
57//! | `Bytes` | self | 零拷贝 |
58//! | `&Rc`, `&Arc`, `&Bytes` | clone | O(1) 引用计数 +1 |
59//! | `String` | `Vec<u8>` | into_bytes() |
60//! | `&[u8]`, `&str`, `&[u8; N]` | `Box<[u8]>` | 拷贝 |
61//! | `Cow<[u8]>`, `Cow<str>` | `Vec<u8>` | into_owned |
62
63use std::{borrow::Cow, rc::Rc, sync::Arc};
64
65#[cfg(feature = "bytes")]
66use bytes::Bytes;
67use compio::buf::IoBuf;
68
69/// Binary data trait for async IO / 异步 IO 二进制数据 trait
70///
71/// `Io` is the owned type for compio async write (must impl [`IoBuf`])
72/// `Io` 是用于 compio 异步写入的拥有所有权类型(必须实现 [`IoBuf`])
73pub trait Bin<'a> {
74 /// Owned type for IO operations / IO 操作的拥有所有权类型
75 type Io: IoBuf;
76
77 /// Get slice reference / 获取切片引用
78 fn as_slice(&self) -> &[u8];
79
80 /// Convert to owned IO buffer (zero-copy if possible)
81 /// 转换为拥有所有权的 IO 缓冲区(尽可能零拷贝)
82 fn io(self) -> Self::Io;
83
84 #[inline(always)]
85 fn len(&self) -> usize {
86 self.as_slice().len()
87 }
88
89 #[inline(always)]
90 fn is_empty(&self) -> bool {
91 self.as_slice().is_empty()
92 }
93}
94
95macro_rules! impl_bin {
96 ($($ty:ty, $io:ty, $slice:ident, $into:expr);* $(;)?) => {
97 $(
98 #[allow(clippy::borrowed_box)]
99 impl<'a> Bin<'a> for $ty {
100 type Io = $io;
101 #[inline(always)]
102 fn as_slice(&self) -> &[u8] { self.$slice() }
103 #[inline(always)]
104 fn io(self) -> $io { $into(self) }
105 }
106 )*
107 };
108}
109
110impl_bin!(
111 // Owned types (zero-copy) / 拥有所有权类型(零拷贝)
112 Vec<u8>, Vec<u8>, as_ref, |s| s;
113 Box<[u8]>, Box<[u8]>, as_ref, |s| s;
114 Rc<[u8]>, Rc<[u8]>, as_ref, |s| s;
115 Arc<[u8]>, Arc<[u8]>, as_ref, |s| s;
116 String, Vec<u8>, as_bytes, String::into_bytes;
117
118 // Reference to owned types / 拥有所有权类型的引用
119 &'a Vec<u8>, Box<[u8]>, as_ref, |s: &Vec<u8>| s.as_slice().into();
120 &'a Box<[u8]>, Box<[u8]>, as_ref, |s: &Box<[u8]>| (*s).clone();
121 &'a Rc<[u8]>, Rc<[u8]>, as_ref, |s: &Rc<[u8]>| s.clone();
122 &'a Arc<[u8]>, Arc<[u8]>, as_ref, |s: &Arc<[u8]>| s.clone();
123 &'a String, Box<[u8]>, as_bytes, |s: &String| s.as_bytes().into();
124
125 // Primitive references / 原始引用类型
126 &'a [u8], Box<[u8]>, as_ref, |s: &[u8]| s.into();
127 &'a str, Box<[u8]>, as_bytes, |s: &str| s.as_bytes().into();
128
129 // Cow types / Cow 类型
130 Cow<'a, [u8]>, Vec<u8>, as_ref, Cow::into_owned;
131 Cow<'a, str>, Vec<u8>, as_bytes, |s: Cow<'_, str>| s.into_owned().into_bytes();
132);
133
134#[cfg(feature = "bytes")]
135impl_bin!(
136 Bytes, Bytes, as_ref, |s| s;
137 &'a Bytes, Bytes, as_ref, |s: &Bytes| s.clone();
138);
139
140// Array reference (const generic) / 数组引用(常量泛型)
141impl<'a, const N: usize> Bin<'a> for &'a [u8; N] {
142 type Io = Box<[u8]>;
143 #[inline(always)]
144 fn as_slice(&self) -> &[u8] {
145 *self
146 }
147 #[inline(always)]
148 fn io(self) -> Box<[u8]> {
149 self.as_slice().into()
150 }
151}
152
153// Array reference (const generic) / 数组引用(常量泛型)
154impl<'a, const N: usize> Bin<'a> for [u8; N] {
155 type Io = [u8; N];
156 #[inline(always)]
157 fn as_slice(&self) -> &[u8] {
158 &self[..]
159 }
160 #[inline(always)]
161 fn io(self) -> Self::Io {
162 self
163 }
164}
165
166// Empty tuple / 空元组
167impl<'a> Bin<'a> for () {
168 type Io = [u8; 0];
169
170 #[inline(always)]
171 fn as_slice(&self) -> &[u8] {
172 &[]
173 }
174
175 #[inline(always)]
176 fn io(self) -> Self::Io {
177 []
178 }
179}