From 623e475146670f64d1cfec0e5924d82d46729724 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 21 Feb 2014 23:53:37 -0800 Subject: [PATCH 1/5] test: 'ratcher' is not a word --- src/libtest/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 4a9575c78f465..9e457870994b9 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -608,7 +608,7 @@ impl ConsoleTestState { let ratchet_success = match *ratchet_metrics { None => true, Some(ref pth) => { - try!(self.write_plain(format!("\nusing metrics ratcher: {}\n", + try!(self.write_plain(format!("\nusing metrics ratchet: {}\n", pth.display()))); match ratchet_pct { None => (), From 713ca7d5402fb33ea1ac4f34a50618d60156d1d3 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 23 Feb 2014 09:11:36 +1100 Subject: [PATCH 2/5] std: mark two helper functions #[inline]. `str::utf8_char_width` and `char::from_u32` are tiny, which means it's a big performance hit to call them in a tight loop outside libstd. --- src/libstd/char.rs | 1 + src/libstd/str.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libstd/char.rs b/src/libstd/char.rs index 71a297d71765e..1ec89d1850f0e 100644 --- a/src/libstd/char.rs +++ b/src/libstd/char.rs @@ -69,6 +69,7 @@ static TAG_FOUR_B: uint = 240u; pub static MAX: char = '\U0010ffff'; /// Convert from `u32` to a character. +#[inline] pub fn from_u32(i: u32) -> Option { // catch out-of-bounds and surrogates if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) { diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 123b4957599f5..ecd297b72a41b 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1061,6 +1061,7 @@ static UTF8_CHAR_WIDTH: [u8, ..256] = [ ]; /// Given a first byte, determine how many bytes are in this UTF-8 character +#[inline] pub fn utf8_char_width(b: u8) -> uint { return UTF8_CHAR_WIDTH[b] as uint; } From a8941c3e04fc7900c3e9a4e82b6a63bc9018c769 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 22 Feb 2014 15:53:54 -0800 Subject: [PATCH 3/5] std: Remove some nonsense from old std::io docs Most of this stuff is irrelevant implementation notes from last year. This trims out the stuff that isn't appropriate for user-facing docs. --- src/libstd/io/mod.rs | 167 +++++++++++-------------------------------- 1 file changed, 41 insertions(+), 126 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index d9419fb3ebc47..91a8d59932689 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! Synchronous I/O +// FIXME: cover these topics: +// path, reader, writer, stream, raii (close not needed), +// stdio, print!, println!, file access, process spawning, +// error handling -This module defines the Rust interface for synchronous I/O. -It models byte-oriented input and output with the Reader and Writer traits. -Types that implement both `Reader` and `Writer` are called 'streams', -and automatically implement the `Stream` trait. -Implementations are provided for common I/O streams like -file, TCP, UDP, Unix domain sockets. -Readers and Writers may be composed to add capabilities like string -parsing, encoding, and compression. + +/*! I/O, including files, networking, timers, and processes + +`std::io` provides Rust's basic I/O types, +for reading and writing to files, TCP, UDP, +and other types of sockets and pipes, +manipulating the file system, spawning processes and signal handling. # Examples @@ -77,9 +79,7 @@ Some examples of obvious things you might want to do let lines: ~[~str] = file.lines().collect(); ``` -* Make a simple HTTP request - FIXME This needs more improvement: TcpStream constructor taking &str, - `write_str` and `write_line` methods. +* Make a simple TCP client connection and request ```rust,should_fail # #[allow(unused_must_use)]; @@ -92,72 +92,35 @@ Some examples of obvious things you might want to do let response = socket.read_to_end(); ``` -* Connect based on URL? Requires thinking about where the URL type lives - and how to make protocol handlers extensible, e.g. the "tcp" protocol - yields a `TcpStream`. - FIXME this is not implemented now. +* Make a simple TCP server ```rust - // connect("tcp://localhost:8080"); + # fn main() { } + # fn foo() { + # #[allow(unused_must_use, dead_code)]; + use std::io::net::tcp::TcpListener; + use std::io::net::ip::{Ipv4Addr, SocketAddr}; + use std::io::{Acceptor, Listener}; + + let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 80 }; + let listener = TcpListener::bind(addr); + + // bind the listener to the specified address + let mut acceptor = listener.listen(); + + // accept connections and process them + # fn handle_client(_: T) {} + for stream in acceptor.incoming() { + spawn(proc() { + handle_client(stream); + }); + } + + // close the socket server + drop(acceptor); + # } ``` -# Terms - -* Reader - An I/O source, reads bytes into a buffer -* Writer - An I/O sink, writes bytes from a buffer -* Stream - Typical I/O sources like files and sockets are both Readers and Writers, - and are collectively referred to a `streams`. - such as encoding or decoding - -# Blocking and synchrony - -When discussing I/O you often hear the terms 'synchronous' and -'asynchronous', along with 'blocking' and 'non-blocking' compared and -contrasted. A synchronous I/O interface performs each I/O operation to -completion before proceeding to the next. Synchronous interfaces are -usually used in imperative style as a sequence of commands. An -asynchronous interface allows multiple I/O requests to be issued -simultaneously, without waiting for each to complete before proceeding -to the next. - -Asynchronous interfaces are used to achieve 'non-blocking' I/O. In -traditional single-threaded systems, performing a synchronous I/O -operation means that the program stops all activity (it 'blocks') -until the I/O is complete. Blocking is bad for performance when -there are other computations that could be done. - -Asynchronous interfaces are most often associated with the callback -(continuation-passing) style popularised by node.js. Such systems rely -on all computations being run inside an event loop which maintains a -list of all pending I/O events; when one completes the registered -callback is run and the code that made the I/O request continues. -Such interfaces achieve non-blocking at the expense of being more -difficult to reason about. - -Rust's I/O interface is synchronous - easy to read - and non-blocking by default. - -Remember that Rust tasks are 'green threads', lightweight threads that -are multiplexed onto a single operating system thread. If that system -thread blocks then no other task may proceed. Rust tasks are -relatively cheap to create, so as long as other tasks are free to -execute then non-blocking code may be written by simply creating a new -task. - -When discussing blocking in regards to Rust's I/O model, we are -concerned with whether performing I/O blocks other Rust tasks from -proceeding. In other words, when a task calls `read`, it must then -wait (or 'sleep', or 'block') until the call to `read` is complete. -During this time, other tasks may or may not be executed, depending on -how `read` is implemented. - - -Rust's default I/O implementation is non-blocking; by cooperating -directly with the task scheduler it arranges to never block progress -of *other* tasks. Under the hood, Rust uses asynchronous I/O via a -per-scheduler (and hence per-thread) event loop. Synchronous I/O -requests are implemented by descheduling the running task and -performing an asynchronous request; the task is only resumed once the -asynchronous request completes. # Error Handling @@ -170,10 +133,11 @@ Rust's I/O employs a combination of techniques to reduce boilerplate while still providing feedback about errors. The basic strategy: * All I/O operations return `IoResult` which is equivalent to - `Result`. The core `Result` type is defined in the `std::result` + `Result`. The `Result` type is defined in the `std::result` module. * If the `Result` type goes unused, then the compiler will by default emit a - warning about the unused result. + warning about the unused result. This is because `Result` has the + `#[must_use]` attribute. * Common traits are implemented for `IoResult`, e.g. `impl Reader for IoResult`, so that error values do not have to be 'unwrapped' before use. @@ -192,7 +156,7 @@ If you wanted to handle the error though you might write: use std::io::File; match File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n")) { - Ok(()) => { /* succeeded */ } + Ok(()) => (), // succeeded Err(e) => println!("failed to write to my diary: {}", e), } @@ -208,55 +172,6 @@ need to inspect or unwrap the `IoResult` and we simply call `write_line` on it. If `new` returned an `Err(..)` then the followup call to `write_line` will also return an error. -# Issues with i/o scheduler affinity, work stealing, task pinning - -# Resource management - -* `close` vs. RAII - -# Paths, URLs and overloaded constructors - - - -# Scope - -In scope for core - -* Url? - -Some I/O things don't belong in core - - - url - - net - `fn connect` - - http - - flate - -Out of scope - -* Async I/O. We'll probably want it eventually - - -# FIXME Questions and issues - -* Should default constructors take `Path` or `&str`? `Path` makes simple cases verbose. - Overloading would be nice. -* Add overloading for Path and &str and Url &str -* stdin/err/out -* print, println, etc. -* fsync -* relationship with filesystem querying, Directory, File types etc. -* Rename Reader/Writer to ByteReader/Writer, make Reader/Writer generic? -* Can Port and Chan be implementations of a generic Reader/Writer? -* Trait for things that are both readers and writers, Stream? -* How to handle newline conversion -* String conversion -* open vs. connect for generic stream opening -* Do we need `close` at all? dtors might be good enough -* How does I/O relate to the Iterator trait? -* std::base64 filters -* Using conditions is a big unknown since we don't have much experience with them -* Too many uses of OtherIoError - */ #[allow(missing_doc)]; From e9bb571affe69e9b116c7258eaa5c49d199adbdb Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Sun, 23 Feb 2014 19:52:33 +0100 Subject: [PATCH 4/5] Fix C function FFI example in the Rust cheatsheet --- src/doc/complement-cheatsheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/complement-cheatsheet.md b/src/doc/complement-cheatsheet.md index 79f33a8856273..debe4a27f56b8 100644 --- a/src/doc/complement-cheatsheet.md +++ b/src/doc/complement-cheatsheet.md @@ -211,7 +211,7 @@ Description C signature Equivalent ---------------------- ---------------------------------------------- ------------------------------------------ no parameters `void foo(void);` `fn foo();` return value `int foo(void);` `fn foo() -> c_int;` -function parameters `void foo(int x, int y);` `fn foo(x: int, y: int);` +function parameters `void foo(int x, int y);` `fn foo(x: c_int, y: c_int);` in-out pointers `void foo(const int* in_ptr, int* out_ptr);` `fn foo(in_ptr: *c_int, out_ptr: *mut c_int);` Note: The Rust signatures should be wrapped in an `extern "ABI" { ... }` block. From 778d03236450655907a6e8dfbe3899a9e76b5ff0 Mon Sep 17 00:00:00 2001 From: kud1ing Date: Sun, 23 Feb 2014 22:23:10 +0100 Subject: [PATCH 5/5] Tutorial: fix typo --- src/doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 304dc1fb5af43..d21f97f76ab0a 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -1026,7 +1026,7 @@ type was invalid because the size was infinite! An *owned box* (`~`) uses a dynamic memory allocation to provide the invariant of always being the size of a pointer, regardless of the contained type. This -can be leverage to create a valid `List` definition: +can be leveraged to create a valid `List` definition: ~~~ enum List {