Skip to content

Commit 634988d

Browse files
committed
feat(io): reimplement vectored extensions
1 parent 7ff681e commit 634988d

File tree

5 files changed

+309
-94
lines changed

5 files changed

+309
-94
lines changed

compio-io/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ pub mod compat;
109109
mod read;
110110
mod split;
111111
pub mod util;
112+
mod vectored;
112113
mod write;
113114

114115
pub(crate) type IoResult<T> = std::io::Result<T>;

compio-io/src/read/ext.rs

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#[cfg(feature = "allocator_api")]
22
use std::alloc::Allocator;
33

4-
use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, IoVectoredBufMut, t_alloc};
4+
use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, IoVectoredBufMut, SetBufInit, t_alloc};
55

6-
use crate::{AsyncRead, AsyncReadAt, IoResult, util::Take};
6+
use crate::{AsyncRead, AsyncReadAt, IoResult, util::Take, vectored::VectoredWrap};
77

88
/// Shared code for read a scalar value from the underlying reader.
99
macro_rules! read_scalar {
@@ -36,63 +36,35 @@ macro_rules! read_scalar {
3636

3737
/// Shared code for loop reading until reaching a certain length.
3838
macro_rules! loop_read_exact {
39-
($buf:ident, $len:expr, $tracker:ident,loop $read_expr:expr) => {
40-
let mut $tracker = 0;
39+
($buf:ident, $len:expr, $tracker:ident, $read_expr:expr, $update_expr:expr, $buf_expr:expr) => {
40+
let mut $tracker = 0usize;
4141
let len = $len;
42-
4342
while $tracker < len {
44-
match $read_expr.await.into_inner() {
45-
BufResult(Ok(0), buf) => {
43+
let BufResult(res, buf) = $read_expr;
44+
$buf = buf;
45+
match res {
46+
Ok(0) => {
4647
return BufResult(
4748
Err(::std::io::Error::new(
4849
::std::io::ErrorKind::UnexpectedEof,
4950
"failed to fill whole buffer",
5051
)),
51-
buf,
52+
$buf_expr,
5253
);
5354
}
54-
BufResult(Ok(n), buf) => {
55-
$tracker += n;
56-
$buf = buf;
57-
}
58-
BufResult(Err(ref e), buf) if e.kind() == ::std::io::ErrorKind::Interrupted => {
59-
$buf = buf;
55+
Ok(n) => {
56+
$tracker += n as usize;
57+
$update_expr;
6058
}
61-
BufResult(Err(e), buf) => return BufResult(Err(e), buf),
59+
Err(ref e) if e.kind() == ::std::io::ErrorKind::Interrupted => {}
60+
Err(e) => return BufResult(Err(e), $buf_expr),
6261
}
6362
}
64-
return BufResult(Ok(()), $buf)
63+
return BufResult(Ok(()), $buf_expr)
6564
};
6665
}
6766

6867
macro_rules! loop_read_vectored {
69-
($buf:ident, $tracker:ident : $tracker_ty:ty, $iter:ident,loop $read_expr:expr) => {{
70-
use ::compio_buf::OwnedIterator;
71-
72-
let mut $iter = match $buf.owned_iter() {
73-
Ok(buf) => buf,
74-
Err(buf) => return BufResult(Ok(()), buf),
75-
};
76-
let mut $tracker: $tracker_ty = 0;
77-
78-
loop {
79-
let len = $iter.buf_capacity();
80-
if len > 0 {
81-
match $read_expr.await {
82-
BufResult(Ok(()), ret) => {
83-
$iter = ret;
84-
$tracker += len as $tracker_ty;
85-
}
86-
BufResult(Err(e), $iter) => return BufResult(Err(e), $iter.into_inner()),
87-
};
88-
}
89-
90-
match $iter.next() {
91-
Ok(next) => $iter = next,
92-
Err(buf) => return BufResult(Ok(()), buf),
93-
}
94-
}
95-
}};
9668
($buf:ident, $iter:ident, $read_expr:expr) => {{
9769
use ::compio_buf::OwnedIterator;
9870

@@ -158,7 +130,14 @@ pub trait AsyncReadExt: AsyncRead {
158130

159131
/// Read the exact number of bytes required to fill the buf.
160132
async fn read_exact<T: IoBufMut>(&mut self, mut buf: T) -> BufResult<(), T> {
161-
loop_read_exact!(buf, buf.buf_capacity(), read, loop self.read(buf.slice(read..)));
133+
loop_read_exact!(
134+
buf,
135+
buf.buf_capacity(),
136+
read,
137+
self.read(buf.slice(read..)).await.into_inner(),
138+
{},
139+
buf
140+
);
162141
}
163142

164143
/// Read all bytes until underlying reader reaches `EOF`.
@@ -171,7 +150,15 @@ pub trait AsyncReadExt: AsyncRead {
171150

172151
/// Read the exact number of bytes required to fill the vectored buf.
173152
async fn read_vectored_exact<T: IoVectoredBufMut>(&mut self, buf: T) -> BufResult<(), T> {
174-
loop_read_vectored!(buf, _total: usize, iter, loop self.read_exact(iter))
153+
let mut buf = VectoredWrap::new(buf);
154+
loop_read_exact!(
155+
buf,
156+
buf.capacity(),
157+
read,
158+
self.read_vectored(buf).await,
159+
unsafe { buf.set_buf_init(read) },
160+
buf.into_inner()
161+
);
175162
}
176163

177164
/// Creates an adaptor which reads at most `limit` bytes from it.
@@ -234,7 +221,11 @@ pub trait AsyncReadAtExt: AsyncReadAt {
234221
buf,
235222
buf.buf_capacity(),
236223
read,
237-
loop self.read_at(buf.slice(read..), pos + read as u64)
224+
self.read_at(buf.slice(read..), pos + read as u64)
225+
.await
226+
.into_inner(),
227+
{},
228+
buf
238229
);
239230
}
240231

@@ -262,7 +253,15 @@ pub trait AsyncReadAtExt: AsyncReadAt {
262253
buf: T,
263254
pos: u64,
264255
) -> BufResult<(), T> {
265-
loop_read_vectored!(buf, total: u64, iter, loop self.read_exact_at(iter, pos + total))
256+
let mut buf = VectoredWrap::new(buf);
257+
loop_read_exact!(
258+
buf,
259+
buf.capacity(),
260+
read,
261+
self.read_vectored_at(buf, pos + read as u64).await,
262+
unsafe { buf.set_buf_init(read) },
263+
buf.into_inner()
264+
);
266265
}
267266
}
268267

compio-io/src/vectored.rs

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
use std::pin::Pin;
2+
3+
use compio_buf::{
4+
Indexable, IndexableMut, IndexedIter, IntoInner, IoBuf, IoBufMut, IoVectoredBuf,
5+
IoVectoredBufMut, MaybeOwned, MaybeOwnedMut, SetBufInit,
6+
};
7+
8+
pub struct VectoredWrap<T> {
9+
buffers: Pin<Box<T>>,
10+
wraps: Vec<BufWrap>,
11+
vec_off: usize,
12+
}
13+
14+
impl<T: IoVectoredBuf> VectoredWrap<T> {
15+
pub fn new(buffers: T) -> Self {
16+
let buffers = Box::pin(buffers);
17+
let wraps = buffers.iter_buf().map(|buf| BufWrap::new(&*buf)).collect();
18+
Self {
19+
buffers,
20+
wraps,
21+
vec_off: 0,
22+
}
23+
}
24+
25+
pub fn len(&self) -> usize {
26+
self.wraps.iter().map(|buf| buf.len).sum()
27+
}
28+
29+
pub fn capacity(&self) -> usize {
30+
self.wraps.iter().map(|buf| buf.capacity).sum()
31+
}
32+
}
33+
34+
impl<T: IoVectoredBuf + 'static> IoVectoredBuf for VectoredWrap<T> {
35+
type Buf = BufWrap;
36+
type OwnedIter = IndexedIter<Self>;
37+
38+
fn iter_buf(&self) -> impl Iterator<Item = MaybeOwned<'_, Self::Buf>> {
39+
self.wraps
40+
.iter()
41+
.skip(self.vec_off)
42+
.map(MaybeOwned::Borrowed)
43+
}
44+
45+
fn owned_iter(self) -> Result<Self::OwnedIter, Self>
46+
where
47+
Self: Sized,
48+
{
49+
IndexedIter::new(self)
50+
}
51+
}
52+
53+
impl<T: IoVectoredBufMut + 'static> IoVectoredBufMut for VectoredWrap<T> {
54+
fn iter_buf_mut(&mut self) -> impl Iterator<Item = MaybeOwnedMut<'_, Self::Buf>> {
55+
self.wraps
56+
.iter_mut()
57+
.skip(self.vec_off)
58+
.map(MaybeOwnedMut::Borrowed)
59+
}
60+
}
61+
62+
impl<T: SetBufInit> SetBufInit for VectoredWrap<T> {
63+
unsafe fn set_buf_init(&mut self, mut len: usize) {
64+
self.buffers.as_mut().get_unchecked_mut().set_buf_init(len);
65+
self.vec_off = 0;
66+
for buf in self.wraps.iter_mut().skip(self.vec_off) {
67+
let capacity = (*buf).buf_capacity();
68+
let buf_new_len = len.min(capacity);
69+
buf.set_buf_init(buf_new_len);
70+
*buf = buf.offset(buf_new_len);
71+
if len >= capacity {
72+
len -= capacity;
73+
} else {
74+
break;
75+
}
76+
self.vec_off += 1;
77+
}
78+
}
79+
}
80+
81+
impl<T> Indexable for VectoredWrap<T> {
82+
type Output = BufWrap;
83+
84+
fn index(&self, n: usize) -> Option<&Self::Output> {
85+
self.wraps.get(n + self.vec_off)
86+
}
87+
}
88+
89+
impl<T> IndexableMut for VectoredWrap<T> {
90+
fn index_mut(&mut self, n: usize) -> Option<&mut Self::Output> {
91+
self.wraps.get_mut(n + self.vec_off)
92+
}
93+
}
94+
95+
impl<T> IntoInner for VectoredWrap<T> {
96+
type Inner = T;
97+
98+
fn into_inner(self) -> Self::Inner {
99+
// Safety: no pointers still maintaining
100+
*unsafe { Pin::into_inner_unchecked(self.buffers) }
101+
}
102+
}
103+
104+
pub struct BufWrap {
105+
ptr: *mut u8,
106+
len: usize,
107+
capacity: usize,
108+
}
109+
110+
impl BufWrap {
111+
fn new<T: IoBuf>(buf: &T) -> Self {
112+
Self {
113+
ptr: buf.as_buf_ptr().cast_mut(),
114+
len: buf.buf_len(),
115+
capacity: buf.buf_capacity(),
116+
}
117+
}
118+
119+
fn offset(&self, off: usize) -> Self {
120+
Self {
121+
ptr: unsafe { self.ptr.add(off) },
122+
len: self.len.saturating_sub(off),
123+
capacity: self.capacity.saturating_sub(off),
124+
}
125+
}
126+
}
127+
128+
unsafe impl IoBuf for BufWrap {
129+
fn as_buf_ptr(&self) -> *const u8 {
130+
self.ptr.cast_const()
131+
}
132+
133+
fn buf_len(&self) -> usize {
134+
self.len
135+
}
136+
137+
fn buf_capacity(&self) -> usize {
138+
self.capacity
139+
}
140+
}
141+
142+
unsafe impl IoBufMut for BufWrap {
143+
fn as_buf_mut_ptr(&mut self) -> *mut u8 {
144+
self.ptr
145+
}
146+
}
147+
148+
impl SetBufInit for BufWrap {
149+
unsafe fn set_buf_init(&mut self, len: usize) {
150+
debug_assert!(len <= self.capacity, "{} > {}", len, self.capacity);
151+
self.len = self.len.max(len);
152+
}
153+
}

0 commit comments

Comments
 (0)