Various restructuring

This commit is contained in:
Brian Anderson 2017-04-29 19:51:16 -07:00
parent 085cb40f67
commit 7bd8dd1062
26 changed files with 326 additions and 204 deletions

1
.gitignore vendored
View file

@ -1,5 +1,4 @@
target
*~
book/
*.swp

View file

@ -25,18 +25,47 @@ TODO: Fixing bugs
TODO: Pull requests
## Crates
TODO: How to add new crates to project
All crates used by the cookbook are listed in Cargo.toml. If you are
adding a new crate, first add it there.
## Tests
TODO: Write about writing tests
All examples are tested using [`skeptic`]. Run them with `cargo test`.
[`skeptic`]: https://github.com/brson/rust-skeptic
## Style
https://aturon.github.io
### Git Commit Messages
https://chris.beams.io/posts/git-commit/
TODO: Possibly take relevant parts from this post or write our own
### Snippet Style
TODO: Talk about writing good idiomatic code
TODO: Maybe provide a template?
Snippets are intended to be read by complete beginners, and copied
into projects for experimentation. They should follow best practices.
Snippets should have a simple single-sentence description
that describes something a typical Rust user typically wants to do.
The snippet should have minimal code that doesn't directly support the
description of the snippet. Keep extra functions and types to a
minimum.
Follow the template in [src/error_handling_note.md]. Examples always
set up error handling correctly and propagate errors with `?` (not
`try!`).
Don't use glob imports, even for preludes.
Sort imports.
Describe the code in prose, not in comments. Things that should be
described include any traits imported and their methods used. Think
about what information here supports the use case and might not be
obvious to someone new. Say the minimum possible about aspects that
don't directly support the use case. See [basics.md] for examples.
Hyperlink all references to APIs, and style them as `code`.

View file

