about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-09-17 19:42:07 -0700
committerAlex Crichton <alex@alexcrichton.com>2013-09-17 20:50:23 -0700
commit88bc11e646c8d1db7ac7894f74e2f660d9a82c54 (patch)
treee0dfde7157dadefae8bb2420e8e93f9eefc95bfa /src/libstd
parent0efc4822e93221714aa7d142de44a057bdbad2ca (diff)
downloadrust-88bc11e646c8d1db7ac7894f74e2f660d9a82c54.tar.gz
rust-88bc11e646c8d1db7ac7894f74e2f660d9a82c54.zip
Document a few undocumented modules in libstd
Hopefull this will make our libstd docs appear a little more "full".
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/c_str.rs52
-rw-r--r--src/libstd/condition.rs175
-rw-r--r--src/libstd/fmt/mod.rs17
-rw-r--r--src/libstd/iter.rs55
-rw-r--r--src/libstd/str.rs86
-rw-r--r--src/libstd/vec.rs2
6 files changed, 336 insertions, 51 deletions
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index 75598b300a3..0e623f33ff7 100644
--- a/src/libstd/c_str.rs
+++ b/src/libstd/c_str.rs
@@ -8,6 +8,58 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+/*!
+
+C-string manipulation and management
+
+This modules provides the basic methods for creating and manipulating
+null-terminated strings for use with FFI calls (back to C). Most C APIs require
+that the string being passed to them is null-terminated, and by default rust's
+string types are *not* null terminated.
+
+The other problem with translating Rust strings to C strings is that Rust
+strings can validly contain a null-byte in the middle of the string (0 is a
+valid unicode codepoint). This means that not all Rust strings can actually be
+translated to C strings.
+
+# Creation of a C string
+
+A C string is managed through the `CString` type defined in this module. It
+"owns" the internal buffer of characters and will automatically deallocate the
+buffer when the string is dropped. The `ToCStr` trait is implemented for `&str`
+and `&[u8]`, but the conversions can fail due to some of the limitations
+explained above.
+
+This also means that currently whenever a C string is created, an allocation
+must be performed to place the data elsewhere (the lifetime of the C string is
+not tied to the lifetime of the original string/data buffer). If C strings are
+heavily used in applications, then caching may be advisable to prevent
+unnecessary amounts of allocations.
+
+An example of creating and using a C string would be:
+
+~~~{.rust}
+use std::libc;
+externfn!(fn puts(s: *libc::c_char))
+
+let my_string = "Hello, world!";
+
+// Allocate the C string with an explicit local that owns the string. The
+// `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope.
+let my_c_string = my_string.to_c_str();
+do my_c_string.with_ref |c_buffer| {
+    unsafe { puts(c_buffer); }
+}
+
+// Don't save off the allocation of the C string, the `c_buffer` will be
+// deallocated when this block returns!
+do my_string.with_c_str |c_buffer| {
+    unsafe { puts(c_buffer); }
+}
+~~~
+
+*/
+
 use cast;
 use iter::{Iterator, range};
 use libc;
diff --git a/src/libstd/condition.rs b/src/libstd/condition.rs
index 954b8bd7330..c47dcfe3de6 100644
--- a/src/libstd/condition.rs
+++ b/src/libstd/condition.rs
@@ -8,71 +8,179 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*! Condition handling */
+/*!
 
-#[allow(missing_doc)];
+Condition handling
+
+Conditions are a utility used to deal with handling error conditions. The syntax
+of a condition handler strikes a resemblance to try/catch blocks in other
+languages, but condition handlers are *not* a form of exception handling in the
+same manner.
+
+A condition is declared through the `condition!` macro provided by the compiler:
+
+~~~{.rust}
+condition! {
+    pub my_error: int -> ~str;
+}
+~~~
+
+This macro declares an inner module called `my_error` with one static variable,
+`cond` that is a static `Condition` instance. To help understand what the other
+parameters are used for, an example usage of this condition would be:
+
+~~~{.rust}
+do my_error::cond.trap(|raised_int| {
+
+    // the condition `my_error` was raised on, and the value it raised is stored
+    // in `raised_int`. This closure must return a `~str` type (as specified in
+    // the declaration of the condition
+    if raised_int == 3 { ~"three" } else { ~"oh well" }
+
+}).inside {
+
+    // The condition handler above is installed for the duration of this block.
+    // That handler will override any previous handler, but the previous handler
+    // is restored when this block returns (handlers nest)
+    //
+    // If any code from this block (or code from another block) raises on the
+    // condition, then the above handler will be invoked (so long as there's no
+    // other nested handler).
+
+    println(my_error::cond.raise(3)); // prints "three"
+    println(my_error::cond.raise(4)); // prints "oh well"
+
+}
+~~~
+
+Condition handling is useful in cases where propagating errors is either to
+cumbersome or just not necessary in the first place. It should also be noted,
+though, that if there is not handler installed when a condition is raised, then
+the task invokes `fail!()` and will terminate.
+
+## More Info
+
+Condition handlers as an error strategy is well explained in the [conditions
+tutorial](http://static.rust-lang.org/doc/master/tutorial-conditions.html),
+along with comparing and contrasting it with other error handling strategies.
+
+*/
 
 use local_data;
 use prelude::*;
