Skip to content

Commit 0bc39e6

Browse files
committed
add io::cursor
Signed-off-by: Yoshua Wuyts <[email protected]>
1 parent 3054509 commit 0bc39e6

File tree

3 files changed

+267
-4
lines changed

3 files changed

+267
-4
lines changed

src/io/cursor.rs

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
use futures_io::{AsyncRead, AsyncSeek, AsyncWrite};
2+
3+
use std::io::{self, IoSlice, IoSliceMut, SeekFrom};
4+
use std::pin::Pin;
5+
use std::task::{Context, Poll};
6+
7+
/// A `Cursor` wraps an in-memory buffer and provides it with a
8+
/// [`Seek`] implementation.
9+
///
10+
/// `Cursor`s are used with in-memory buffers, anything implementing
11+
/// `AsRef<[u8]>`, to allow them to implement [`Read`] and/or [`Write`],
12+
/// allowing these buffers to be used anywhere you might use a reader or writer
13+
/// that does actual I/O.
14+
///
15+
/// The standard library implements some I/O traits on various types which
16+
/// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
17+
/// `Cursor<`[`&[u8]`][bytes]`>`.
18+
///
19+
/// [`Seek`]: trait.Seek.html
20+
/// [`Read`]: trait.Read.html
21+
/// [`Write`]: trait.Write.html
22+
/// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
23+
/// [bytes]: https://doc.rust-lang.org/std/primitive.slice.html
24+
/// [`File`]: struct.File.html
25+
#[derive(Clone, Debug, Default)]
26+
pub struct Cursor<T> {
27+
inner: std::io::Cursor<T>,
28+
}
29+
30+
impl<T> Cursor<T> {
31+
/// Creates a new cursor wrapping the provided underlying in-memory buffer.
32+
///
33+
/// Cursor initial position is `0` even if underlying buffer (e.g., `Vec`)
34+
/// is not empty. So writing to cursor starts with overwriting `Vec`
35+
/// content, not with appending to it.
36+
///
37+
/// # Examples
38+
///
39+
/// ```
40+
/// use async_std::io::Cursor;
41+
///
42+
/// let buff = Cursor::new(Vec::new());
43+
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
44+
/// # force_inference(&buff);
45+
/// ```
46+
pub fn new(inner: T) -> Cursor<T> {
47+
Cursor {
48+
inner: std::io::Cursor::new(inner),
49+
}
50+
}
51+
52+
/// Consumes this cursor, returning the underlying value.
53+
///
54+
/// # Examples
55+
///
56+
/// ```
57+
/// use async_std::io::Cursor;
58+
///
59+
/// let buff = Cursor::new(Vec::new());
60+
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
61+
/// # force_inference(&buff);
62+
///
63+
/// let vec = buff.into_inner();
64+
/// ```
65+
pub fn into_inner(self) -> T {
66+
self.inner.into_inner()
67+
}
68+
69+
/// Gets a reference to the underlying value in this cursor.
70+
///
71+
/// # Examples
72+
///
73+
/// ```
74+
/// use async_std::io::Cursor;
75+
///
76+
/// let buff = Cursor::new(Vec::new());
77+
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
78+
/// # force_inference(&buff);
79+
///
80+
/// let reference = buff.get_ref();
81+
/// ```
82+
pub fn get_ref(&self) -> &T {
83+
self.inner.get_ref()
84+
}
85+
86+
/// Gets a mutable reference to the underlying value in this cursor.
87+
///
88+
/// Care should be taken to avoid modifying the internal I/O state of the
89+
/// underlying value as it may corrupt this cursor's position.
90+
///
91+
/// # Examples
92+
///
93+
/// ```
94+
/// use async_std::io::Cursor;
95+
///
96+
/// let mut buff = Cursor::new(Vec::new());
97+
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
98+
/// # force_inference(&buff);
99+
///
100+
/// let reference = buff.get_mut();
101+
/// ```
102+
pub fn get_mut(&mut self) -> &mut T {
103+
self.inner.get_mut()
104+
}
105+
106+
/// Returns the current position of this cursor.
107+
///
108+
/// # Examples
109+
///
110+
/// ```
111+
/// use async_std::io::Cursor;
112+
/// use async_std::io::prelude::*;
113+
/// use async_std::io::SeekFrom;
114+
///
115+
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
116+
///
117+
/// assert_eq!(buff.position(), 0);
118+
///
119+
/// buff.seek(SeekFrom::Current(2)).unwrap();
120+
/// assert_eq!(buff.position(), 2);
121+
///
122+
/// buff.seek(SeekFrom::Current(-1)).unwrap();
123+
/// assert_eq!(buff.position(), 1);
124+
/// ```
125+
pub fn position(&self) -> u64 {
126+
self.inner.position()
127+
}
128+
129+
/// Sets the position of this cursor.
130+
///
131+
/// # Examples
132+
///
133+
/// ```
134+
/// use async_std::io::Cursor;
135+
///
136+
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
137+
///
138+
/// assert_eq!(buff.position(), 0);
139+
///
140+
/// buff.set_position(2);
141+
/// assert_eq!(buff.position(), 2);
142+
///
143+
/// buff.set_position(4);
144+
/// assert_eq!(buff.position(), 4);
145+
/// ```
146+
pub fn set_position(&mut self, pos: u64) {
147+
self.inner.set_position(pos)
148+
}
149+
}
150+
151+
impl<T> AsyncSeek for Cursor<T>
152+
where
153+
T: AsRef<[u8]> + Unpin,
154+
{
155+
fn poll_seek(
156+
mut self: Pin<&mut Self>,
157+
_: &mut Context<'_>,
158+
pos: SeekFrom,
159+
) -> Poll<io::Result<u64>> {
160+
Poll::Ready(io::Seek::seek(&mut self.inner, pos))
161+
}
162+
}
163+
164+
impl<T> AsyncRead for Cursor<T>
165+
where
166+
T: AsRef<[u8]> + Unpin,
167+
{
168+
fn poll_read(
169+
mut self: Pin<&mut Self>,
170+
_cx: &mut Context<'_>,
171+
buf: &mut [u8],
172+
) -> Poll<io::Result<usize>> {
173+
Poll::Ready(io::Read::read(&mut self.inner, buf))
174+
}
175+
176+
fn poll_read_vectored(
177+
mut self: Pin<&mut Self>,
178+
_: &mut Context<'_>,
179+
bufs: &mut [IoSliceMut<'_>],
180+
) -> Poll<io::Result<usize>> {
181+
Poll::Ready(io::Read::read_vectored(&mut self.inner, bufs))
182+
}
183+
}
184+
185+
// impl<T> AsyncBufRead for Cursor<T>
186+
// where
187+
// T: AsRef<[u8]> + Unpin,
188+
// {
189+
// fn poll_fill_buf(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
190+
// // let amt = cmp::min(self.position(), self.as_ref().len() as u64);
191+
// // Poll::Ready(Ok(&self.inner.as_ref()[(amt as usize)..]))
192+
// let res = io::BufRead::fill_buf(&mut self.inner);
193+
// Poll::Ready(res)
194+
// }
195+
196+
// fn consume(mut self: Pin<&mut Self>, amt: usize) {
197+
// io::BufRead::consume(&mut self.inner, amt)
198+
// }
199+
// }
200+
201+
impl AsyncWrite for Cursor<&mut [u8]> {
202+
fn poll_write(
203+
mut self: Pin<&mut Self>,
204+
_: &mut Context<'_>,
205+
buf: &[u8],
206+
) -> Poll<io::Result<usize>> {
207+
Poll::Ready(io::Write::write(&mut self.inner, buf))
208+
}
209+
210+
fn poll_write_vectored(
211+
mut self: Pin<&mut Self>,
212+
_: &mut Context<'_>,
213+
bufs: &[IoSlice<'_>],
214+
) -> Poll<io::Result<usize>> {
215+
Poll::Ready(io::Write::write_vectored(&mut self.inner, bufs))
216+
}
217+
218+
fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
219+
Poll::Ready(io::Write::flush(&mut self.inner))
220+
}
221+
222+
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
223+
self.poll_flush(cx)
224+
}
225+
}
226+
227+
impl AsyncWrite for Cursor<&mut Vec<u8>> {
228+
fn poll_write(
229+
mut self: Pin<&mut Self>,
230+
_: &mut Context<'_>,
231+
buf: &[u8],
232+
) -> Poll<io::Result<usize>> {
233+
Poll::Ready(io::Write::write(&mut self.inner, buf))
234+
}
235+
236+
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
237+
self.poll_flush(cx)
238+
}
239+
240+
fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
241+
Poll::Ready(io::Write::flush(&mut self.inner))
242+
}
243+
}
244+
245+
impl AsyncWrite for Cursor<Vec<u8>> {
246+
fn poll_write(
247+
mut self: Pin<&mut Self>,
248+
_: &mut Context<'_>,
249+
buf: &[u8],
250+
) -> Poll<io::Result<usize>> {
251+
Poll::Ready(io::Write::write(&mut self.inner, buf))
252+
}
253+
254+
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
255+
self.poll_flush(cx)
256+
}
257+
258+
fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
259+
Poll::Ready(io::Write::flush(&mut self.inner))
260+
}
261+
}

src/io/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub use std::io::{Error, ErrorKind, Result, SeekFrom};
2828
pub use buf_read::{BufRead, Lines};
2929
pub use buf_reader::BufReader;
3030
pub use copy::copy;
31+
pub use cursor::Cursor;
3132
pub use empty::{empty, Empty};
3233
pub use read::Read;
3334
pub use seek::Seek;
@@ -41,6 +42,7 @@ pub use write::Write;
4142
mod buf_read;
4243
mod buf_reader;
4344
mod copy;
45+
mod cursor;
4446
mod empty;
4547
mod read;
4648
mod seek;

src/io/prelude.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
//! ```
1010
1111
#[doc(no_inline)]
12-
pub use super::BufRead as _;
12+
pub use super::BufRead;
1313
#[doc(no_inline)]
14-
pub use super::Read as _;
14+
pub use super::Read;
1515
#[doc(no_inline)]
16-
pub use super::Seek as _;
16+
pub use super::Seek;
1717
#[doc(no_inline)]
18-
pub use super::Write as _;
18+
pub use super::Write;

0 commit comments

Comments
 (0)