Skip to content

Commit 3b1ff36

Browse files
committed
---
yaml --- r: 141003 b: refs/heads/try2 c: d45dc8d h: refs/heads/master i: 141001: 7eaed5c 140999: a73e95b v: v3
1 parent 5bd2189 commit 3b1ff36

File tree

3 files changed

+128
-66
lines changed

3 files changed

+128
-66
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 28a13ec8d76ba9a4f9645991e1260882a3b7dc68
8+
refs/heads/try2: d45dc8df7278649d101ce28fae1d934559e0e3c2
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libcore/rt/io/extensions.rs

Lines changed: 121 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// XXX: Iteration should probably be considered separately
1515

1616
use vec;
17-
use rt::io::{Reader, read_error, standard_error, EndOfFile};
17+
use rt::io::{Reader, read_error, standard_error, EndOfFile, DEFAULT_BUF_SIZE};
1818
use option::{Option, Some, None};
1919
use unstable::finally::Finally;
2020
use util;
@@ -37,18 +37,17 @@ pub trait ReaderUtil {
3737
/// # Failure
3838
///
3939
/// Raises the same conditions as `read`. Additionally raises `read_error`
40-
/// on EOF. If `read_error` is handled then `push_bytes` returns without
41-
/// pushing any bytes onto `buf` - that is, `buf` has the same length
42-
/// upon exit as it did on entry.
40+
/// on EOF. If `read_error` is handled then `push_bytes` may push less
41+
/// than the requested number of bytes.
4342
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint);
4443

4544
/// Reads `len` bytes and gives you back a new vector of length `len`
4645
///
4746
/// # Failure
4847
///
4948
/// Raises the same conditions as `read`. Additionally raises `read_error`
50-
/// on EOF. If `read_error` is handled then the returned vector has
51-
/// length 0.
49+
/// on EOF. If `read_error` is handled then the returned vector may
50+
/// contain less than the requested number of bytes.
5251
fn read_bytes(&mut self, len: uint) -> ~[u8];
5352

5453
/// Reads all remaining bytes from the stream.
@@ -60,60 +59,6 @@ pub trait ReaderUtil {
6059

6160
}
6261

63-
impl<T: Reader> ReaderUtil for T {
64-
fn read_byte(&mut self) -> Option<u8> {
65-
let mut buf = [0];
66-
match self.read(buf) {
67-
Some(0) => {
68-
debug!("read 0 bytes. trying again");
69-
self.read_byte()
70-
}
71-
Some(1) => Some(buf[0]),
72-
Some(_) => util::unreachable(),
73-
None => None
74-
}
75-
}
76-
77-
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) {
78-
unsafe {
79-
let start_len = buf.len();
80-
let mut total_read = 0;
81-
82-
vec::reserve_at_least(buf, start_len + len);
83-
vec::raw::set_len(buf, start_len + len);
84-
85-
do (|| {
86-
while total_read < len {
87-
let slice = vec::mut_slice(*buf, start_len + total_read, buf.len());
88-
match self.read(slice) {
89-
Some(nread) => {
90-
total_read += nread;
91-
}
92-
None => {
93-
read_error::cond.raise(standard_error(EndOfFile));
94-
// Reset the vector length as though we didn't read anything
95-
total_read = 0;
96-
break;
97-
}
98-
}
99-
}
100-
}).finally {
101-
vec::raw::set_len(buf, start_len + total_read);
102-
}
103-
}
104-
}
105-
106-
fn read_bytes(&mut self, len: uint) -> ~[u8] {
107-
let mut buf = vec::with_capacity(len);
108-
self.push_bytes(&mut buf, len);
109-
return buf;
110-
}
111-
112-
fn read_to_end(&mut self) -> ~[u8] {
113-
fail!()
114-
}
115-
}
116-
11762
pub trait ReaderByteConversions {
11863
/// Reads `n` little-endian unsigned integer bytes.
11964
///
@@ -323,6 +268,71 @@ pub trait WriterByteConversions {
323268
fn write_i8(&mut self, n: i8);
324269
}
325270

271+
impl<T: Reader> ReaderUtil for T {
272+
fn read_byte(&mut self) -> Option<u8> {
273+
let mut buf = [0];
274+
match self.read(buf) {
275+
Some(0) => {
276+
debug!("read 0 bytes. trying again");
277+
self.read_byte()
278+
}
279+
Some(1) => Some(buf[0]),
280+
Some(_) => util::unreachable(),
281+
None => None
282+
}
283+
}
284+
285+
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) {
286+
unsafe {
287+
let start_len = buf.len();
288+
let mut total_read = 0;
289+
290+
vec::reserve_at_least(buf, start_len + len);
291+
vec::raw::set_len(buf, start_len + len);
292+
293+
do (|| {
294+
while total_read < len {
295+
let slice = vec::mut_slice(*buf, start_len + total_read, buf.len());
296+
match self.read(slice) {
297+
Some(nread) => {
298+
total_read += nread;
299+
}
300+
None => {
301+
read_error::cond.raise(standard_error(EndOfFile));
302+
break;
303+
}
304+
}
305+
}
306+
}).finally {
307+
vec::raw::set_len(buf, start_len + total_read);
308+
}
309+
}
310+
}
311+
312+
fn read_bytes(&mut self, len: uint) -> ~[u8] {
313+
let mut buf = vec::with_capacity(len);
314+
self.push_bytes(&mut buf, len);
315+
return buf;
316+
}
317+
318+
fn read_to_end(&mut self) -> ~[u8] {
319+
let mut buf = vec::with_capacity(DEFAULT_BUF_SIZE);
320+
let mut keep_reading = true;
321+
do read_error::cond.trap(|e| {
322+
if e.kind == EndOfFile {
323+
keep_reading = false;
324+
} else {
325+
read_error::cond.raise(e)
326+
}
327+
}).in {
328+
while keep_reading {
329+
self.push_bytes(&mut buf, DEFAULT_BUF_SIZE)
330+
}
331+
}
332+
return buf;
333+
}
334+
}
335+
326336
#[cfg(test)]
327337
mod test {
328338
use super::*;
@@ -414,7 +424,7 @@ mod test {
414424
let mut reader = MemReader::new(~[10, 11]);
415425
do read_error::cond.trap(|_| {
416426
}).in {
417-
assert!(reader.read_bytes(4) == ~[]);
427+
assert!(reader.read_bytes(4) == ~[10, 11]);
418428
}
419429
}
420430

@@ -456,7 +466,7 @@ mod test {
456466
do read_error::cond.trap(|_| {
457467
}).in {
458468
reader.push_bytes(&mut buf, 4);
459-
assert!(buf == ~[8, 9]);
469+
assert!(buf == ~[8, 9, 10, 11]);
460470
}
461471
}
462472

@@ -480,7 +490,7 @@ mod test {
480490
do read_error::cond.trap(|_| { } ).in {
481491
reader.push_bytes(&mut buf, 4);
482492
}
483-
assert!(buf == ~[8, 9]);
493+
assert!(buf == ~[8, 9, 10]);
484494
}
485495

486496
#[test]
@@ -514,4 +524,52 @@ mod test {
514524
}
515525
}
516526

