Skip to content

Commit 827de72

Browse files
committed
Move std::io::Cursor into core::io
1 parent 4b0c9d7 commit 827de72

4 files changed

Lines changed: 351 additions & 314 deletions

File tree

library/core/src/io/cursor.rs

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
/// A `Cursor` wraps an in-memory buffer and provides it with a
2+
/// [`Seek`] implementation.
3+
///
4+
/// `Cursor`s are used with in-memory buffers, anything implementing
5+
/// <code>[AsRef]<\[u8]></code>, to allow them to implement [`Read`] and/or [`Write`],
6+
/// allowing these buffers to be used anywhere you might use a reader or writer
7+
/// that does actual I/O.
8+
///
9+
/// The standard library implements some I/O traits on various types which
10+
/// are commonly used as a buffer, like <code>Cursor<[Vec]\<u8>></code> and
11+
/// <code>Cursor<[&\[u8\]][bytes]></code>.
12+
///
13+
/// # Examples
14+
///
15+
/// We may want to write bytes to a [`File`] in our production
16+
/// code, but use an in-memory buffer in our tests. We can do this with
17+
/// `Cursor`:
18+
///
19+
/// [bytes]: crate::slice "slice"
20+
/// [`File`]: ../../std/fs/struct.File.html
21+
/// [`Read`]: ../../std/io/trait.Read.html
22+
/// [`Write`]: ../../std/io/trait.Write.html
23+
/// [`Seek`]: ../../std/io/trait.Seek.html
24+
///
25+
/// ```no_run
26+
/// use std::io::prelude::*;
27+
/// use std::io::{self, SeekFrom};
28+
/// use std::fs::File;
29+
///
30+
/// // a library function we've written
31+
/// fn write_ten_bytes_at_end<W: Write + Seek>(mut writer: W) -> io::Result<()> {
32+
/// writer.seek(SeekFrom::End(-10))?;
33+
///
34+
/// for i in 0..10 {
35+
/// writer.write(&[i])?;
36+
/// }
37+
///
38+
/// // all went well
39+
/// Ok(())
40+
/// }
41+
///
42+
/// # fn foo() -> io::Result<()> {
43+
/// // Here's some code that uses this library function.
44+
/// //
45+
/// // We might want to use a BufReader here for efficiency, but let's
46+
/// // keep this example focused.
47+
/// let mut file = File::create("foo.txt")?;
48+
/// // First, we need to allocate 10 bytes to be able to write into.
49+
/// file.set_len(10)?;
50+
///
51+
/// write_ten_bytes_at_end(&mut file)?;
52+
/// # Ok(())
53+
/// # }
54+
///
55+
/// // now let's write a test
56+
/// #[test]
57+
/// fn test_writes_bytes() {
58+
/// // setting up a real File is much slower than an in-memory buffer,
59+
/// // let's use a cursor instead
60+
/// use std::io::Cursor;
61+
/// let mut buff = Cursor::new(vec![0; 15]);
62+
///
63+
/// write_ten_bytes_at_end(&mut buff).unwrap();
64+
///
65+
/// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
66+
/// }
67+
/// ```
68+
#[stable(feature = "rust1", since = "1.0.0")]
69+
#[derive(Debug, Default, Eq, PartialEq)]
70+
pub struct Cursor<T> {
71+
inner: T,
72+
pos: u64,
73+
}
74+
75+
impl<T> Cursor<T> {
76+
/// Creates a new cursor wrapping the provided underlying in-memory buffer.
77+
///
78+
/// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`])
79+
/// is not empty. So writing to cursor starts with overwriting [`Vec`]
80+
/// content, not with appending to it.
81+
///
82+
/// [`Vec`]: ../../alloc/vec/struct.Vec.html
83+
///
84+
/// # Examples
85+
///
86+
/// ```
87+
/// use std::io::Cursor;
88+
///
89+
/// let buff = Cursor::new(Vec::new());
90+
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
91+
/// # force_inference(&buff);
92+
/// ```
93+
#[stable(feature = "rust1", since = "1.0.0")]
94+
#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")]
95+
pub const fn new(inner: T) -> Cursor<T> {
96+
Cursor { pos: 0, inner }
97+
}
98+
99+
/// Consumes this cursor, returning the underlying value.
100+
///
101+
/// # Examples
102+
///
103+
/// ```
104+
/// use std::io::Cursor;
105+
///
106+
/// let buff = Cursor::new(Vec::new());
107+
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
108+
/// # force_inference(&buff);
109+
///
110+
/// let vec = buff.into_inner();
111+
/// ```
112+
#[stable(feature = "rust1", since = "1.0.0")]
113+
pub fn into_inner(self) -> T {
114+
self.inner
115+
}
116+
117+
/// Gets a reference to the underlying value in this cursor.
118+
///
119+
/// # Examples
120+
///
121+
/// ```
122+
/// use std::io::Cursor;
123+
///
124+
/// let buff = Cursor::new(Vec::new());
125+
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
126+
/// # force_inference(&buff);
127+
///
128+
/// let reference = buff.get_ref();
129+
/// ```
130+
#[stable(feature = "rust1", since = "1.0.0")]
131+
#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")]
132+
pub const fn get_ref(&self) -> &T {
133+
&self.inner
134+
}
135+
136+
/// Gets a mutable reference to the underlying value in this cursor.
137+
///
138+
/// Care should be taken to avoid modifying the internal I/O state of the
139+
/// underlying value as it may corrupt this cursor's position.
140+
///
141+
/// # Examples
142+
///
143+
/// ```
144+
/// use std::io::Cursor;
145+
///
146+
/// let mut buff = Cursor::new(Vec::new());
147+
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
148+
/// # force_inference(&buff);
149+
///
150+
/// let reference = buff.get_mut();
151+
/// ```
152+
#[stable(feature = "rust1", since = "1.0.0")]
153+
#[rustc_const_stable(feature = "const_mut_cursor", since = "1.86.0")]
154+
pub const fn get_mut(&mut self) -> &mut T {
155+
&mut self.inner
156+
}
157+
158+
/// Returns the current position of this cursor.
159+
///
160+
/// # Examples
161+
///
162+
/// ```
163+
/// use std::io::Cursor;
164+
/// use std::io::prelude::*;
165+
/// use std::io::SeekFrom;
166+
///
167+
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
168+
///
169+
/// assert_eq!(buff.position(), 0);
170+
///
171+
/// buff.seek(SeekFrom::Current(2)).unwrap();
172+
/// assert_eq!(buff.position(), 2);
173+
///
174+
/// buff.seek(SeekFrom::Current(-1)).unwrap();
175+
/// assert_eq!(buff.position(), 1);
176+
/// ```
177+
#[stable(feature = "rust1", since = "1.0.0")]
178+
#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")]
179+
pub const fn position(&self) -> u64 {
180+
self.pos
181+
}
182+
183+
/// Sets the position of this cursor.
184+
///
185+
/// # Examples
186+
///
187+
/// ```
188+
/// use std::io::Cursor;
189+
///
190+
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
191+
///
192+
/// assert_eq!(buff.position(), 0);
193+
///
194+
/// buff.set_position(2);
195+
/// assert_eq!(buff.position(), 2);
196+
///
197+
/// buff.set_position(4);
198+
/// assert_eq!(buff.position(), 4);
199+
/// ```
200+
#[stable(feature = "rust1", since = "1.0.0")]
201+
#[rustc_const_stable(feature = "const_mut_cursor", since = "1.86.0")]
202+
pub const fn set_position(&mut self, pos: u64) {
203+
self.pos = pos;
204+
}
205+
206+
#[doc(hidden)]
207+
#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
208+
pub const fn into_parts_mut(&mut self) -> (&mut u64, &mut T) {
209+
(&mut self.pos, &mut self.inner)
210+
}
211+
}
212+
213+
impl<T> Cursor<T>
214+
where
215+
T: AsRef<[u8]>,
216+
{
217+
/// Splits the underlying slice at the cursor position and returns them.
218+
///
219+
/// # Examples
220+
///
221+
/// ```
222+
/// #![feature(cursor_split)]
223+
/// use std::io::Cursor;
224+
///
225+
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
226+
///
227+
/// assert_eq!(buff.split(), ([].as_slice(), [1, 2, 3, 4, 5].as_slice()));
228+
///
229+
/// buff.set_position(2);
230+
/// assert_eq!(buff.split(), ([1, 2].as_slice(), [3, 4, 5].as_slice()));
231+
///
232+
/// buff.set_position(6);
233+
/// assert_eq!(buff.split(), ([1, 2, 3, 4, 5].as_slice(), [].as_slice()));
234+
/// ```
235+
#[unstable(feature = "cursor_split", issue = "86369")]
236+
pub fn split(&self) -> (&[u8], &[u8]) {
237+
let slice = self.inner.as_ref();
238+
let pos = self.pos.min(slice.len() as u64);
239+
slice.split_at(pos as usize)
240+
}
241+
}
242+
243+
impl<T> Cursor<T>
244+
where
245+
T: AsMut<[u8]>,
246+
{
247+
/// Splits the underlying slice at the cursor position and returns them
248+
/// mutably.
249+
///
250+
/// # Examples
251+
///
252+
/// ```
253+
/// #![feature(cursor_split)]
254+
/// use std::io::Cursor;
255+
///
256+
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
257+
///
258+
/// assert_eq!(buff.split_mut(), ([].as_mut_slice(), [1, 2, 3, 4, 5].as_mut_slice()));
259+
///
260+
/// buff.set_position(2);
261+
/// assert_eq!(buff.split_mut(), ([1, 2].as_mut_slice(), [3, 4, 5].as_mut_slice()));
262+
///
263+
/// buff.set_position(6);
264+
/// assert_eq!(buff.split_mut(), ([1, 2, 3, 4, 5].as_mut_slice(), [].as_mut_slice()));
265+
/// ```
266+
#[unstable(feature = "cursor_split", issue = "86369")]
267+
pub fn split_mut(&mut self) -> (&mut [u8], &mut [u8]) {
268+
let slice = self.inner.as_mut();
269+
let pos = self.pos.min(slice.len() as u64);
270+
slice.split_at_mut(pos as usize)
271+
}
272+
}
273+
274+
#[stable(feature = "rust1", since = "1.0.0")]
275+
impl<T> Clone for Cursor<T>
276+
where
277+
T: Clone,
278+
{
279+
#[inline]
280+
fn clone(&self) -> Self {
281+
Cursor { inner: self.inner.clone(), pos: self.pos }
282+
}
283+
284+
#[inline]
285+
fn clone_from(&mut self, other: &Self) {
286+
self.inner.clone_from(&other.inner);
287+
self.pos = other.pos;
288+
}
289+
}

library/core/src/io/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
//! Traits, helpers, and type definitions for core I/O functionality.
22
33
mod borrowed_buf;
4+
mod cursor;
45
mod error;
56

67
#[unstable(feature = "core_io_borrowed_buf", issue = "117693")]
78
pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor};
89
#[unstable(feature = "core_io", issue = "154046")]
10+
pub use self::cursor::Cursor;
11+
#[unstable(feature = "core_io", issue = "154046")]
912
pub use self::error::ErrorKind;
1013
#[unstable(feature = "raw_os_error_ty", issue = "107792")]
1114
pub use self::error::RawOsError;

0 commit comments

Comments
 (0)