Writing Documentation in Rust
Documentation is important. It’s also easy to do. Rust ships with tools to help developers create documentation for their libraries.
Code Comments
The main way that many developers write documentation is through source code comments. A single-line comment in Rust is started with //
. Many programming languages should already use this construct, so it’s probably not surprising to you. Equally unsurprising, multi-line comments start with /*
and end with */
. Many Rustaceans (that’s what Rust developers call themselves) prefer single-line comments. Do whatever you want, it’s fun to argue about inconsequential things after the fact. I use code comments to document code for myself and my co-workers. I use code comments for explaining something to whoever is looking at the code after me. Mainly code comments are for walking through a design decision or piece of logic that might not be clear at a casual glance. In flaker
, code comments are used to walk through the construct_id
function. With the code removed, it reads like:```
fn construct_id(&mut self) -> BigUint {
// Create a new vec of bytes
// push the counter into bytes
// next 6 bytes are the worker id
// fill the rest of the buffer with the current time, as bytes
// create a BigUint from the buffer
}
[](#document-comments)Document Comments
---------------------------------------
Document comments make it easy to document as you write code. This also makes it easier to keep your documentation up to date as you're modifying code. It is, after all, right next to the code you're changing. Just like code comments, there are two ways to write document comments for functions and methods. A single-line document comment looks like `///`. A multi-line document comment starts with `/**` on the first line, all by itself, and ends with `*/`. These are referred to as outer comments - outer line doc comments and outer block doc comments, if you want to get specific about it. We put the comments outside of the code that we're documenting. Pulling from my `flaker` library again:```
/// Returns a new Flaker based on the specified identifier
///
/// # Arguments
///
/// \* \`identifier\` - A 6 byte vec that provides some arbitrary identification.
///
/// # Remarks
///
/// This is a convenience function that converts the \`identifier\` \`vec\` into
/// a 6 byte array. Where possible, prefer the array and use \`new\`.
///
/// \*Note\*: This also assumes the \`flaker\` is being created on a little endian
/// CPU.
pub fn new\_from\_identifier(identifier: Vec) -> Flaker {
// magic
}
```We can use Markdown in our documentation comments! That's exciting. Now we can create good looking documentation that has structure. We'll see more about what this looks like in a little bit. There are a few conventions to use while documenting your code. These are `# Examples`, `# Panics`, `# Errors`, and `# Safety`. You can read more about the documentation conventions in [Documentation - Special Sections](https://doc.rust-lang.org/book/documentation.html#special-sections) and in [RFC 505](https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md).
[](#module-comments)Module Comments
-----------------------------------
We can also use documentation comments to write docs for our modules. These use what's called _inner doc comments_. An inner line doc comment looks like `//!` - note the bang. An inner block doc comment starts with `/*!` and ends with, you guessed it, `*/`. These are called inner doc comments because they go _inside_ the thing being documented. Outer doc comments go outside the thing being documented. Sadly, `flaker` doesn't have any module documentation. If it did, though, it would look like:```
//! This is the documentation for \`flaker\`
//!
//! # Examples
```This documentation will get generated later when we run `cargo doc`, which I promise we'll talk about in a second.
[](#documentation-tests)Documentation Tests
-------------------------------------------
It's possible to add code samples to a documentation comment using three backticks:```
//! \`\`\`
//! assert\_eq!(4, 2 + 2);
//! \`\`\`
```When we run `cargo test` - this code will be executed with all of our tests. But we'll still see the code when we generate documentation. This also works for function and method level documentation - just replace the `//!` with `///`. Just remember, your documentation tests will only be run if your crate is a library, not if it's an application.
[](#building-documentation)Building Documentation
-------------------------------------------------
Building documentation is relatively simple - you can execute `cargo doc` to build your documentation. This command will build documentation for your library and _all_ of its dependencies. That may not be desirable (it's probably not). If you only want to build the documentation for your own library, you can execute: `cargo doc --no-deps`. Using `--no-deps` will only build documentation for your code, not for any third party dependencies. You can even add a `--open` flag to open the newly built documentation in your web browser. It should look something like this: [![2016-05-03_12-00-10](/img/2016/05/2016-05-03_12-00-10-300x176.png)](/img/2016/05/2016-05-03_12-00-10.png) If I click through to the `Flaker` struct itself, we can see the documentation that we wrote! That's exciting. \[caption id="attachment\_1045" align="aligncenter" width="300"\][![Auto-generated documentation for the flaker struct.](/img/2016/05/2016-05-03_12-06-18-1-300x276.png)](/img/2016/05/2016-05-03_12-06-18-1.png) Auto-generated documentation for the flaker struct.\[/caption\] Writing docs should always be this easy. Right now, `cargo doc` won't put your documentation anywhere apart from the local file system. Many developers [use tools to publish documentation](http://www.steveklabnik.com/automatically_update_github_pages_with_travis_example/) to a GitHub static site.
[](#documentation-for-everyone)Documentation for Everyone!
----------------------------------------------------------
At this point, we know enough to write documentation for our methods and functions using doc comments - `///`. We can also write module level documentation with doc comments - `//!`. We can even format our documentation using markdown and its many features. And, finally, we can even include tests in our documentation. How's that for a documentation feature? There are a few more tricks available to you with Rust's documentation (like using external Markdown files), you can learn more in the [documentation chapter](https://doc.rust-lang.org/book/documentation.html) of the Rust Book.