Skip to content

Commit e950a8a

Browse files
alexcrichtonEricson2314
authored andcommitted
std: Implement bare bones of the new io module
This commit is an implementation of [RFC 576][rfc] which focuses on some of the more core aspects of `std::io`. It re-introduces a new `std::io` module with the base set of traits, helpers, and adaptors. The module is not currently ready for prime time as it is not integrated into the rest of the system, but some proof-of-concept implementations and methods are now available. [rfc]: rust-lang/rfcs#576 This module will grow quickly over the next few weeks as more I/O RFCs land and as the `old_io` module is slowly deprecated and phased out. At this time it is not recommended for use, but it is helpful to land in-tree to start developing more implementations.
1 parent 30062bc commit e950a8a

File tree

25 files changed

+1658
-126
lines changed

25 files changed

+1658
-126
lines changed

src/libcollections/io.rs

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use core::prelude::*;
12+
13+
use core::io::prelude::*;
14+
use core::io::{Cursor, NegativeSeek, SeekPos};
15+
use core::iter::repeat;
16+
use core::slice;
17+
use core::void::Void;
18+
19+
use vec::Vec;
20+
21+
impl Read for Cursor<Vec<u8>> {
22+
type Err = Void;
23+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Void> {
24+
let pos = self.position();
25+
let n = {
26+
let inner = self.get_ref();
27+
if pos > inner.len() as u64 { return Ok(0) }
28+
let mut slice = &inner[(pos as usize)..];
29+
try!(slice.read(buf))
30+
};
31+
self.set_position(pos + n as u64);
32+
Ok(n)
33+
}
34+
}
35+
36+
impl Seek for Cursor<Vec<u8>> {
37+
type Err = NegativeSeek;
38+
39+
fn seek(&mut self, pos: SeekPos) -> Result<u64, NegativeSeek> {
40+
let old_pos = self.position();
41+
let new_pos = {
42+
let mut c = Cursor::new(&self.get_mut()[]);
43+
c.set_position(old_pos);
44+
try!(c.seek(pos))
45+
};
46+
self.set_position(new_pos);
47+
Ok(new_pos)
48+
}
49+
}
50+
51+
impl Write for Vec<u8> {
52+
type Err = Void;
53+
54+
fn write(&mut self, buf: &[u8]) -> Result<usize, Void> {
55+
self.push_all(buf);
56+
Ok(buf.len())
57+
}
58+
}
59+
60+
impl Write for Cursor<Vec<u8>> {
61+
type Err = Void;
62+
63+
fn write(&mut self, buf: &[u8]) -> Result<usize, Void> {
64+
let pos = self.position();
65+
let mut len = self.get_ref().len();
66+
if pos == len as u64 {
67+
self.get_mut().push_all(buf)
68+
} else {
69+
// Make sure the internal buffer is as least as big as where we
70+
// currently are
71+
let difference = pos as i64 - len as i64;
72+
if difference > 0 {
73+
self.get_mut().extend(repeat(0).take(difference as usize));
74+
len += difference as usize;
75+
}
76+
77+
// Figure out what bytes will be used to overwrite what's currently
78+
// there (left), and what will be appended on the end (right)
79+
let cap = len - (pos as usize);
80+
let (left, right) = if cap <= buf.len() {
81+
(&buf[..cap], &buf[cap..])
82+
} else {
83+
let result: (_, &[_]) = (buf, &[]);
84+
result
85+
};
86+
87+
// Do the necessary writes
88+
if left.len() > 0 {
89+
let dst = &mut self.get_mut()[(pos as usize)..];
90+
slice::bytes::copy_memory(dst, left);
91+
}
92+
if right.len() > 0 {
93+
self.get_mut().push_all(right);
94+
}
95+
}
96+
97+
// Bump us forward
98+
self.set_position(pos + buf.len() as u64);
99+
Ok(buf.len())
100+
}
101+
}

src/libcollections/string.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use core::iter::FromIterator;
2525
use core::mem;
2626
use core::ops::{self, Deref, Add, Index};
2727
use core::ptr;
28+
use core::str as core_str;
2829
use core::raw::Slice as RawSlice;
2930
use unicode::str as unicode_str;
3031
use unicode::str::Utf16Item;
@@ -199,7 +200,7 @@ impl String {
199200
if byte < 128u8 {
200201
// subseqidx handles this
201202
} else {
202-
let w = unicode_str::utf8_char_width(byte);
203+
let w = core_str::utf8_char_width(byte);
203204

204205
match w {
205206
2 => {

src/libcore/borrow.rs

+9
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,12 @@ impl<'a, T, B: ?Sized> fmt::Display for Cow<'a, T, B> where
263263
}
264264
}
265265
}
266+
267+
/// A helper structure whose sole purpose is to contain an inner reference.
268+
///
269+
/// This structure is often returned from methods called `by_ref` on iterators,
270+
/// readers, and writers.
271+
pub struct ByRef<'a, T: ?Sized + 'a> {
272+
/// The contained reference in this structure.
273+
pub inner: &'a mut T,
274+
}

src/libcore/io/mem.rs

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(missing_copy_implementations)]
12+
13+
use prelude::*;
14+
15+
use cmp;
16+
use error::Error;
17+
use fmt;
18+
use void::Void;
19+
use io::{Read, BufferedRead, Write, Seek, SeekPos};
20+
use mem;
21+
use slice;
22+
23+
/// A `Cursor` is a type which wraps another I/O object to provide a `Seek`
24+
/// implementation.
25+
///
26+
/// Cursors are currently typically used with memory buffer objects in order to
27+
/// allow `Seek` plus `Read` and `Write` implementations. For example, common
28+
/// cursor types include:
29+
///
30+
/// * `Cursor<Vec<u8>>`
31+
/// * `Cursor<&[u8]>`
32+
///
33+
/// Cursors are not currently generic over the type contained within, but may
34+
/// become so.
35+
pub struct Cursor<T> {
36+
pos: u64,
37+
inner: T,
38+
}
39+
40+
/// Error returned from primitive seek implementations indicating that a
41+
/// negative byte position was seeked to.
42+
#[derive(Show, PartialEq, Clone, Copy)]
43+
pub struct NegativeSeek;
44+
45+
impl<T> Cursor<T> {
46+
/// Create a new cursor wrapping the provided underlying I/O object.
47+
pub fn new(inner: T) -> Cursor<T> {
48+
Cursor { pos: 0, inner: inner }
49+
}
50+
51+
/// Consume this cursor, returning the underlying value.
52+
pub fn into_inner(self) -> T { self.inner }
53+
54+
/// Get a reference to the underlying value in this cursor.
55+
pub fn get_ref(&self) -> &T { &self.inner }
56+
57+
/// Get a mutable reference to the underlying value in this cursor.
58+
///
59+
/// Care should be taken to avoid modifying the internal I/O state of the
60+
/// underlying value as it may corrupt this cursor's position.
61+
pub fn get_mut(&mut self) -> &mut T { &mut self.inner }
62+
63+
/// Returns the current value of this cursor
64+
pub fn position(&self) -> u64 { self.pos }
65+
66+
/// Sets the value of this cursor
67+
pub fn set_position(&mut self, pos: u64) { self.pos = pos; }
68+
}
69+
70+
macro_rules! seek {
71+
() => {
72+
fn seek(&mut self, style: SeekPos) -> Result<u64, NegativeSeek> {
73+
let pos = match style {
74+
SeekPos::FromStart(n) => n as i64,
75+
SeekPos::FromEnd(n) => self.inner.len() as i64 + n,
76+
SeekPos::FromCur(n) => self.pos as i64 + n,
77+
};
78+
79+
if pos < 0 {
80+
Err(NegativeSeek)
81+
} else {
82+
self.pos = pos as u64;
83+
Ok(self.pos)
84+
}
85+
}
86+
}
87+
}
88+
89+
impl<'a> Seek for Cursor<&'a [u8]> { type Err = NegativeSeek; seek!(); }
90+
impl<'a> Seek for Cursor<&'a mut [u8]> { type Err = NegativeSeek; seek!(); }
91+
92+
impl<'a> Read for &'a [u8] {
93+
type Err = Void;
94+
#[inline]
95+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Void> {
96+
let write_len = cmp::min(buf.len(), self.len());
97+
{
98+
let input = &self[..write_len];
99+
let output = &mut buf[.. write_len];
100+
slice::bytes::copy_memory(output, input);
101+
}
102+
103+
*self = &self[write_len..];
104+
105+
Ok(write_len)
106+
}
107+
}
108+
109+
macro_rules! read {
110+
() => {
111+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Void> {
112+
if self.pos > self.inner.len() as u64 { return Ok(0) }
113+
let mut slice = &self.inner[(self.pos as usize)..];
114+
let n = try!(slice.read(buf));
115+
self.pos += n as u64;
116+
Ok(n)
117+
}
118+
}
119+
}
120+
121+
impl<'a> Read for Cursor<&'a [u8]> { type Err = Void; read!(); }
122+
impl<'a> Read for Cursor<&'a mut [u8]> { type Err = Void; read!(); }
123+
124+
macro_rules! buffer {
125+
() => {
126+
fn fill_buf(&mut self) -> Result<&[u8], Void> {
127+
if self.pos < (self.inner.len() as u64) {
128+
Ok(&self.inner[(self.pos as usize)..])
129+
} else {
130+
Ok(&[])
131+
}
132+
}
133+
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
134+
}
135+
}
136+
137+
impl<'a> BufferedRead for Cursor<&'a [u8]> { buffer!(); }
138+
impl<'a> BufferedRead for Cursor<&'a mut [u8]> { buffer!(); }
139+
140+
impl<'a> Write for &'a mut [u8] {
141+
type Err = Void;
142+
143+
fn write(&mut self, data: &[u8]) -> Result<usize, Void> {
144+
let dst_len = self.len();
145+
let data_len = data.len();
146+
if dst_len >= data_len {
147+
slice::bytes::copy_memory(*self, data);
148+
// TODO: is this actually safe?
149+
*self = unsafe {
150+
let next: &'a mut [u8] = mem::transmute_copy(&*self);
151+
&mut next[data_len..]
152+
};
153+
Ok(data_len)
154+
} else {
155+
slice::bytes::copy_memory(*self, &data[..dst_len]);
156+
*self = &mut [];
157+
Ok(dst_len)
158+
}
159+
}
160+
}
161+
162+
impl<'a> Write for Cursor<&'a mut [u8]> {
163+
type Err = Void;
164+
165+
fn write(&mut self, data: &[u8]) -> Result<usize, Void> {
166+
if self.pos >= self.inner.len() as u64 { return Ok(0) }
167+
168+
let amt = {
169+
let mut s = &mut self.inner[(self.pos as usize)..];
170+
try!(s.write(data))
171+
};
172+
self.pos += amt as u64;
173+
Ok(amt)
174+
}
175+
}
176+
177+
impl fmt::Display for NegativeSeek {
178+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
179+
"cannot seek to a negative position".fmt(f)
180+
}
181+
}
182+
183+
impl Error for NegativeSeek {
184+
fn description(&self) -> &str { "seek error" }
185+
}

0 commit comments

Comments
 (0)