Skip to content

Commit bfde029

Browse files
committed
auto merge of #10861 : alexcrichton/rust/iostr, r=pcwalton
These methods are sorely needed on readers and writers, and I believe that the encoding story should be solved with composition. This commit adds back the missed functions when reading/writing strings onto generic Readers/Writers.
2 parents bb9c5c4 + a2a6720 commit bfde029

File tree

2 files changed

+73
-24
lines changed

2 files changed

+73
-24
lines changed

src/libstd/io/mem.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,24 @@ mod test {
408408
let mut r = BufReader::new(bytes!(0x80));
409409
assert_eq!(r.read_char(), None);
410410
}
411+
412+
#[test]
413+
fn test_write_strings() {
414+
let mut writer = MemWriter::new();
415+
writer.write_str("testing");
416+
writer.write_line("testing");
417+
writer.write_str("testing");
418+
let mut r = BufReader::new(*writer.inner_ref());
419+
assert_eq!(r.read_to_str(), ~"testingtesting\ntesting");
420+
}
421+
422+
#[test]
423+
fn test_read_whole_string_bad() {
424+
let buf = [0xff];
425+
let mut r = BufReader::new(buf);
426+
match result(|| r.read_to_str()) {
427+
Ok(..) => fail!(),
428+
Err(..) => {}
429+
}
430+
}
411431
}

src/libstd/io/mod.rs

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ pub enum IoErrorKind {
407407
MismatchedFileTypeForOperation,
408408
ResourceUnavailable,
409409
IoUnavailable,
410+
InvalidInput,
410411
}
411412

412413
// FIXME: #8242 implementing manually because deriving doesn't work for some reason
@@ -430,6 +431,7 @@ impl ToStr for IoErrorKind {
430431
IoUnavailable => ~"IoUnavailable",
431432
ResourceUnavailable => ~"ResourceUnavailable",
432433
ConnectionAborted => ~"ConnectionAborted",
434+
InvalidInput => ~"InvalidInput",
433435
}
434436
}
435437
}
@@ -601,6 +603,23 @@ pub trait Reader {
601603
return buf;
602604
}
603605

606+
/// Reads all of the remaining bytes of this stream, interpreting them as a
607+
/// UTF-8 encoded stream. The corresponding string is returned.
608+
///
609+
/// # Failure
610+
///
611+
/// This function will raise all the same conditions as the `read` method,
612+
/// along with raising a condition if the input is not valid UTF-8.
613+
fn read_to_str(&mut self) -> ~str {
614+
match str::from_utf8_owned_opt(self.read_to_end()) {
615+
Some(s) => s,
616+
None => {
617+
io_error::cond.raise(standard_error(InvalidInput));
618+
~""
619+
}
620+
}
621+
}
622+
604623
/// Create an iterator that reads a single byte on
605624
/// each iteration, until EOF.
606625
///
@@ -861,6 +880,28 @@ pub trait Writer {
861880
/// decide whether their stream needs to be buffered or not.
862881
fn flush(&mut self) {}
863882

883+
/// Write a rust string into this sink.
884+
///
885+
/// The bytes written will be the UTF-8 encoded version of the input string.
886+
/// If other encodings are desired, it is recommended to compose this stream
887+
/// with another performing the conversion, or to use `write` with a
888+
/// converted byte-array instead.
889+
fn write_str(&mut self, s: &str) {
890+
self.write(s.as_bytes());
891+
}
892+
893+
/// Writes a string into this sink, and then writes a literal newline (`\n`)
894+
/// byte afterwards. Note that the writing of the newline is *not* atomic in
895+
/// the sense that the call to `write` is invoked twice (once with the
896+
/// string and once with a newline character).
897+
///
898+
/// If other encodings or line ending flavors are desired, it is recommended
899+
/// that the `write` method is used specifically instead.
900+
fn write_line(&mut self, s: &str) {
901+
self.write_str(s);
902+
self.write(['\n' as u8]);
903+
}
904+
864905
/// Write the result of passing n through `int::to_str_bytes`.
865906
fn write_int(&mut self, n: int) {
866907
int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
@@ -1053,7 +1094,7 @@ pub trait Buffer: Reader {
10531094
/// so they should no longer be returned in calls to `fill` or `read`.
10541095
fn consume(&mut self, amt: uint);
10551096

1056-
/// Reads the next line of input, interpreted as a sequence of utf-8
1097+
/// Reads the next line of input, interpreted as a sequence of UTF-8
10571098
/// encoded unicode codepoints. If a newline is encountered, then the
10581099
/// newline is contained in the returned string.
10591100
///
@@ -1062,7 +1103,7 @@ pub trait Buffer: Reader {
10621103
/// This function will raise on the `io_error` condition (except for
10631104
/// `EndOfFile` which is swallowed) if a read error is encountered.
10641105
/// The task will also fail if sequence of bytes leading up to
1065-
/// the newline character are not valid utf-8.
1106+
/// the newline character are not valid UTF-8.
10661107
fn read_line(&mut self) -> Option<~str> {
10671108
self.read_until('\n' as u8).map(str::from_utf8_owned)
10681109
}
@@ -1246,29 +1287,17 @@ pub trait Decorator<T> {
12461287
}
12471288

12481289
pub fn standard_error(kind: IoErrorKind) -> IoError {
1249-
match kind {
1250-
PreviousIoError => {
1251-
IoError {
1252-
kind: PreviousIoError,
1253-
desc: "Failing due to a previous I/O error",
1254-
detail: None
1255-
}
1256-
}
1257-
EndOfFile => {
1258-
IoError {
1259-
kind: EndOfFile,
1260-
desc: "End of file",
1261-
detail: None
1262-
}
1263-
}
1264-
IoUnavailable => {
1265-
IoError {
1266-
kind: IoUnavailable,
1267-
desc: "I/O is unavailable",
1268-
detail: None
1269-
}
1270-
}
1290+
let desc = match kind {
1291+
PreviousIoError => "failing due to previous I/O error",
1292+
EndOfFile => "end of file",
1293+
IoUnavailable => "I/O is unavailable",
1294+
InvalidInput => "invalid input",
12711295
_ => fail!()
1296+
};
1297+
IoError {
1298+
kind: kind,
1299+
desc: desc,
1300+
detail: None,
12721301
}
12731302
}
12741303

0 commit comments

Comments
 (0)