527+
#[test]
528+
fn read_to_end() {
529+
let mut reader = MockReader::new();
530+
let count = Cell(0);
531+
reader.read = |buf| {
532+
do count.with_mut_ref |count| {
533+
if *count == 0 {
534+
*count = 1;
535+
buf[0] = 10;
536+
buf[1] = 11;
537+
Some(2)
538+
} else if *count == 1 {
539+
*count = 2;
540+
buf[0] = 12;
541+
buf[1] = 13;
542+
Some(2)
543+
} else {
544+
None
545+
}
546+
}
547+
};
548+
let buf = reader.read_to_end();
549+
assert!(buf == ~[10, 11, 12, 13]);
550+
}
551+
552+
#[test]
553+
#[should_fail]
554+
#[ignore(cfg(windows))]
555+
fn read_to_end_error() {
556+
let mut reader = MockReader::new();
557+
let count = Cell(0);
558+
reader.read = |buf| {
559+
do count.with_mut_ref |count| {
560+
if *count == 0 {
561+
*count = 1;
562+
buf[0] = 10;
563+
buf[1] = 11;
564+
Some(2)
565+
} else {
566+
read_error::cond.raise(placeholder_error());
567+
None
568+
}
569+
}
570+
};
571+
let buf = reader.read_to_end();
572+
assert!(buf == ~[10, 11]);
573+
}
574+
517575
}

branches/try2/src/libcore/rt/io/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ In particular code written to ignore errors and expect conditions to be unhandle
187187
will start passing around null or zero objects when wrapped in a condition handler.
188188
189189
* XXX: How should we use condition handlers that return values?
190-
190+
* XXX: Should EOF raise default conditions when EOF is not an error?
191191
192192
# Issues withi/o scheduler affinity, work stealing, task pinning
193193
@@ -323,6 +323,10 @@ pub mod native {
323323
/// Mock implementations for testing
324324
mod mock;
325325

326+
/// The default buffer size for various I/O operations
327+
/// XXX: Not pub
328+
pub static DEFAULT_BUF_SIZE: uint = 1024 * 64;
329+
326330
/// The type passed to I/O condition handlers to indicate error
327331
///
328332
/// # XXX
@@ -375,7 +379,7 @@ pub trait Reader {
375379
///
376380
/// # XXX
377381
///
378-
/// * Should raise error on eof
382+
/// * Should raise_default error on eof?
379383
/// * If the condition is handled it should still return the bytes read,
380384
/// in which case there's no need to return Option - but then you *have*
381385
/// to install a handler to detect eof.

0 commit comments

Comments
 (0)