Skip to content

Commit ff20534

Browse files
Merge #167
167: add io::cursor r=stjepang a=yoshuawuyts Adds `io::Cursor` and makes it so `io::prelude::*` behaves the way it does in std (so it can actually be implemented - though this might just have been a bug on my side??). Ref #131. Thanks! Co-authored-by: Yoshua Wuyts <[email protected]>
2 parents c8475ca + 3b8e604 commit ff20534

File tree

3 files changed

+269
-4
lines changed

3 files changed

+269
-4
lines changed

Diff for: src/io/cursor.rs

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

Diff for: src/io/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, 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 repeat::{repeat, Repeat};
@@ -42,6 +43,7 @@ pub use write::Write;
4243
mod buf_read;
4344
mod buf_reader;
4445
mod copy;
46+
mod cursor;
4547
mod empty;
4648
mod read;
4749
mod repeat;

Diff for: src/io/prelude.rs

+4-4
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)