@ -18,8 +18,6 @@ function main() {
elif [ $(program_installed mdbook) == 0 ]; then
echo "Please install mdbook: cargo install mdbook."
else
echo "Copying CONTRIBUTING.md to src/pages/contributing.md"
cp CONTRIBUTING.md src/pages/contributing.md
echo "Building site to book/"
mdbook build
echo "Copying assets/* to book/"

View file

@ -3,7 +3,7 @@ extern crate skeptic;
use std::fs;
fn main() {
let paths = fs::read_dir("./src/pages/").unwrap()
let paths = fs::read_dir("./src/").unwrap()
// convert paths to Strings
.map(|p| p.unwrap().path().to_str().unwrap().to_string())
// only compile markdown files

View file

@ -1,22 +1,8 @@
# Summary
[Table of Contents](pages/table_of_contents.md)
[A Note About Error Handling](pages/error_handling_note.md)
[Table of Contents](intro.md)
[A Note About Error Handling](error_handling_note.md)
- [Math](pages/math.md)
- [rand](pages/rand.md)
- [petgraph](pages/petgraph.md)
- [crossbeam](pages/crossbeam.md)
- [Algorithms](pages/algorithms.md)
- [IO](pages/IO.md)
- [File IO](pages/file_io.md)
- [Command Line Parsing](pages/cli_parsing.md)
- [Serialization](pages/serialization.md)
- [Byteorder](pages/byteorder.md)
- [JSON](pages/json.md)
- [TOML](pages/toml.md)
- [Networking](pages/networking.md)
- [Concurrency](pages/concurrency.md)
- [Rayon](pages/rayon.md)
[Contributing](pages/contributing.md)
- [Basics](basics.md)
- [Concurrency]
- [Application development]

148
src/basics.md Normal file
View file

@ -0,0 +1,148 @@
# Basics
| Recipe | Crates | Categories |
|--------|--------|------------|
| [Read lines of strings from a file][ex-std-read-lines] | [![std-badge]][std] | [![cat-file-io-badge]][cat-file-io] |
| [Read and write integers in little-endian byte order][ex-byteorder-le] | [![byteorder-badge]][byteorder] | [![cat-serialization-badge]][cat-serialization] |
| [Generate random floating point numbers][ex-rand-float] | [![rand-badge]][rand] | [![cat-math-badge]][cat-math] |
| [Generate random values on a custom type][ex-rand-custom] | [![rand-badge]][rand] | [![cat-math-badge]][cat-math] |
| [Construct a graph of objects][ex-petgraph-basic] | [![petgraph-badge]][petgraph] | [![cat-math-badge]][cat-math] |
<a name="ex-std-read-lines"/>
## Read lines of strings from a file
[![std-badge]][std] [![cat-file-io-badge]][cat-file-io]
Writes a three-line message to a file, then reads it back a line at a
time with the [`Lines`] iterator created by
[`BufRead::lines`]. [`BufRead`] is a trait, and the most common way to
get one is from a [`BufReader`], which is constructed from some type
that implements [`Write`], here a [`File`]. The [`File`] is opened
for writing with [`File::create`], and reading with [`File::open`].
```rust
use std::fs::File;
use std::io::{self, Write, BufReader, BufRead};
fn run() -> io::Result<()> {
write!(File::create("lines.txt")?, "Rust\n💖\nFun")?;
let file = File::open("lines.txt")?;
let file = BufReader::new(file);
for line in file.lines() {
println!("{}", line?);
}
Ok(())
}
fn main() { run().unwrap() }
```
<a name="ex-byteorder-le"/>
## Read and write integers in little-endian byte order
[![byteorder-badge]][byteorder] [![cat-serialization-badge]][cat-serialization]
```rust
extern crate byteorder;
use std::io::Cursor;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
#[derive(Default, Eq, PartialEq, Debug)]
struct Payload {
kind: u8,
value: u16,
}
fn run() -> Result<()> {
let original_payload = Payload::default();
let encoded_buf = encode(&original_payload)?;
let decoded_payload = decode(&encoded_buf)?;
assert_eq!(original_payload, decoded_payload);
Ok(())
}
fn encode(payload: &Payload) -> Result<Vec<u8>> {
let mut wtr = vec![];
wtr.write_u8(payload.kind)?;
wtr.write_u16::<LittleEndian>(payload.value)?;
Ok(wtr)
}
fn decode(buf: &[u8]) -> Result<Payload> {
let mut rdr = Cursor::new(buf);
Ok(Payload {
kind: rdr.read_u8()?,
value: rdr.read_u16::<LittleEndian>()?,
})
}
#[macro_use]
extern crate error_chain;
error_chain! {
foreign_links {
Io(::std::io::Error);
}
}
fn main() { run().unwrap() }
```
<a name="ex-rand-float"/>
## Generate random floating point numbers
[![rand-badge]][rand] [![cat-math-badge]][cat-math]
<a name="ex-rand-custom"/>
## Generate random values on a custom type
[![rand-badge]][rand] [![cat-math-badge]][cat-math]
<a name="ex-petgraph-basic"/>
## Construct a graph of objects
[![petgraph-badge]][petgraph] [![cat-math-badge]][cat-math]
<!- Categories -->
[cat-file-io-badge]: https://img.shields.io/badge/-file_io-orange.svg
[cat-file-io]: https://crates.io
[cat-math-badge]: https://img.shields.io/badge/-rand-orange.svg
[cat-math]: https://crates.io
[cat-serialization-badge]: https://img.shields.io/badge/-serialization-orange.svg
[cat-serialization]: https://crates.io
<!-- Crates -->
[byteorder-badge]: https://img.shields.io/badge/byteorder-1.0.0-blue.svg
[byteorder]: https://docs.rs/byteorder/1.0.0/byteorder/
[petgraph-badge]: https://img.shields.io/badge/petgraph-0.4.3-blue.svg
[petgraph]: https://docs.rs/petgraph/0.4.3/petgraph/
[std-badge]: https://img.shields.io/badge/std-1.17.0-blue.svg
[std]: https://doc.rust-lang.org/std
[rand-badge]: https://img.shields.io/badge/rand-0.3.15-blue.svg
[rand]: https://docs.rs/rand/0.3.15/rand/
<!-- Examples -->
[ex-byteorder-le]: basics.html#ex-byteorder-le
[ex-petgraph-basic]: basics.html#ex-petgraph-basic
[ex-rand-custom]: basics.html#ex-rand-custom
[ex-rand-float]: basics.html#ex-rand-float
[ex-std-read-lines]: basics.html#ex-std-read-lines
<!-- API links -->
[`BufRead::lines`]: https://doc.rust-lang.org/std/io/trait.BufRead.html#method.lines
[`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
[`BufReader`]: https://doc.rust-lang.org/std/io/struct.BufReader.html
[`File`]: https://doc.rust-lang.org/std/fs/struct.File.html
[`File::create`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.create
[`File::open`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.open
[`Lines`]: https://doc.rust-lang.org/std/io/struct.Lines.html
[`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html

View file

@ -1,6 +1,8 @@
# Parallel Prime Calculations
[![crossbeam-badge]][crossbeam]
FIXME: This doesn't look like it's running in parallel
## Calculate primes upto a number
```rust

View file

@ -0,0 +1,92 @@
# A note about error handling
Error handling in Rust is robust when done correctly, but in today's
Rust it requires a fair bit of boilerplate. Because of this one often
sees Rust examples filled with `unwrap` calls instead of proper error
handling.
Since these recipes are intended to be reused as-is and encourage best
practices, they set up error handling correctly when there are
`Result` types involved.
The basic pattern we use is to have a `fn run() -> Result` that acts
like the "real" main function.
The code for this setup generally looks like:
```rust
use std::io::{self, Write};
fn run() -> io::Result<()> {
let ref mut stdout = io::stdout();
writeln!(stdout, "hello, world")?;
Ok(())
}
fn main() { run().unwrap() }
```
and when necessary to reduce boilerplate,
they use the [error-chain] crate.
```rust
extern crate byteorder;
use std::io::Cursor;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
#[derive(Default, Eq, PartialEq, Debug)]
struct Payload {
kind: u8,
value: u16,
}
fn run() -> Result<()> {
let original_payload = Payload::default();
let encoded_buf = encode(&original_payload)?;
let decoded_payload = decode(&encoded_buf)?;
assert_eq!(original_payload, decoded_payload);
Ok(())
}
fn encode(payload: &Payload) -> Result<Vec<u8>> {
let mut wtr = vec![];
wtr.write_u8(payload.kind)?;
wtr.write_u16::<LittleEndian>(payload.value)?;
Ok(wtr)
}
fn decode(buf: &[u8]) -> Result<Payload> {
let mut rdr = Cursor::new(buf);
Ok(Payload {
kind: rdr.read_u8()?,
value: rdr.read_u16::<LittleEndian>()?,
})
}
#[macro_use]
extern crate error_chain;
error_chain! {
foreign_links {
Io(::std::io::Error);
}
}
fn main() { run().unwrap() }
```
This is using the `error_chain!` macro to define a custom `Error`
and `Result` type, along with an automatic conversion from
the common `::std::io::Error` type. The automatic conversion
makes the `?` operator work .
For more background on error handling in Rust, read [this page of the
Rust book][error-docs] and [this blog post][error-blog].
<!-- Links-->
[error-docs]: https://doc.rust-lang.org/book/error-handling.html
[error-blog]: https://brson.github.io/2016/11/30/starting-with-error-chain

View file

@ -26,6 +26,7 @@ fn operate_on_file(myfile: &str, mystring: &str, count: i32) -> io::Result<()> {
// Read lines from file
for line in io::BufReader::new(&f).lines() {
// FIXME: bad unwrap
println!("{}", line.unwrap());
}
Ok(())

View file

@ -2,16 +2,24 @@
A practical guide to the Rust crate ecosystem.
## Recipes
### Foundations
### Basics
| Recipe | Crates | Categories |
|--------|--------|------------|
| [Read lines of strings from a file][ex-std-read-lines] | [![std-badge]][std] | [![cat-file-io-badge]][cat-file-io] |
| [Read and write integers in little-endian byte order][ex-byteorder-le] | [![byteorder-badge]][byteorder] | [![cat-serialization-badge]][cat-serialization] |
| [Generate random floating point numbers][ex-rand-float] | [![rand-badge]][rand] | [![cat-math-badge]][cat-math] |
| [Generate random values on a custom type][ex-rand-custom] | [![rand-badge]][rand] | [![cat-math-badge]][cat-math] |
| [Construct a graph of objects][ex-petgraph-basic] | [![petgraph-badge]][petgraph] | [![cat-math-badge]][cat-math] |
### Serialization
| Recipe | Crates | Categories |
|--------|--------|------------|
| [Serialize and deserialize unstructured JSON][ex-json-basic] | [![json-badge]][json] | [![cat-serialization-badge]][cat-serialization] |
| [Deserialize an unstructured TOML configuration file][ex-toml-basic] | [![toml-badge]][toml] | [![cat-serialization-badge]][cat-serialization] |
@ -21,16 +29,12 @@ A practical guide to the Rust crate ecosystem.
|--------|--------|------------|
| [Mutate the elements of an array in parallel][ex-rayon-iter-mut] | [![rayon-badge]][rayon] | [![cat-concurrency-badge]][cat-concurrency] |
### I/O
### Application development
| Recipe | Crates | Categories |
|--------|--------|------------|
| [Parse command line arguments][ex-clap-basic] | [![clap-badge]][clap] | [![cat-app-badge]][cat-app] |
## Contributing
If you'd like to make changes to the project, please see [this guide](pages/contributing.html).
@ -39,41 +43,60 @@ If you'd like to make changes to the project, please see [this guide](pages/cont
MIT/Apache-2.0
<!--
Links, in a few categories. Follow the existing structure.
Individual pages contain a subset of these exact links, depending on
the crates and categories of their examples.
Keep lines sorted.
-->
<!- Categories -->
[cat-serialization-badge]: https://img.shields.io/badge/-serialization-orange.svg
[cat-serialization]: https://crates.io
[cat-math-badge]: https://img.shields.io/badge/-rand-orange.svg
[cat-math]: https://crates.io
[cat-app-badge]: https://img.shields.io/badge/-app-orange.svg
[cat-app]: https://crates.io
[cat-concurrency-badge]: https://img.shields.io/badge/-concurrency-orange.svg
[cat-concurrency]: https://crates.io
[cat-file-io-badge]: https://img.shields.io/badge/-file_io-orange.svg
[cat-file-io]: https://crates.io
[cat-math-badge]: https://img.shields.io/badge/-rand-orange.svg
[cat-math]: https://crates.io
[cat-serialization-badge]: https://img.shields.io/badge/-serialization-orange.svg
[cat-serialization]: https://crates.io
<!-- Crates -->
[byteorder-badge]: https://img.shields.io/badge/byteorder-1.0.0-blue.svg
[byteorder]: https://docs.rs/byteorder/1.0.0/byteorder/
[clap-badge]: https://img.shields.io/badge/clap-2.22.2-blue.svg
[clap]: https://docs.rs/clap/2.22.0/rand/
[json-badge]: https://img.shields.io/badge/json-0.11.5-blue.svg
[json]: https://docs.rs/json/0.11.5/json/
[petgraph-badge]: https://img.shields.io/badge/petgraph-0.4.3-blue.svg
[petgraph]: https://docs.rs/petgraph/0.4.3/petgraph/
[rand-badge]: https://img.shields.io/badge/rand-0.3.15-blue.svg
[rand]: https://docs.rs/rand/0.3.15/rand/
[clap-badge]: https://img.shields.io/badge/clap-2.22.2-blue.svg
[clap]: https://docs.rs/clap/2.22.0/rand/
[rayon-badge]: https://img.shields.io/badge/rayon-0.6.0-blue.svg
[rayon]: https://docs.rs/rayon/0.6.0/rayon/
[json-badge]: https://img.shields.io/badge/json-0.11.5-blue.svg
[json]: https://docs.rs/json/0.11.5/json/
[std-badge]: https://img.shields.io/badge/std-1.17.0-blue.svg
[std]: https://doc.rust-lang.org/std
[toml-badge]: https://img.shields.io/badge/toml-0.3.0-blue.svg
[toml]: https://docs.rs/toml/0.3.0/toml/
<!-- Examples -->
[ex-byteorder-le]: todo
[ex-rand-float]: todo
[ex-rand-custom]: todo
[ex-petgraph-basic]: todo
[ex-byteorder-le]: basics.html#ex-byteorder-le
[ex-clap-basic]: todo
[ex-json-basic]: todo
[ex-toml-basic]: todo
[ex-petgraph-basic]: basics.html#ex-petgraph-basic
[ex-rand-custom]: basics.html#ex-rand-custom
[ex-rand-float]: basics.html#ex-rand-float
[ex-rayon-iter-mut]: todo
[ex-std-read-lines]: basics.html#ex-std-read-lines
[ex-toml-basic]: todo

View file

@ -1,3 +1,4 @@
fn main() {
println!("Hello, world!");
println!("This program does nothing.");
println!("See documentation at https://github.com/brson/rust-cookbook");
}

View file

View file

@ -1 +0,0 @@
# Algorithms

View file

@ -1,57 +0,0 @@
# Byteorder
[![byteorder-badge]][byteorder]
## Read and write integers in little-endian byte order
```rust
extern crate byteorder;
use std::io::Cursor;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
#[derive(Default, Eq, PartialEq, Debug)]
struct Payload {
kind: u8,
value: u16,
}
fn run() -> Result<()> {
let original_payload = Payload::default();
let encoded_buf = encode(&original_payload)?;
let decoded_payload = decode(&encoded_buf)?;
assert_eq!(original_payload, decoded_payload);
Ok(())
}
fn encode(payload: &Payload) -> Result<Vec<u8>> {
let mut wtr = vec![];
wtr.write_u8(payload.kind)?;
wtr.write_u16::<LittleEndian>(payload.value)?;
Ok(wtr)
}
fn decode(buf: &[u8]) -> Result<Payload> {
let mut rdr = Cursor::new(buf);
Ok(Payload {
kind: rdr.read_u8()?,
value: rdr.read_u16::<LittleEndian>()?,
})
}
#[macro_use]
extern crate error_chain;
mod errors {
error_chain! {
foreign_links {
Io(::std::io::Error);
}
}
}
use errors::*;
fn main() { run().unwrap() }
```
<!-- Links -->
[byteorder-badge]: https://img.shields.io/crates/v/rustc-serialize.svg?label=byteorder
[byteorder]: https://docs.rs/byteorder

View file

@ -1 +0,0 @@
# Concurrency

View file

@ -1,46 +0,0 @@
# Contributing to the Rust Cookbook
Have something useful to add to the Rust Cookbook? We'd love to have it!
This document contains information and guidelines that you should read before
contributing to the project. If you think something in this document should change,
feel free propose a change in a pull request.
## Table of Contents
* [Getting Started](#getting-started)
* [How to Contribute](#how-to-contribute)
* [Crates](#crates)
* [Tests](#tests)
* [Style](#style)
* [Git Commit Messages](#git-commit-messages)
* [Snippet Style](#snippet-style)
## Getting Started
TODO: Mention Trello and how to join (if we keep using it)
## How to Contribute
TODO: Reporting bugs
TODO: Project page suggestions
TODO: Fixing bugs
TODO: Pull requests
## Crates
All crates used by the cookbook are listed in Cargo.toml. If you are
adding a new crate, first add it there.
## Tests
All examples are tested using [`skeptic`]. Run them with `cargo test`.
[`skeptic`]: https://github.com/brson/rust-skeptic
## Style
### Git Commit Messages
https://chris.beams.io/posts/git-commit/
TODO: Possibly take relevant parts from this post or write our own
### Snippet Style
TODO: Talk about writing good idiomatic code
TODO: Maybe provide a template?

View file

@ -1,50 +0,0 @@
# A note about error handling
Error handling in Rust is robust when done correctly, but in today's
Rust it requires a fair bit of boilerplate. Because of this one often
sees Rust examples filled with `unwrap` calls instead of proper error
handling.
Since these recipes are intended to be reused as-is and encourage best
practices, they set up error handling correctly, and when necessary to
reduce boilerplate, they use the [error-chain] crate.
The code for this setup generally looks like:
```rust
#[macro_use]
extern crate error_chain;
mod errors {
error_chain! {
foreign_links {
Io(::std::io::Error);
}
}
}
use errors::*;
fn main() { run().unwrap() }
fn run() -> Result<()> {
use std::io::Write;
let ref mut stdout = ::std::io::stdout();
writeln!(stdout, "hello, world")?;
Ok(())
}
```
This is using the `error_chain!` macro to define a custom `Error`
and `Result` type, along with an automatic conversion from
the common `::std::io::Error` type. The automatic conversion
makes the `?` operator work
For more background on error handling in Rust, read [this page of the Rust book][error-docs] and [this blog post][error-blog].
<!-- Links-->
[error-docs]: https://doc.rust-lang.org/book/error-handling.html
[error-blog]: https://brson.github.io/2016/11/30/starting-with-error-chain

View file

@ -1 +0,0 @@
# Math

View file

@ -1 +0,0 @@
# Networking