-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathbuf_reader.rs
82 lines (75 loc) · 2.05 KB
/
buf_reader.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use core::{
pin::Pin,
task::{self, Poll},
};
use embrio_core::io::{BufRead, Read};
use futures_util::ready;
pub struct BufReader<R, B> {
reader: R,
buffer: B,
left: usize,
right: usize,
}
impl<R, B> BufReader<R, B> {
pub fn new(reader: R, buffer: B) -> Self {
BufReader {
reader,
buffer,
left: 0,
right: 0,
}
}
}
impl<R: Read, B: AsMut<[u8]>> Read for BufReader<R, B> {
type Error = R::Error;
fn poll_read(
self: Pin<&mut Self>,
cx: &mut task::Context<'_>,
buf: &mut [u8],
) -> Poll<Result<usize, Self::Error>> {
let available = ready!(self.poll_fill_buf(cx))?;
buf.copy_from_slice(available);
Poll::Ready(Ok(available.len()))
}
}
impl<R: Read, B: AsMut<[u8]>> BufRead for BufReader<R, B> {
fn poll_fill_buf<'a>(
self: Pin<&'a mut Self>,
cx: &mut task::Context<'_>,
) -> Poll<Result<&'a [u8], Self::Error>> {
// Safety: we re-wrap the only !Unpin field in a new PinMut
let BufReader {
ref mut reader,
ref mut buffer,
ref left,
ref mut right,
} = unsafe { Pin::get_unchecked_mut(self) };
let reader = unsafe { Pin::new_unchecked(reader) };
let buffer = buffer.as_mut();
if let Poll::Ready(amount) =
reader.poll_read(cx, &mut buffer[*right..])?
{
*right += amount;
return Poll::Ready(Ok(&buffer[*left..*right]));
}
if *left == *right {
Poll::Pending
} else {
Poll::Ready(Ok(&buffer[*left..*right]))
}
}
fn consume(self: Pin<&mut Self>, amount: usize) {
// Safety: we only access unpin fields
let BufReader {
ref mut left,
ref mut right,
..
} = unsafe { Pin::get_unchecked_mut(self) };
assert!(amount <= *right - *left);
*left += amount;
if *left == *right {
*left = 0;
*right = 0;
}
}
}