Skip to content

Commit 3fee6bd

Browse files
committed
---
yaml --- r: 140994 b: refs/heads/try2 c: b764d4c h: refs/heads/master v: v3
1 parent 6b2cc38 commit 3fee6bd

File tree

4 files changed

+326
-6
lines changed

4 files changed

+326
-6
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: 013b7760b7bbc43ee56179588f8fe1a81d4567e5
8+
refs/heads/try2: b764d4cb4f0c893caf5a6395db9b1e10a167a28f
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: 262 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,103 @@
1313
// XXX: Not sure how this should be structured
1414
// XXX: Iteration should probably be considered separately
1515

16+
use vec;
17+
use rt::io::Reader;
18+
use option::{Option, Some, None};
19+
use unstable::finally::Finally;
20+
1621
pub trait ReaderUtil {
1722

23+
/// Reads a single byte. Returns `None` on EOF.
24+
///
25+
/// # Failure
26+
///
27+
/// Raises the same conditions as the `read` method. Returns
28+
/// `None` if the condition is handled.
29+
fn read_byte(&mut self) -> Option<u8>;
30+
31+
/// Reads `len` bytes and appends them to a vector.
32+
///
33+
/// May push fewer than the requested number of bytes on error
34+
/// or EOF. Returns true on success, false on EOF or error.
35+
///
36+
/// # Failure
37+
///
38+
/// Raises the same conditions as `read`. Returns `false` if
39+
/// the condition is handled.
40+
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) -> bool;
41+
1842
/// Reads `len` bytes and gives you back a new vector
1943
///
2044
/// # Failure
2145
///
22-
/// Raises the `io_error` condition on error. Returns an empty
23-
/// vector if the condition is handled.
46+
/// Raises the same conditions as the `read` method. May return
47+
/// less than the requested number of bytes on error or EOF.
2448
fn read_bytes(&mut self, len: uint) -> ~[u8];
2549

2650
/// Reads all remaining bytes from the stream.
2751
///
2852
/// # Failure
2953
///
30-
/// Raises the `io_error` condition on error. Returns an empty
31-
/// vector if the condition is handled.
54+
/// Raises the same conditions as the `read` method.
3255
fn read_to_end(&mut self) -> ~[u8];
3356

3457
}
3558

