Book Image

Practical System Programming for Rust Developers

By : Prabhu Eshwarla
Book Image

Practical System Programming for Rust Developers

By: Prabhu Eshwarla

Overview of this book

Modern programming languages such as Python, JavaScript, and Java have become increasingly accepted for application-level programming, but for systems programming, C and C++ are predominantly used due to the need for low-level control of system resources. Rust promises the best of both worlds: the type safety of Java, and the speed and expressiveness of C++, while also including memory safety without a garbage collector. This book is a comprehensive introduction if you’re new to Rust and systems programming and are looking to build reliable and efficient systems software without C or C++. The book takes a unique approach by starting each topic with Linux kernel concepts and APIs relevant to that topic. You’ll also explore how system resources can be controlled from Rust. As you progress, you’ll delve into advanced topics. You’ll cover network programming, focusing on aspects such as working with low-level network primitives and protocols in Rust, before going on to learn how to use and compile Rust with WebAssembly. Later chapters will take you through practical code examples and projects to help you build on your knowledge. By the end of this Rust programming book, you will be equipped with practical skills to write systems software tools, libraries, and utilities in Rust.
Table of Contents (17 chapters)
1
Section 1: Getting Started with System Programming in Rust
6
Section 2: Managing and Controlling System Resources in Rust
12
Section 3: Advanced Topics

Documenting your project

Rust ships with a tool called Rustdoc, which can generate documentation for Rust projects. Cargo has integration with Rustdoc, so you can use either tool to generate documentation.

To get an idea of what it means to have documentation generated for Rust projects, go to http://docs.rs.

This is a documentation repository for all the crates in crates.io. To see a sample of the generated documentation, select a crate and view the docs. For example, you can go to docs.rs/serde to see docs for the popular serialization/deserialization library in Rust.

To generate similar documentation for your Rust projects, it is important to think through what to document, and how to document it.

But what can you document? The following are some of the aspects of a crate that it would be useful to document:

  • An overall short description of what your Rust library does
  • A list of modules and public functions in the library
  • A list of other items, such as traits, macros, structs, enums, and typedefs, that a public user of the library needs to be familiar with to use various features
  • For binary crates, installation instructions and command-line parameters.
  • Examples that demonstrate to users how to use the crate
  • Optionally, design details for the crate

Now that we know what to document, we have to learn how to document it. There are two ways to document your crate:

  • Inline documentation comments within the crate
  • Separate markdown files

You can use either approach, and the rustdoc tool will convert them into HTML, CSS, and JavaScript code that can be viewed from a browser.

Writing inline documentation comments within crate

Rust has two types of comments: code comments (aimed at developers) and documentation comments (aimed at users of the library/crate).

Code comments are written using:

  • // for single-line comments and writing inline documentation comments within crate
  • /* */ for multi-line comments

Documentation comments are written using two styles:

The first style is to use three slashes /// for commenting on individual items that follow the comments. Markdown notation can be used to style the comments (for example, bold or italic). This is typically used for item-level documentation.

The second style is to use //!. This is used to add documentation for the item that contains these comments (as opposed to the first style, which is used to comment items that follow the comments). This is typically used for crate-level documentation.

In both cases, rustdoc extracts documentation from the crate's documentation comments.

Add the following comments to the integ-test-example project, in src/lib.rs:

//! This is a library that contains functions related to 
//! dealing with processes,  
//! and makes these tasks more convenient.  
use std::process;
/// This function gets the process ID of the current 
/// executable. It returns a non-zero  number  
pub fn get_process_id() -> u32 {
    process::id()
}

Run cargo doc –open to see the generated HTML documentation corresponding to the documentation comments.

Writing documentation in markdown files

Create a new folder, doc, under the crate root, and add a new file, itest.md, with the following markdown content:

# Docs for integ-test-example crate
  
This is a project to test `rustdoc`.
[Here is a link!](https://www.rust-lang.org)
// Function signature
pub fn get_process_id() -> u32 {}

This function returns the process ID of the currently running executable:

// Example
```rust
use integ_test_example;
fn get_id() -> i32 {
 let my_pid = get_process_id();
 println!("Process id for current process is: {}", my_pid);
}
```

Note that the preceding code example is only representational.

Unfortunately, cargo does not directly support generating HTML from standalone markdown files (at the time of this writing), so we have to use rustdoc as follows:

rustdoc doc/itest.md

You will find the generated HTML document itest.html in the same folder. View it in your browser.

Running documentation tests

If there are any code examples written as part of the documentation, rustdoc can execute the code examples as tests.

Let's write a code example for our library. Open src/lib.rs and add the following code example to existing code:

//! Integration-test-example crate
//!
//! This is a library that contains functions related to 
//! dealing with processes
//! , and makes these tasks more convenient.
use std::process;
/// This function gets the process id of the current 
/// executable. It returns a non-zero number
/// ```
/// fn get_id() {
/// let x = integ_test_example::get_process_id();
/// println!("{}",x);
/// }
/// ```
pub fn get_process_id() -> u32 {
    process::id()
}

If you run cargo test --doc, it will run this example code and provide the status of the execution.

Alternatively, running cargo test will run all the test cases from the tests directory (except those that are marked as ignored), and then run the documentation tests (that is, code samples provided as part of the documentation).