Skip to content

Commit a95604f

Browse files
committed
auto merge of #9276 : alexcrichton/rust/dox, r=brson
Hopefull this will make our libstd docs appear a little more "full".
2 parents 2fd3c07 + 88bc11e commit a95604f

File tree

6 files changed

+336
-51
lines changed

6 files changed

+336
-51
lines changed

src/libstd/c_str.rs

+52
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,58 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
/*!
12+
13+
C-string manipulation and management
14+
15+
This modules provides the basic methods for creating and manipulating
16+
null-terminated strings for use with FFI calls (back to C). Most C APIs require
17+
that the string being passed to them is null-terminated, and by default rust's
18+
string types are *not* null terminated.
19+
20+
The other problem with translating Rust strings to C strings is that Rust
21+
strings can validly contain a null-byte in the middle of the string (0 is a
22+
valid unicode codepoint). This means that not all Rust strings can actually be
23+
translated to C strings.
24+
25+
# Creation of a C string
26+
27+
A C string is managed through the `CString` type defined in this module. It
28+
"owns" the internal buffer of characters and will automatically deallocate the
29+
buffer when the string is dropped. The `ToCStr` trait is implemented for `&str`
30+
and `&[u8]`, but the conversions can fail due to some of the limitations
31+
explained above.
32+
33+
This also means that currently whenever a C string is created, an allocation
34+
must be performed to place the data elsewhere (the lifetime of the C string is
35+
not tied to the lifetime of the original string/data buffer). If C strings are
36+
heavily used in applications, then caching may be advisable to prevent
37+
unnecessary amounts of allocations.
38+
39+
An example of creating and using a C string would be:
40+
41+
~~~{.rust}
42+
use std::libc;
43+
externfn!(fn puts(s: *libc::c_char))
44+
45+
let my_string = "Hello, world!";
46+
47+
// Allocate the C string with an explicit local that owns the string. The
48+
// `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope.
49+
let my_c_string = my_string.to_c_str();
50+
do my_c_string.with_ref |c_buffer| {
51+
unsafe { puts(c_buffer); }
52+
}
53+
54+
// Don't save off the allocation of the C string, the `c_buffer` will be
55+
// deallocated when this block returns!
56+
do my_string.with_c_str |c_buffer| {
57+
unsafe { puts(c_buffer); }
58+
}
59+
~~~
60+
61+
*/
62+
1163
use cast;
1264
use iter::{Iterator, range};
1365
use libc;

src/libstd/condition.rs

+142-33
Original file line numberDiff line numberDiff line change
@@ -8,71 +8,179 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
/*! Condition handling */
11+
/*!
1212
13-
#[allow(missing_doc)];
13+
Condition handling
14+
15+
Conditions are a utility used to deal with handling error conditions. The syntax
16+
of a condition handler strikes a resemblance to try/catch blocks in other
17+
languages, but condition handlers are *not* a form of exception handling in the
18+
same manner.
19+
20+
A condition is declared through the `condition!` macro provided by the compiler:
21+
22+
~~~{.rust}
23+
condition! {
24+
pub my_error: int -> ~str;
25+
}
26+
~~~
27+
28+
This macro declares an inner module called `my_error` with one static variable,
29+
`cond` that is a static `Condition` instance. To help understand what the other
30+
parameters are used for, an example usage of this condition would be:
31+
32+
~~~{.rust}
33+
do my_error::cond.trap(|raised_int| {
34+
35+
// the condition `my_error` was raised on, and the value it raised is stored
36+
// in `raised_int`. This closure must return a `~str` type (as specified in
37+
// the declaration of the condition
38+
if raised_int == 3 { ~"three" } else { ~"oh well" }
39+
40+
}).inside {
41+
42+
// The condition handler above is installed for the duration of this block.
43+
// That handler will override any previous handler, but the previous handler
44+
// is restored when this block returns (handlers nest)
45+
//
46+
// If any code from this block (or code from another block) raises on the
47+
// condition, then the above handler will be invoked (so long as there's no
48+
// other nested handler).
49+
50+
println(my_error::cond.raise(3)); // prints "three"
51+
println(my_error::cond.raise(4)); // prints "oh well"
52+
53+
}
54+
~~~
55+
56+
Condition handling is useful in cases where propagating errors is either to
57+
cumbersome or just not necessary in the first place. It should also be noted,
58+
though, that if there is not handler installed when a condition is raised, then
59+
the task invokes `fail!()` and will terminate.
60+
61+
## More Info
62+
63+
Condition handlers as an error strategy is well explained in the [conditions
64+
tutorial](http://static.rust-lang.org/doc/master/tutorial-conditions.html),
65+
along with comparing and contrasting it with other error handling strategies.
66+
67+
*/
1468