59+
impl<T: Reader> ReaderUtil for T {
60+
fn read_byte(&mut self) -> Option<u8> {
61+
let mut buf = [0];
62+
match self.read(buf) {
63+
Some(nread) if nread == 0 => {
64+
debug!("read 0 bytes. trying again");
65+
self.read_byte()
66+
}
67+
Some(nread) => Some(buf[0]),
68+
None => None
69+
}
70+
}
71+
72+
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) -> bool {
73+
unsafe {
74+
let start_len = buf.len();
75+
let mut total_read = 0;
76+
let mut eof = false;
77+
78+
vec::reserve_at_least(buf, start_len + len);
79+
vec::raw::set_len(buf, start_len + len);
80+
81+
do (|| {
82+
while total_read < len {
83+
let slice = vec::mut_slice(*buf, start_len + total_read, buf.len());
84+
match self.read(slice) {
85+
Some(nread) => {
86+
total_read += nread;
87+
}
88+
None => {
89+
eof = true;
90+
break;
91+
}
92+
}
93+
}
94+
}).finally {
95+
vec::raw::set_len(buf, start_len + total_read);
96+
}
97+
98+
return !eof;
99+
}
100+
}
101+
102+
fn read_bytes(&mut self, len: uint) -> ~[u8] {
103+
let mut buf = vec::with_capacity(len);
104+
self.push_bytes(&mut buf, len);
105+
return buf;
106+
}
107+
108+
fn read_to_end(&mut self) -> ~[u8] {
109+
fail!()
110+
}
111+
}
112+
36113
pub trait ReaderByteConversions {
37114
/// Reads `n` little-endian unsigned integer bytes.
38115
///
@@ -467,3 +544,184 @@ pub trait WriterByteConversions {
467544
/// Raises the `io_error` condition on error.
468545
fn write_i8(&mut self, n: i8);
469546
}
547+
548+
#[cfg(test)]
549+
mod test {
550+
use super::*;
551+
use option::{Some, None};
552+
use cell::Cell;
553+
use rt::io::mem::MemReader;
554+
use rt::io::mock::*;
555+
use rt::io::{io_error, placeholder_error};
556+
557+
#[test]
558+
fn read_byte() {
559+
let mut reader = MemReader::new(~[10]);
560+
let byte = reader.read_byte();
561+
assert!(byte == Some(10));
562+
}
563+
564+
#[test]
565+
fn read_byte_0_bytes() {
566+
let mut reader = MockReader::new();
567+
let count = Cell(0);
568+
reader.read = |buf| {
569+
do count.with_mut_ref |count| {
570+
if *count == 0 {
571+
*count = 1;
572+
Some(0)
573+
} else {
574+
buf[0] = 10;
575+
Some(1)
576+
}
577+
}
578+
};
579+
let byte = reader.read_byte();
580+
assert!(byte == Some(10));
581+
}
582+
583+
#[test]
584+
fn read_byte_eof() {
585+
let mut reader = MockReader::new();
586+
reader.read = |_| None;
587+
let byte = reader.read_byte();
588+
assert!(byte == None);
589+
}
590+
591+
#[test]
592+
fn read_byte_error() {
593+
let mut reader = MockReader::new();
594+
reader.read = |_| {
595+
io_error::cond.raise(placeholder_error());
596+
None
597+
};
598+
do io_error::cond.trap(|_| {
599+
}).in {
600+
let byte = reader.read_byte();
601+
assert!(byte == None);
602+
}
603+
}
604+
605+
#[test]
606+
fn read_bytes() {
607+
let mut reader = MemReader::new(~[10, 11, 12, 13]);
608+
let bytes = reader.read_bytes(4);
609+
assert!(bytes == ~[10, 11, 12, 13]);
610+
}
611+
612+
#[test]
613+
fn read_bytes_partial() {
614+
let mut reader = MockReader::new();
615+
let count = Cell(0);
616+
reader.read = |buf| {
617+
do count.with_mut_ref |count| {
618+
if *count == 0 {
619+
*count = 1;
620+
buf[0] = 10;
621+
buf[1] = 11;
622+
Some(2)
623+
} else {
624+
buf[0] = 12;
625+
buf[1] = 13;
626+
Some(2)
627+
}
628+
}
629+
};
630+
let bytes = reader.read_bytes(4);
631+
assert!(bytes == ~[10, 11, 12, 13]);
632+
}
633+
634+
#[test]
635+
fn push_bytes() {
636+
let mut reader = MemReader::new(~[10, 11, 12, 13]);
637+
let mut buf = ~[8, 9];
638+
assert!(reader.push_bytes(&mut buf, 4));
639+
assert!(buf == ~[8, 9, 10, 11, 12, 13]);
640+
}
641+
642+
#[test]
643+
fn push_bytes_partial() {
644+
let mut reader = MockReader::new();
645+
let count = Cell(0);
646+
reader.read = |buf| {
647+
do count.with_mut_ref |count| {
648+
if *count == 0 {
649+
*count = 1;
650+
buf[0] = 10;
651+
buf[1] = 11;
652+
Some(2)
653+
} else {
654+
buf[0] = 12;
655+
buf[1] = 13;
656+
Some(2)
657+
}
658+
}
659+
};
660+
let mut buf = ~[8, 9];
661+
assert!(reader.push_bytes(&mut buf, 4));
662+
assert!(buf == ~[8, 9, 10, 11, 12, 13]);
663+
}
664+
665+
#[test]
666+
fn push_bytes_eof() {
667+
let mut reader = MemReader::new(~[10, 11]);
668+
let mut buf = ~[8, 9];
669+
assert!(!reader.push_bytes(&mut buf, 4));
670+
assert!(buf == ~[8, 9, 10, 11]);
671+
}
672+
673+
#[test]
674+
fn push_bytes_error() {
675+
let mut reader = MockReader::new();
676+
let count = Cell(0);
677+
reader.read = |buf| {
678+
do count.with_mut_ref |count| {
679+
if *count == 0 {
680+
*count = 1;
681+
buf[0] = 10;
682+
Some(1)
683+
} else {
684+
io_error::cond.raise(placeholder_error());
685+
None
686+
}
687+
}
688+
};
689+
let mut buf = ~[8, 9];
690+
do io_error::cond.trap(|_| { } ).in {
691+
assert!(!reader.push_bytes(&mut buf, 4));
692+
}
693+
assert!(buf == ~[8, 9, 10]);
694+
}
695+
696+
#[test]
697+
#[should_fail]
698+
#[ignore(cfg(windows))]
699+
fn push_bytes_fail_reset_len() {
700+
use unstable::finally::Finally;
701+
702+
// push_bytes unsafely sets the vector length. This is testing that
703+
// upon failure the length is reset correctly.
704+
let mut reader = MockReader::new();
705+
let count = Cell(0);
706+
reader.read = |buf| {
707+
do count.with_mut_ref |count| {
708+
if *count == 0 {
709+
*count = 1;
710+
buf[0] = 10;
711+
Some(1)
712+
} else {
713+
io_error::cond.raise(placeholder_error());
714+
None
715+
}
716+
}
717+
};
718+
let buf = @mut ~[8, 9];
719+
do (|| {
720+
reader.push_bytes(&mut *buf, 4);
721+
}).finally {
722+
// NB: Using rtassert here to trigger abort on failure since this is a should_fail test
723+
rtassert!(*buf == ~[8, 9, 10]);
724+
}
725+
}
726+
727+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2013 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 option::{Option, None};
12+
use rt::io::{Reader, Writer};
13+
14+
pub struct MockReader {
15+
read: ~fn(buf: &mut [u8]) -> Option<uint>,
16+
eof: ~fn() -> bool
17+
}
18+
19+
impl MockReader {
20+
pub fn new() -> MockReader {
21+
MockReader {
22+
read: |_| None,
23+
eof: || false
24+
}
25+
}
26+
}
27+
28+
impl Reader for MockReader {
29+
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { (self.read)(buf) }
30+
fn eof(&mut self) -> bool { (self.eof)() }
31+
}
32+
33+
pub struct MockWriter {
34+
write: ~fn(buf: &[u8]),
35+
flush: ~fn()
36+
}
37+
38+
impl MockWriter {
39+
pub fn new() -> MockWriter {
40+
MockWriter {
41+
write: |_| (),
42+
flush: || ()
43+
}
44+
}
45+
}
46+
47+
impl Writer for MockWriter {
48+
fn write(&mut self, buf: &[u8]) { (self.write)(buf) }
49+
fn flush(&mut self) { (self.flush)() }
50+
}

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ pub mod native {
316316
}
317317
}
318318

319+
/// Mock implementations for testing
320+
mod mock;
319321

320322
/// The type passed to I/O condition handlers to indicate error
321323
///
@@ -350,7 +352,8 @@ condition! {
350352

351353
pub trait Reader {
352354
/// Read bytes, up to the length of `buf` and place them in `buf`.
353-
/// Returns the number of bytes read, or `None` on EOF.
355+
/// Returns the number of bytes read, or `None` on EOF. The number
356+
/// of bytes read my be less than the number requested, even 0.
354357
///
355358
/// # Failure
356359
///
@@ -361,6 +364,7 @@ pub trait Reader {
361364
/// This doesn't take a `len` argument like the old `read`.
362365
/// Will people often need to slice their vectors to call this
363366
/// and will that be annoying?
367+
/// Is it actually possible for 0 bytes to be read successfully?
364368
fn read(&mut self, buf: &mut [u8]) -> Option<uint>;
365369

366370
/// Return whether the Reader has reached the end of the stream.
@@ -467,3 +471,11 @@ pub fn standard_error(kind: IoErrorKind) -> IoError {
467471
_ => fail!()
468472
}
469473
}
474+
475+
pub fn placeholder_error() -> IoError {
476+
IoError {
477+
kind: OtherIoError,
478+
desc: "Placeholder error. You shouldn't be seeing this",
479+
detail: None
480+
}
481+
}

0 commit comments

Comments
 (0)