+use unstable::raw::Closure;
 
-// helper for transmutation, shown below.
-type RustClosure = (int, int);
-
+#[doc(hidden)]
 pub struct Handler<T, U> {
-    handle: RustClosure,
-    prev: Option<@Handler<T, U>>,
+    priv handle: Closure,
+    priv prev: Option<@Handler<T, U>>,
 }
 
+/// This struct represents the state of a condition handler. It contains a key
+/// into TLS which holds the currently install handler, along with the name of
+/// the condition (useful for debugging).
+///
+/// This struct should never be created directly, but rather only through the
+/// `condition!` macro provided to all libraries using libstd.
 pub struct Condition<T, U> {
+    /// Name of the condition handler
     name: &'static str,
+    /// TLS key used to insert/remove values in TLS.
     key: local_data::Key<@Handler<T, U>>
 }
 
 impl<T, U> Condition<T, U> {
+    /// Creates an object which binds the specified handler. This will also save
+    /// the current handler *on creation* such that when the `Trap` is consumed,
+    /// it knows which handler to restore.
+    ///
+    /// # Example
+    ///
+    /// ~~~{.rust}
+    /// condition! { my_error: int -> int; }
+    ///
+    /// let trap = my_error::cond.trap(|error| error + 3);
+    ///
+    /// // use `trap`'s inside method to register the handler and then run a
+    /// // block of code with the handler registered
+    /// ~~~
     pub fn trap<'a>(&'a self, h: &'a fn(T) -> U) -> Trap<'a, T, U> {
-        unsafe {
-            let p : *RustClosure = ::cast::transmute(&h);
-            let prev = local_data::get(self.key, |k| k.map(|&x| *x));
-            let h = @Handler { handle: *p, prev: prev };
-            Trap { cond: self, handler: h }
-        }
+        let h: Closure = unsafe { ::cast::transmute(h) };
+        let prev = local_data::get(self.key, |k| k.map(|&x| *x));
+        let h = @Handler { handle: h, prev: prev };
+        Trap { cond: self, handler: h }
     }
 
+    /// Raises on this condition, invoking any handler if one has been
+    /// registered, or failing the current task otherwise.
+    ///
+    /// While a condition handler is being run, the condition will have no
+    /// handler listed, so a task failure will occur if the condition is
+    /// re-raised during the handler.
+    ///
+    /// # Arguments
+    ///
+    /// * t - The argument to pass along to the condition handler.
+    ///
+    /// # Return value
+    ///
+    /// If a handler is found, its return value is returned, otherwise this
+    /// function will not return.
     pub fn raise(&self, t: T) -> U {
         let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
         self.raise_default(t, || fail!(msg.clone()))
     }
 
+    /// Performs the same functionality as `raise`, except that when no handler
+    /// is found the `default` argument is called instead of failing the task.
     pub fn raise_default(&self, t: T, default: &fn() -> U) -> U {
-        unsafe {
-            match local_data::pop(self.key) {
-                None => {
-                    debug!("Condition.raise: found no handler");
-                    default()
-                }
-                Some(handler) => {
-                    debug!("Condition.raise: found handler");
-                    match handler.prev {
-                        None => {}
-                        Some(hp) => local_data::set(self.key, hp)
-                    }
-                    let handle : &fn(T) -> U =
-                        ::cast::transmute(handler.handle);
-                    let u = handle(t);
-                    local_data::set(self.key, handler);
-                    u
+        match local_data::pop(self.key) {
+            None => {
+                debug!("Condition.raise: found no handler");
+                default()
+            }
+            Some(handler) => {
+                debug!("Condition.raise: found handler");
+                match handler.prev {
+                    None => {}
+                    Some(hp) => local_data::set(self.key, hp)
                 }
+                let handle : &fn(T) -> U = unsafe {
+                    ::cast::transmute(handler.handle)
+                };
+                let u = handle(t);
+                local_data::set(self.key, handler);
+                u
             }
         }
     }
 }
 
+/// A `Trap` is created when the `trap` method is invoked on a `Condition`, and
+/// it is used to actually bind a handler into the TLS slot reserved for this
+/// condition.
+///
+/// Normally this object is not dealt with directly, but rather it's directly
+/// used after being returned from `trap`
 struct Trap<'self, T, U> {
-    cond: &'self Condition<T, U>,
-    handler: @Handler<T, U>
+    priv cond: &'self Condition<T, U>,
+    priv handler: @Handler<T, U>
 }
 
 impl<'self, T, U> Trap<'self, T, U> {
+    /// Execute a block of code with this trap handler's exception handler
+    /// registered.
+    ///
+    /// # Example
+    ///
+    /// ~~~{.rust}
+    /// condition! { my_error: int -> int; }
+    ///
+    /// let result = do my_error::cond.trap(|error| error + 3).inside {
+    ///     my_error::cond.raise(4)
+    /// };
+    /// assert_eq!(result, 7);
+    /// ~~~
     pub fn inside<V>(&self, inner: &'self fn() -> V) -> V {
         let _g = Guard { cond: self.cond };
         debug!("Trap: pushing handler to TLS");
@@ -81,8 +189,9 @@ impl<'self, T, U> Trap<'self, T, U> {
     }
 }
 
+#[doc(hidden)]
 struct Guard<'self, T, U> {
-    cond: &'self Condition<T, U>
+    priv cond: &'self Condition<T, U>
 }
 
 #[unsafe_destructor]
diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs
index cad9f14bda7..99a5ed4d698 100644
--- a/src/libstd/fmt/mod.rs
+++ b/src/libstd/fmt/mod.rs
@@ -10,17 +10,18 @@
 
 /*!
 
-# The Formatting Module
+The Formatting Module
 
-This module contains the runtime support for the `format!` syntax extension. This
-macro is implemented in the compiler to emit calls to this module in order to
-format arguments at runtime into strings and streams.
+This module contains the runtime support for the `format!` syntax extension.
+This macro is implemented in the compiler to emit calls to this module in order
+to format arguments at runtime into strings and streams.
 
 The functions contained in this module should not normally be used in everyday
-use cases of `format!`. The assumptions made by these functions are unsafe for all
-inputs, and the compiler performs a large amount of validation on the arguments
-to `format!` in order to ensure safety at runtime. While it is possible to call
-these functions directly, it is not recommended to do so in the general case.
+use cases of `format!`. The assumptions made by these functions are unsafe for
+all inputs, and the compiler performs a large amount of validation on the
+arguments to `format!` in order to ensure safety at runtime. While it is
+possible to call these functions directly, it is not recommended to do so in the
+general case.
 
 ## Usage
 
diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs
index 07d2aeac627..87fad9aae70 100644
--- a/src/libstd/iter.rs
+++ b/src/libstd/iter.rs
@@ -8,12 +8,59 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*! Composable external iterators
+/*!
 
-The `Iterator` trait defines an interface for objects which implement iteration as a state machine.
+Composable external iterators
 
-Algorithms like `zip` are provided as `Iterator` implementations which wrap other objects
-implementing the `Iterator` trait.
+# The `Iterator` trait
+
+This module defines Rust's core iteration trait. The `Iterator` trait has one
+un-implemented method, `next`. All other methods are derived through default
+methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`.
+
+The goal of this module is to unify iteration across all containers in Rust.
+An iterator can be considered as a state machine which is used to track which
+element will be yielded next.
+
+There are various extensions also defined in this module to assist with various
+types of iteration, such as the `DoubleEndedIterator` for iterating in reverse,
+the `FromIterator` trait for creating a container from an iterator, and much
+more.
+
+## Rust's `for` loop
+
+The special syntax used by rust's `for` loop is based around the `Iterator`
+trait defined in this module. For loops can be viewed as a syntactical expansion
+into a `loop`, for example, the `for` loop in this example is essentially
+translated to the `loop` below.
+
+~~~{.rust}
+let values = ~[1, 2, 3];
+
+// "Syntactical sugar" taking advantage of an iterator
+for &x in values.iter() {
+    println!("{}", x);
+}
+
+// Rough translation of the iteration without a `for` iterator.
+let mut it = values.iter();
+loop {
+    match it.next() {
+        Some(&x) => {
+            println!("{}", x);
+        }
+        None => { break }
+    }
+}
+~~~
+
+This `for` loop syntax can be applied to any iterator over any type.
+
+## Iteration protocol and more
+
+More detailed information about iterators can be found in the [container
+tutorial](http://static.rust-lang.org/doc/master/tutorial-container.html) with
+the rest of the rust manuals.
 
 */
 
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index 93cac8797bb..a7391b76de1 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -8,12 +8,86 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! String manipulation
-//!
-//! Strings are a packed UTF-8 representation of text, stored as
-//! buffers of u8 bytes. The buffer is not null terminated.
-//! Strings should be indexed in bytes, for efficiency, but UTF-8 unsafe
-//! operations should be avoided.
+/*!
+
+String manipulation
+
+# Basic Usage
+
+Rust's string type is one of the core primitive types of the language. While
+represented by the name `str`, the name `str` is not actually a valid type in
+Rust. Each string must also be decorated with how its ownership. This means that
+there are three common kinds of strings in rust:
+
+* `~str` - This is an owned string. This type obeys all of the normal semantics
+           of the `~T` types, meaning that it has one, and only one, owner. This
+           type cannot be implicitly copied, and is moved out of when passed to
+           other functions.
+
+* `@str` - This is a managed string. Similarly to `@T`, this type can be
+           implicitly copied, and each implicit copy will increment the
+           reference count to the string. This means that there is not "true
+           owner" of the string, and the string will be deallocated when the
+           reference count reaches 0.
+
+* `&str` - Finally, this is the borrowed string type. This type of string can
+           only be created from one of the other two kinds of strings. As the
+           name "borrowed" implies, this type of string is owned elsewhere, and
+           this string cannot be moved out of.
+
+As an example, here's a few different kinds of strings.
+
+~~~{.rust}
+let owned_string = ~"I am an owned string";
+let managed_string = @"This string is garbage-collected";
+let borrowed_string1 = "This string is borrowed with the 'static lifetime";
+let borrowed_string2: &str = owned_string;   // owned strings can be borrowed
+let borrowed_string3: &str = managed_string; // managed strings can also be borrowed
+~~~
+
+From the example above, you can see that rust has 3 different kinds of string
+literals. The owned/managed literals correspond to the owned/managed string
+types, but the "borrowed literal" is actually more akin to C's concept of a
+static string.
+
+When a string is declared without a `~` or `@` sigil, then the string is
+allocated statically in the rodata of the executable/library. The string then
+has the type `&'static str` meaning that the string is valid for the `'static`
+lifetime, otherwise known as the lifetime of the entire program. As can be
+inferred from the type, these static strings are not mutable.
+
+# Mutability
+
+Many languages have immutable strings by default, and rust has a particular
+flavor on this idea. As with the rest of Rust types, strings are immutable by
+default. If a string is declared as `mut`, however, it may be mutated. This
+works the same way as the rest of Rust's type system in the sense that if
+there's a mutable reference to a string, there may only be one mutable reference
+to that string. With these guarantees, strings can easily transition between
+being mutable/immutable with the same benefits of having mutable strings in
+other languages.
+
+~~~{.rust}
+let mut buf = ~"testing";
+buf.push_char(' ');
+buf.push_str("123");
+assert_eq!(buf, ~"testing 123");
+~~~
+
+# Representation
+
+Rust's string type, `str`, is a sequence of unicode codepoints encoded as a
+stream of UTF-8 bytes. All safely-created strings are guaranteed to be validly
+encoded UTF-8 sequences. Additionally, strings are not guaranteed to be
+null-terminated (the null byte is a valid unicode codepoint).
+
+The actual representation of strings have direct mappings to vectors:
+
+* `~str` is the same as `~[u8]`
+* `&str` is the same as `&[u8]`
+* `@str` is the same as `@[u8]`
+
+*/
 
 use at_vec;
 use cast;
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 9fc0eaf72b1..3cdee0eb19a 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -10,6 +10,8 @@
 
 /*!
 
+Vector manipulation
+
 The `vec` module contains useful code to help work with vector values.
 Vectors are Rust's list type. Vectors contain zero or more values of
 homogeneous types: