@@ -25,41 +25,63 @@ Some examples of obvious things you might want to do
25
25
26
26
* Read lines from stdin
27
27
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);
30
32
}
33
+ ```
31
34
32
- * Read a complete file to a string, (converting newlines?)
35
+ * Read a complete file
33
36
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
+ ```
35
40
36
41
* Write a line to a file
37
42
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
+ ```
40
47
41
48
* Iterate over the lines of a file
42
49
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
+ ```
46
57
47
58
* Pull the lines of a file into a vector of strings
48
59
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
+ ```
50
65
51
66
* Make an simple HTTP request
67
+ XXX This needs more improvement: TcpStream constructor taking &str,
68
+ `write_str` and `write_line` methods.
52
69
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"));
56
74
let response = socket.read_to_end();
75
+ ```
57
76
58
77
* Connect based on URL? Requires thinking about where the URL type lives
59
78
and how to make protocol handlers extensible, e.g. the "tcp" protocol
60
79
yields a `TcpStream`.
80
+ XXX this is not implemented now.
61
81
62
- connect("tcp://localhost:8080");
82
+ ```rust
83
+ // connect("tcp://localhost:8080");
84
+ ```
63
85
64
86
# Terms
65
87
@@ -535,7 +557,8 @@ pub trait Reader {
535
557
///
536
558
/// # Failure
537
559
///
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.
539
562
fn read_to_end ( & mut self ) -> ~[ u8 ] {
540
563
let mut buf = vec:: with_capacity ( DEFAULT_BUF_SIZE ) ;
541
564
let mut keep_reading = true ;
@@ -561,7 +584,7 @@ pub trait Reader {
561
584
/// Raises the same conditions as the `read` method, for
562
585
/// each call to its `.next()` method.
563
586
/// 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 > {
565
588
extensions:: ByteIterator :: new ( self )
566
589
}
567
590
@@ -958,6 +981,30 @@ pub trait Stream: Reader + Writer { }
958
981
959
982
impl < T : Reader + Writer > Stream for T { }
960
983
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
+
961
1008
/// A Buffer is a type of reader which has some form of internal buffering to
962
1009
/// allow certain kinds of reading operations to be more optimized than others.
963
1010
/// This type extends the `Reader` trait with a few methods that are not
@@ -987,46 +1034,67 @@ pub trait Buffer: Reader {
987
1034
///
988
1035
/// # Failure
989
1036
///
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
992
1040
/// the newline character are not valid utf-8.
993
1041
fn read_line ( & mut self ) -> Option < ~str > {
994
1042
self . read_until ( '\n' as u8 ) . map ( str:: from_utf8_owned)
995
1043
}
996
1044
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
+
997
1057
/// Reads a sequence of bytes leading up to a specified delimeter. Once the
998
1058
/// specified byte is encountered, reading ceases and the bytes up to and
999
1059
/// including the delimiter are returned.
1000
1060
///
1001
1061
/// # Failure
1002
1062
///
1003
1063
/// This function will raise on the `io_error` condition if a read error is
1004
- /// encountered.
1064
+ /// encountered, except that `EndOfFile` is swallowed .
1005
1065
fn read_until ( & mut self , byte : u8 ) -> Option < ~[ u8 ] > {
1006
1066
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
+ }
1020
1087
}
1021
1088
}
1022
- }
1023
- if used == 0 {
1024
- break
1089
+ if used == 0 {
1090
+ break
1091
+ }
1092
+ self . consume ( used) ;
1025
1093
}
1026
1094
self . consume ( used) ;
1027
- }
1028
- self . consume ( used) ;
1095
+ } ) ;
1029
1096
return if res. len ( ) == 0 { None } else { Some ( res) } ;
1097
+
1030
1098
}
1031
1099
1032
1100
/// Reads the next utf8-encoded character from the underlying stream.
0 commit comments