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.
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.
13 This module defines the Rust interface for synchronous I/O.
14 It models byte-oriented input and output with the Reader and Writer traits.
15 Types that implement both `Reader` and `Writer` and called 'streams',
16 and automatically implement trait `Stream`.
17 Implementations are provided for common I/O streams like
18 file, TCP, UDP, Unix domain sockets.
19 Readers and Writers may be composed to add capabilities like string
20 parsing, encoding, and compression.
22 This will likely live in std::io, not std::rt::io.
26 Some examples of obvious things you might want to do
28 * Read lines from stdin
30 for stdin().each_line |line| {
34 * Read a complete file to a string, (converting newlines?)
36 let contents = File::open("message.txt").read_to_str(); // read_to_str??
38 * Write a line to a file
40 let file = File::open("message.txt", Create, Write);
41 file.write_line("hello, file!");
43 * Iterate over the lines of a file
45 do File::open("message.txt").each_line |line| {
49 * Pull the lines of a file into a vector of strings
51 let lines = File::open("message.txt").line_iter().to_vec();
53 * Make an simple HTTP request
55 let socket = TcpStream::open("localhost:8080");
56 socket.write_line("GET / HTTP/1.0");
57 socket.write_line("");
58 let response = socket.read_to_end();
60 * Connect based on URL? Requires thinking about where the URL type lives
61 and how to make protocol handlers extensible, e.g. the "tcp" protocol
64 connect("tcp://localhost:8080");
68 * Reader - An I/O source, reads bytes into a buffer
69 * Writer - An I/O sink, writes bytes from a buffer
70 * Stream - Typical I/O sources like files and sockets are both Readers and Writers,
71 and are collectively referred to a `streams`.
72 * Decorator - A Reader or Writer that composes with others to add additional capabilities
73 such as encoding or decoding
75 # Blocking and synchrony
77 When discussing I/O you often hear the terms 'synchronous' and
78 'asynchronous', along with 'blocking' and 'non-blocking' compared and
79 contrasted. A synchronous I/O interface performs each I/O operation to
80 completion before proceeding to the next. Synchronous interfaces are
81 usually used in imperative style as a sequence of commands. An
82 asynchronous interface allows multiple I/O requests to be issued
83 simultaneously, without waiting for each to complete before proceeding
86 Asynchronous interfaces are used to achieve 'non-blocking' I/O. In
87 traditional single-threaded systems, performing a synchronous I/O
88 operation means that the program stops all activity (it 'blocks')
89 until the I/O is complete. Blocking is bad for performance when
90 there are other computations that could be done.
92 Asynchronous interfaces are most often associated with the callback
93 (continuation-passing) style popularised by node.js. Such systems rely
94 on all computations being run inside an event loop which maintains a
95 list of all pending I/O events; when one completes the registered
96 callback is run and the code that made the I/O request continues.
97 Such interfaces achieve non-blocking at the expense of being more
98 difficult to reason about.
100 Rust's I/O interface is synchronous - easy to read - and non-blocking by default.
102 Remember that Rust tasks are 'green threads', lightweight threads that
103 are multiplexed onto a single operating system thread. If that system
104 thread blocks then no other task may proceed. Rust tasks are
105 relatively cheap to create, so as long as other tasks are free to
106 execute then non-blocking code may be written by simply creating a new
109 When discussing blocking in regards to Rust's I/O model, we are
110 concerned with whether performing I/O blocks other Rust tasks from
111 proceeding. In other words, when a task calls `read`, it must then
112 wait (or 'sleep', or 'block') until the call to `read` is complete.
113 During this time, other tasks may or may not be executed, depending on
114 how `read` is implemented.
117 Rust's default I/O implementation is non-blocking; by cooperating
118 directly with the task scheduler it arranges to never block progress
119 of *other* tasks. Under the hood, Rust uses asynchronous I/O via a
120 per-scheduler (and hence per-thread) event loop. Synchronous I/O
121 requests are implemented by descheduling the running task and
122 performing an asynchronous request; the task is only resumed once the
123 asynchronous request completes.
125 For blocking (but possibly more efficient) implementations, look
126 in the `io::native` module.
130 I/O is an area where nearly every operation can result in unexpected
131 errors. It should allow errors to be handled efficiently.
132 It needs to be convenient to use I/O when you don't care
133 about dealing with specific errors.
135 Rust's I/O employs a combination of techniques to reduce boilerplate
136 while still providing feedback about errors. The basic strategy:
138 * Errors are fatal by default, resulting in task failure
139 * Errors raise the `io_error` condition which provides an opportunity to inspect
140 an IoError object containing details.
141 * Return values must have a sensible null or zero value which is returned
142 if a condition is handled successfully. This may be an `Option`, an empty
143 vector, or other designated error value.
144 * Common traits are implemented for `Option`, e.g. `impl<R: Reader> Reader for Option<R>`,
145 so that nullable values do not have to be 'unwrapped' before use.
147 These features combine in the API to allow for expressions like
148 `File::new("diary.txt").write_line("met a girl")` without having to
149 worry about whether "diary.txt" exists or whether the write
150 succeeds. As written, if either `new` or `write_line` encounters
151 an error the task will fail.
153 If you wanted to handle the error though you might write
155 let mut error = None;
156 do io_error::cond(|e: IoError| {
159 File::new("diary.txt").write_line("met a girl");
163 println("failed to write my diary");
166 XXX: Need better condition handling syntax
168 In this case the condition handler will have the opportunity to
169 inspect the IoError raised by either the call to `new` or the call to
170 `write_line`, but then execution will continue.
172 So what actually happens if `new` encounters an error? To understand
173 that it's important to know that what `new` returns is not a `File`
174 but an `Option<File>`. If the file does not open, and the condition
175 is handled, then `new` will simply return `None`. Because there is an
176 implementation of `Writer` (the trait required ultimately required for
177 types to implement `write_line`) there is no need to inspect or unwrap
178 the `Option<File>` and we simply call `write_line` on it. If `new`
179 returned a `None` then the followup call to `write_line` will also
182 ## Concerns about this strategy
184 This structure will encourage a programming style that is prone
185 to errors similar to null pointer dereferences.
186 In particular code written to ignore errors and expect conditions to be unhandled
187 will start passing around null or zero objects when wrapped in a condition handler.
189 * XXX: How should we use condition handlers that return values?
190 * XXX: Should EOF raise default conditions when EOF is not an error?
192 # Issues with i/o scheduler affinity, work stealing, task pinning
194 # Resource management
198 # Paths, URLs and overloaded constructors
208 Some I/O things don't belong in core
217 * Async I/O. We'll probably want it eventually
220 # XXX Questions and issues
222 * Should default constructors take `Path` or `&str`? `Path` makes simple cases verbose.
223 Overloading would be nice.
224 * Add overloading for Path and &str and Url &str
226 * print, println, etc.
228 * relationship with filesystem querying, Directory, File types etc.
229 * Rename Reader/Writer to ByteReader/Writer, make Reader/Writer generic?
230 * Can Port and Chan be implementations of a generic Reader<T>/Writer<T>?
231 * Trait for things that are both readers and writers, Stream?
232 * How to handle newline conversion
234 * File vs. FileStream? File is shorter but could also be used for getting file info
235 - maybe File is for general file querying and *also* has a static `open` method
236 * open vs. connect for generic stream opening
237 * Do we need `close` at all? dtors might be good enough
238 * How does I/O relate to the Iterator trait?
239 * std::base64 filters
240 * Using conditions is a big unknown since we don't have much experience with them
241 * Too many uses of OtherIoError
247 use str::{StrSlice, OwnedStr};
250 pub use self::stdio::stdin;
251 pub use self::stdio::stdout;
252 pub use self::stdio::stderr;
253 pub use self::stdio::print;
254 pub use self::stdio::println;
256 pub use self::file::FileStream;
257 pub use self::timer::Timer;
258 pub use self::net::ip::IpAddr;
259 pub use self::net::tcp::TcpListener;
260 pub use self::net::tcp::TcpStream;
261 pub use self::net::udp::UdpStream;
263 // Some extension traits that all Readers and Writers get.
264 pub use self::extensions::ReaderUtil;
265 pub use self::extensions::ReaderByteConversions;
266 pub use self::extensions::WriterByteConversions;
268 /// Synchronous, non-blocking file I/O.
271 /// Synchronous, non-blocking network I/O.
280 /// Readers and Writers for memory buffers and strings.
283 /// Non-blocking access to stdin, stdout, stderr
286 /// Implementations for Option
289 /// Basic stream compression. XXX: Belongs with other flate code
292 /// Interop between byte streams and pipes. Not sure where it belongs
293 pub mod comm_adapters;
298 /// Non-I/O things needed by the I/O module
304 /// Thread-blocking implementations
308 /// # XXX - implement this
311 /// # XXX - implement this
320 /// Mock implementations for testing
323 /// The default buffer size for various I/O operations
325 pub static DEFAULT_BUF_SIZE: uint = 1024 * 64;
327 /// The type passed to I/O condition handlers to indicate error
331 /// Is something like this sufficient? It's kind of archaic
338 // FIXME: #8242 implementing manually because deriving doesn't work for some reason
339 impl ToStr for IoError {
340 fn to_str(&self) -> ~str {
341 let mut s = ~"IoError { kind: ";
342 s.push_str(self.kind.to_str());
343 s.push_str(", desc: ");
344 s.push_str(self.desc);
345 s.push_str(", detail: ");
346 s.push_str(self.detail.to_str());
353 pub enum IoErrorKind {
366 // FIXME: #8242 implementing manually because deriving doesn't work for some reason
367 impl ToStr for IoErrorKind {
368 fn to_str(&self) -> ~str {
370 PreviousIoError => ~"PreviousIoError",
371 OtherIoError => ~"OtherIoError",
372 EndOfFile => ~"EndOfFile",
373 FileNotFound => ~"FileNotFound",
374 PermissionDenied => ~"PermissionDenied",
375 ConnectionFailed => ~"ConnectionFailed",
377 ConnectionRefused => ~"ConnectionRefused",
378 ConnectionReset => ~"ConnectionReset",
379 BrokenPipe => ~"BrokenPipe"
384 // XXX: Can't put doc comments on macros
385 // Raised by `I/O` operations on error.
387 // FIXME (#6009): uncomment `pub` after expansion support lands.
388 /*pub*/ io_error: super::IoError -> ();
391 // XXX: Can't put doc comments on macros
392 // Raised by `read` on error
394 // FIXME (#6009): uncomment `pub` after expansion support lands.
395 /*pub*/ read_error: super::IoError -> ();
399 /// Read bytes, up to the length of `buf` and place them in `buf`.
400 /// Returns the number of bytes read. The number of bytes read my
401 /// be less than the number requested, even 0. Returns `None` on EOF.
405 /// Raises the `read_error` condition on error. If the condition
406 /// is handled then no guarantee is made about the number of bytes
407 /// read and the contents of `buf`. If the condition is handled
408 /// returns `None` (XXX see below).
412 /// * Should raise_default error on eof?
413 /// * If the condition is handled it should still return the bytes read,
414 /// in which case there's no need to return Option - but then you *have*
415 /// to install a handler to detect eof.
417 /// This doesn't take a `len` argument like the old `read`.
418 /// Will people often need to slice their vectors to call this
419 /// and will that be annoying?
420 /// Is it actually possible for 0 bytes to be read successfully?
421 fn read(&mut self, buf: &mut [u8]) -> Option<uint>;
423 /// Return whether the Reader has reached the end of the stream.
427 /// let reader = FileStream::new()
428 /// while !reader.eof() {
429 /// println(reader.read_line());
434 /// Returns `true` on failure.
435 fn eof(&mut self) -> bool;
439 /// Write the given buffer
443 /// Raises the `io_error` condition on error
444 fn write(&mut self, buf: &[u8]);
450 pub trait Stream: Reader + Writer { }
453 /// Seek from the beginning of the stream
455 /// Seek from the end of the stream
457 /// Seek from the current position
462 /// * Are `u64` and `i64` the right choices?
464 /// Return position of file cursor in the stream
465 fn tell(&self) -> u64;
467 /// Seek to an offset in a stream
469 /// A successful seek clears the EOF indicator.
473 /// * What is the behavior when seeking past the end of a stream?
474 fn seek(&mut self, pos: i64, style: SeekStyle);
477 /// A listener is a value that listens for connections
478 pub trait Listener<S> {
479 /// Wait for and accept an incoming connection
481 /// Returns `None` on timeout.
485 /// Raises `io_error` condition. If the condition is handled,
486 /// then `accept` returns `None`.
487 fn accept(&mut self) -> Option<S>;
490 /// Common trait for decorator types.
492 /// Provides accessors to get the inner, 'decorated' values. The I/O library
493 /// uses decorators to add functionality like compression and encryption to I/O
498 /// Is this worth having a trait for? May be overkill
499 pub trait Decorator<T> {
500 /// Destroy the decorator and extract the decorated value
504 /// Because this takes `self' one could never 'undecorate' a Reader/Writer
505 /// that has been boxed. Is that ok? This feature is mostly useful for
506 /// extracting the buffer from MemWriter
509 /// Take an immutable reference to the decorated value
510 fn inner_ref<'a>(&'a self) -> &'a T;
512 /// Take a mutable reference to the decorated value
513 fn inner_mut_ref<'a>(&'a mut self) -> &'a mut T;
516 pub fn standard_error(kind: IoErrorKind) -> IoError {
520 kind: PreviousIoError,
521 desc: "Failing due to a previous I/O error",
536 pub fn placeholder_error() -> IoError {
539 desc: "Placeholder error. You shouldn't be seeing this",
544 /// Instructions on how to open a file and return a `FileStream`.
546 /// Opens an existing file. IoError if file does not exist.
548 /// Creates a file. IoError if file exists.
550 /// Opens an existing file or creates a new one.
552 /// Opens an existing file or creates a new one, positioned at EOF.
554 /// Opens an existing file, truncating it to 0 bytes.
556 /// Opens an existing file or creates a new one, truncating it to 0 bytes.
560 /// Access permissions with which the file should be opened.
561 /// `FileStream`s opened with `Read` will raise an `io_error` condition if written to.
562 pub enum FileAccess {