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}