1569
use local_data;
1670
use prelude::*;
71+
use unstable::raw::Closure;
1772

18-
// helper for transmutation, shown below.
19-
type RustClosure = (int, int);
20-
73+
#[doc(hidden)]
2174
pub struct Handler<T, U> {
22-
handle: RustClosure,
23-
prev: Option<@Handler<T, U>>,
75+
priv handle: Closure,
76+
priv prev: Option<@Handler<T, U>>,
2477
}
2578

79+
/// This struct represents the state of a condition handler. It contains a key
80+
/// into TLS which holds the currently install handler, along with the name of
81+
/// the condition (useful for debugging).
82+
///
83+
/// This struct should never be created directly, but rather only through the
84+
/// `condition!` macro provided to all libraries using libstd.
2685
pub struct Condition<T, U> {
86+
/// Name of the condition handler
2787
name: &'static str,
88+
/// TLS key used to insert/remove values in TLS.
2889
key: local_data::Key<@Handler<T, U>>
2990
}
3091

3192
impl<T, U> Condition<T, U> {
93+
/// Creates an object which binds the specified handler. This will also save
94+
/// the current handler *on creation* such that when the `Trap` is consumed,
95+
/// it knows which handler to restore.
96+
///
97+
/// # Example
98+
///
99+
/// ~~~{.rust}
100+
/// condition! { my_error: int -> int; }
101+
///
102+
/// let trap = my_error::cond.trap(|error| error + 3);
103+
///
104+
/// // use `trap`'s inside method to register the handler and then run a
105+
/// // block of code with the handler registered
106+
/// ~~~
32107
pub fn trap<'a>(&'a self, h: &'a fn(T) -> U) -> Trap<'a, T, U> {
33-
unsafe {
34-
let p : *RustClosure = ::cast::transmute(&h);
35-
let prev = local_data::get(self.key, |k| k.map(|&x| *x));
36-
let h = @Handler { handle: *p, prev: prev };
37-
Trap { cond: self, handler: h }
38-
}
108+
let h: Closure = unsafe { ::cast::transmute(h) };
109+
let prev = local_data::get(self.key, |k| k.map(|&x| *x));
110+
let h = @Handler { handle: h, prev: prev };
111+
Trap { cond: self, handler: h }
39112
}
40113

114+
/// Raises on this condition, invoking any handler if one has been
115+
/// registered, or failing the current task otherwise.
116+
///
117+
/// While a condition handler is being run, the condition will have no
118+
/// handler listed, so a task failure will occur if the condition is
119+
/// re-raised during the handler.
120+
///
121+
/// # Arguments
122+
///
123+
/// * t - The argument to pass along to the condition handler.
124+
///
125+
/// # Return value
126+
///
127+
/// If a handler is found, its return value is returned, otherwise this
128+
/// function will not return.
41129
pub fn raise(&self, t: T) -> U {
42130
let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
43131
self.raise_default(t, || fail!(msg.clone()))
44132
}
45133

134+
/// Performs the same functionality as `raise`, except that when no handler
135+
/// is found the `default` argument is called instead of failing the task.
46136
pub fn raise_default(&self, t: T, default: &fn() -> U) -> U {
47-
unsafe {
48-
match local_data::pop(self.key) {
49-
None => {
50-
debug!("Condition.raise: found no handler");
51-
default()
52-
}
53-
Some(handler) => {
54-
debug!("Condition.raise: found handler");
55-
match handler.prev {
56-
None => {}
57-
Some(hp) => local_data::set(self.key, hp)
58-
}
59-
let handle : &fn(T) -> U =
60-
::cast::transmute(handler.handle);
61-
let u = handle(t);
62-
local_data::set(self.key, handler);
63-
u
137+
match local_data::pop(self.key) {
138+
None => {
139+
debug!("Condition.raise: found no handler");
140+
default()
141+
}
142+
Some(handler) => {
143+
debug!("Condition.raise: found handler");
144+
match handler.prev {
145+
None => {}
146+
Some(hp) => local_data::set(self.key, hp)
64147
}
148+
let handle : &fn(T) -> U = unsafe {
149+
::cast::transmute(handler.handle)
150+
};
151+
let u = handle(t);
152+
local_data::set(self.key, handler);
153+
u
65154
}
66155
}
67156
}
68157
}
69158

159+
/// A `Trap` is created when the `trap` method is invoked on a `Condition`, and
160+
/// it is used to actually bind a handler into the TLS slot reserved for this
161+
/// condition.
162+
///
163+
/// Normally this object is not dealt with directly, but rather it's directly
164+
/// used after being returned from `trap`
70165
struct Trap<'self, T, U> {
71-
cond: &'self Condition<T, U>,
72-
handler: @Handler<T, U>
166+
priv cond: &'self Condition<T, U>,
167+
priv handler: @Handler<T, U>
73168
}
74169

75170
impl<'self, T, U> Trap<'self, T, U> {
171+
/// Execute a block of code with this trap handler's exception handler
172+
/// registered.
173+
///
174+
/// # Example
175+
///
176+
/// ~~~{.rust}
177+
/// condition! { my_error: int -> int; }
178+
///
179+
/// let result = do my_error::cond.trap(|error| error + 3).inside {
180+
/// my_error::cond.raise(4)
181+
/// };
182+
/// assert_eq!(result, 7);
183+
/// ~~~
76184
pub fn inside<V>(&self, inner: &'self fn() -> V) -> V {
77185
let _g = Guard { cond: self.cond };
78186
debug!("Trap: pushing handler to TLS");
@@ -81,8 +189,9 @@ impl<'self, T, U> Trap<'self, T, U> {
81189
}
82190
}
83191

192+
#[doc(hidden)]
84193
struct Guard<'self, T, U> {
85-
cond: &'self Condition<T, U>
194+
priv cond: &'self Condition<T, U>
86195
}
87196

88197
#[unsafe_destructor]

src/libstd/fmt/mod.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@
1010

1111
/*!
1212
13-
# The Formatting Module
13+
The Formatting Module
1414
15-
This module contains the runtime support for the `format!` syntax extension. This
16-
macro is implemented in the compiler to emit calls to this module in order to
17-
format arguments at runtime into strings and streams.
15+
This module contains the runtime support for the `format!` syntax extension.
16+
This macro is implemented in the compiler to emit calls to this module in order
17+
to format arguments at runtime into strings and streams.
1818
1919
The functions contained in this module should not normally be used in everyday
20-
use cases of `format!`. The assumptions made by these functions are unsafe for all
21-
inputs, and the compiler performs a large amount of validation on the arguments
22-
to `format!` in order to ensure safety at runtime. While it is possible to call
23-
these functions directly, it is not recommended to do so in the general case.
20+
use cases of `format!`. The assumptions made by these functions are unsafe for
21+
all inputs, and the compiler performs a large amount of validation on the
22+
arguments to `format!` in order to ensure safety at runtime. While it is
23+
possible to call these functions directly, it is not recommended to do so in the
24+
general case.
2425
2526
## Usage
2627

src/libstd/iter.rs

+51-4
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,59 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
/*! Composable external iterators
11+
/*!
1212
13-
The `Iterator` trait defines an interface for objects which implement iteration as a state machine.
13+
Composable external iterators
1414
15-
Algorithms like `zip` are provided as `Iterator` implementations which wrap other objects
16-
implementing the `Iterator` trait.
15+
# The `Iterator` trait
16+
17+
This module defines Rust's core iteration trait. The `Iterator` trait has one
18+
un-implemented method, `next`. All other methods are derived through default
19+
methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`.
20+
21+
The goal of this module is to unify iteration across all containers in Rust.
22+
An iterator can be considered as a state machine which is used to track which
23+
element will be yielded next.
24+
25+
There are various extensions also defined in this module to assist with various
26+
types of iteration, such as the `DoubleEndedIterator` for iterating in reverse,
27+
the `FromIterator` trait for creating a container from an iterator, and much
28+
more.
29+
30+
## Rust's `for` loop
31+
32+
The special syntax used by rust's `for` loop is based around the `Iterator`
33+
trait defined in this module. For loops can be viewed as a syntactical expansion
34+
into a `loop`, for example, the `for` loop in this example is essentially
35+
translated to the `loop` below.
36+
37+
~~~{.rust}
38+
let values = ~[1, 2, 3];
39+
40+
// "Syntactical sugar" taking advantage of an iterator
41+
for &x in values.iter() {
42+
println!("{}", x);
43+
}
44+
45+
// Rough translation of the iteration without a `for` iterator.
46+
let mut it = values.iter();
47+
loop {
48+
match it.next() {
49+
Some(&x) => {
50+
println!("{}", x);
51+
}
52+
None => { break }
53+
}
54+
}
55+
~~~
56+
57+
This `for` loop syntax can be applied to any iterator over any type.
58+
59+
## Iteration protocol and more
60+
61+
More detailed information about iterators can be found in the [container
62+
tutorial](http://static.rust-lang.org/doc/master/tutorial-container.html) with
63+
the rest of the rust manuals.
1764
1865
*/
1966

0 commit comments

Comments
 (0)