@@ -25,41 +25,63 @@ Some examples of obvious things you might want to do
2525
2626* Read lines from stdin
2727
28- for stdin().each_line |line| {
29- println(line)
28+ ```rust
29+ let mut stdin = BufferedReader::new(stdin());
30+ for line in stdin.lines() {
31+ print(line);
3032 }
33+ ```
3134
32- * Read a complete file to a string, (converting newlines?)
35+ * Read a complete file
3336
34- let contents = File::open("message.txt").read_to_str(); // read_to_str??
37+ ```rust
38+ let contents = File::open(&Path::new("message.txt")).read_to_end();
39+ ```
3540
3641* Write a line to a file
3742
38- let file = File::open("message.txt", Create, Write);
39- file.write_line("hello, file!");
43+ ```rust
44+ let mut file = File::create(&Path::new("message.txt"));
45+ file.write(bytes!("hello, file!\n"));
46+ ```
4047
4148* Iterate over the lines of a file
4249
43- File::open("message.txt").each_line(|line| {
44- println(line)
45- })
50+ ```rust
51+ let path = Path::new("message.txt");
52+ let mut file = BufferedReader::new(File::open(&path));
53+ for line in file.lines() {
54+ print(line);
55+ }
56+ ```
4657
4758* Pull the lines of a file into a vector of strings
4859
49- let lines = File::open("message.txt").lines().to_vec();
60+ ```rust
61+ let path = Path::new("message.txt");
62+ let mut file = BufferedReader::new(File::open(&path));
63+ let lines: ~[~str] = file.lines().collect();
64+ ```
5065
5166* Make an simple HTTP request
67+ XXX This needs more improvement: TcpStream constructor taking &str,
68+ `write_str` and `write_line` methods.
5269
53- let socket = TcpStream::open("localhost:8080");
54- socket.write_line("GET / HTTP/1.0");
55- socket.write_line("");
70+ ```rust
71+ let addr = from_str::<SocketAddr>("127.0.0.1:8080").unwrap();
72+ let mut socket = TcpStream::connect(addr).unwrap();
73+ socket.write(bytes!("GET / HTTP/1.0\n\n"));
5674 let response = socket.read_to_end();
75+ ```
5776
5877* Connect based on URL? Requires thinking about where the URL type lives
5978 and how to make protocol handlers extensible, e.g. the "tcp" protocol
6079 yields a `TcpStream`.
80+ XXX this is not implemented now.
6181
62- connect("tcp://localhost:8080");
82+ ```rust
83+ // connect("tcp://localhost:8080");
84+ ```
6385
6486# Terms
6587
@@ -535,7 +557,8 @@ pub trait Reader {
535557 ///
536558 /// # Failure
537559 ///
538- /// Raises the same conditions as the `read` method.
560+ /// Raises the same conditions as the `read` method except for
561+ /// `EndOfFile` which is swallowed.
539562 fn read_to_end ( & mut self ) -> ~[ u8 ] {
540563 let mut buf = vec:: with_capacity ( DEFAULT_BUF_SIZE ) ;
541564 let mut keep_reading = true ;
@@ -561,7 +584,7 @@ pub trait Reader {
561584 /// Raises the same conditions as the `read` method, for
562585 /// each call to its `.next()` method.
563586 /// Ends the iteration if the condition is handled.
564- fn bytes ( self ) -> extensions:: ByteIterator < Self > {
587+ fn bytes < ' r > ( & ' r mut self ) -> extensions:: ByteIterator < ' r , Self > {
565588 extensions:: ByteIterator :: new ( self )
566589 }
567590
@@ -958,6 +981,30 @@ pub trait Stream: Reader + Writer { }
958981
959982impl < T : Reader + Writer > Stream for T { }
960983
984+ /// An iterator that reads a line on each iteration,
985+ /// until `.read_line()` returns `None`.
986+ ///
987+ /// # Notes about the Iteration Protocol
988+ ///
989+ /// The `LineIterator` may yield `None` and thus terminate
990+ /// an iteration, but continue to yield elements if iteration
991+ /// is attempted again.
992+ ///
993+ /// # Failure
994+ ///
995+ /// Raises the same conditions as the `read` method except for `EndOfFile`
996+ /// which is swallowed.
997+ /// Iteration yields `None` if the condition is handled.
998+ struct LineIterator < ' r , T > {
999+ priv buffer : & ' r mut T ,
1000+ }
1001+
1002+ impl < ' r , T : Buffer > Iterator < ~str > for LineIterator < ' r , T > {
1003+ fn next ( & mut self ) -> Option < ~str > {
1004+ self . buffer . read_line ( )
1005+ }
1006+ }
1007+
9611008/// A Buffer is a type of reader which has some form of internal buffering to
9621009/// allow certain kinds of reading operations to be more optimized than others.
9631010/// This type extends the `Reader` trait with a few methods that are not
@@ -987,46 +1034,67 @@ pub trait Buffer: Reader {
9871034 ///
9881035 /// # Failure
9891036 ///
990- /// This function will raise on the `io_error` condition if a read error is
991- /// encountered. The task will also fail if sequence of bytes leading up to
1037+ /// This function will raise on the `io_error` condition (except for
1038+ /// `EndOfFile` which is swallowed) if a read error is encountered.
1039+ /// The task will also fail if sequence of bytes leading up to
9921040 /// the newline character are not valid utf-8.
9931041 fn read_line ( & mut self ) -> Option < ~str > {
9941042 self . read_until ( '\n' as u8 ) . map ( str:: from_utf8_owned)
9951043 }
9961044
1045+ /// Create an iterator that reads a line on each iteration until EOF.
1046+ ///
1047+ /// # Failure
1048+ ///
1049+ /// Iterator raises the same conditions as the `read` method
1050+ /// except for `EndOfFile`.
1051+ fn lines < ' r > ( & ' r mut self ) -> LineIterator < ' r , Self > {
1052+ LineIterator {
1053+ buffer : self ,
1054+ }
1055+ }
1056+
9971057 /// Reads a sequence of bytes leading up to a specified delimeter. Once the
9981058 /// specified byte is encountered, reading ceases and the bytes up to and
9991059 /// including the delimiter are returned.
10001060 ///
10011061 /// # Failure
10021062 ///
10031063 /// This function will raise on the `io_error` condition if a read error is
1004- /// encountered.
1064+ /// encountered, except that `EndOfFile` is swallowed .
10051065 fn read_until ( & mut self , byte : u8 ) -> Option < ~[ u8 ] > {
10061066 let mut res = ~[ ] ;
1007- let mut used;
1008- loop {
1009- {
1010- let available = self . fill ( ) ;
1011- match available. iter ( ) . position ( |& b| b == byte) {
1012- Some ( i) => {
1013- res. push_all ( available. slice_to ( i + 1 ) ) ;
1014- used = i + 1 ;
1015- break
1016- }
1017- None => {
1018- res. push_all ( available) ;
1019- used = available. len ( ) ;
1067+
1068+ io_error:: cond. trap ( |e| {
1069+ if e. kind != EndOfFile {
1070+ io_error:: cond. raise ( e) ;
1071+ }
1072+ } ) . inside ( || {
1073+ let mut used;
1074+ loop {
1075+ {
1076+ let available = self . fill ( ) ;
1077+ match available. iter ( ) . position ( |& b| b == byte) {
1078+ Some ( i) => {
1079+ res. push_all ( available. slice_to ( i + 1 ) ) ;
1080+ used = i + 1 ;
1081+ break
1082+ }
1083+ None => {
1084+ res. push_all ( available) ;
1085+ used = available. len ( ) ;
1086+ }
10201087 }
10211088 }
1022- }
1023- if used == 0 {
1024- break
1089+ if used == 0 {
1090+ break
1091+ }
1092+ self . consume ( used) ;
10251093 }
10261094 self . consume ( used) ;
1027- }
1028- self . consume ( used) ;
1095+ } ) ;
10291096 return if res. len ( ) == 0 { None } else { Some ( res) } ;
1097+
10301098 }
10311099
10321100 /// Reads the next utf8-encoded character from the underlying stream.
0 commit comments