Skip to content

Commit 6c7aa99

Browse files
committed
update original
1 parent 41ba5ed commit 6c7aa99

22 files changed

Lines changed: 716 additions & 3 deletions

rust-cookbook/Cargo.toml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,37 @@ exclude = ["crates/web_leptos", "crates/web_leptos_hydrate"]
55
[workspace.package]
66
edition = "2024"
77
version = "1.1.0"
8-
authors = ["Brian Anderson <banderson@mozilla.com>", "Andrew Gauger <andygauge@gmail.com>"]
8+
authors = [
9+
"Brian Anderson <banderson@mozilla.com>",
10+
"David Tolnay <dtolnay@gmail.com>",
11+
"Michał Budzyński <budziq@gmail.com>",
12+
"Brad Anderson <brad.anderson1995@gmail.com>",
13+
"David Harris <dhharris9@gmail.com>",
14+
]
915
license = "MIT OR Apache-2.0"
1016
publish = false
1117

18+
[workspace.metadata]
19+
curator = "Andrew Gauger <andygauge@gmail.com>"
20+
1221
[package]
1322
name = "rust-cookbook"
1423
version = "1.1.0"
15-
authors = ["Brian Anderson <banderson@mozilla.com>", "Andrew Gauger <andygauge@gmail.com>"]
24+
authors = [
25+
"Brian Anderson <banderson@mozilla.com>",
26+
"David Tolnay <dtolnay@gmail.com>",
27+
"Michał Budzyński <budziq@gmail.com>",
28+
"Brad Anderson <brad.anderson1995@gmail.com>",
29+
"David Harris <dhharris9@gmail.com>",
30+
]
1631
edition = "2018"
1732
license = "MIT OR Apache-2.0"
1833
publish = false
1934
build = "build.rs"
2035

36+
[package.metadata]
37+
curator = "Andrew Gauger <andygauge@gmail.com>"
38+
2139
[features]
2240
default = []
2341

rust-cookbook/ci/dictionary.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,13 @@ appender
2121
Appender
2222
applicationx
2323
args
24+
AsRef
25+
AsyncRead
26+
AsyncWrite
27+
asyncread
28+
asyncwrite
2429
ascii
2530
ashley
26-
AsRef
2731
async
2832
attr
2933
auth

rust-cookbook/src/SUMMARY.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
- [Algorithms](algorithms.md)
77
- [Generate Random Values](algorithms/randomness.md)
88
- [Sort a Vector](algorithms/sorting.md)
9+
- [Asynchronous](asynchronous.md)
10+
- [Introduction](asynchronous/intro.md)
11+
- [Runtime](asynchronous/rt.md)
12+
- [File IO](asynchronous/fs.md)
13+
- [Timeouts](asynchronous/timeout.md)
14+
- [Message Passing](asynchronous/channel.md)
15+
- [First to Complete](asynchronous/ftc.md)
16+
- [Structured Concurrency](asynchronous/join.md)
917
- [Command Line](cli.md)
1018
- [Argument Parsing](cli/arguments.md)
1119
- [ANSI Terminal](cli/ansi_terminal.md)

rust-cookbook/src/asynchronous.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Asynchronous
2+
3+
4+
| Recipe | Crates | Categories|
5+
|-------|-------|----------|
6+
| [Intro][ex-async-intro] |-| [![cat-asynchronous-badge]][cat-asynchronous] |
7+
| [Tokio Runtime][ex-tokio-macro] |[![tokio-badge]][tokio]| [![cat-asynchronous-badge]][cat-asynchronous] |
8+
| [Tokio Runtime Builder][ex-tokio-builder] |[![tokio-badge]][tokio] [![std-badge]][std]| [![cat-asynchronous-badge]][cat-asynchronous] |
9+
| [Create Files Operations][ex-fs-create] |[![tokio-badge]][tokio][![std-badge]][std]| [![cat-asynchronous-badge]][cat-asynchronous] |
10+
| [Read Files Operations][ex-fs-read] |[![tokio-badge]][tokio][![std-badge]][std]| [![cat-asynchronous-badge]][cat-asynchronous] |
11+
| [Write Files Operations][ex-fs-write] |[![tokio-badge]][tokio][![std-badge]][std]| [![cat-asynchronous-badge]][cat-asynchronous] |
12+
| [Remove Files Operations][ex-fs-remove] |[![tokio-badge]][tokio][![std-badge]][std]| [![cat-asynchronous-badge]][cat-asynchronous] |
13+
| [AsyncRead and AsyncWrite traits][ex-fs-rw-traits] |[![tokio-badge]][tokio][![std-badge]][std]| [![cat-asynchronous-badge]][cat-asynchronous] |
14+
| [Bounded channels][ex-channel-bounded] |[![tokio-badge]][tokio][![std-badge]][std]| [![cat-asynchronous-badge]][cat-asynchronous] |
15+
| [Unbounded channels][ex-channel-unbounded] |[![tokio-badge]][tokio][![std-badge]][std]| [![cat-asynchronous-badge]][cat-asynchronous] |
16+
| [First-to-complete][ex-ftc] |[![tokio-badge]][tokio]| [![cat-asynchronous-badge]][cat-asynchronous] |
17+
| [Task Timeouts][ex-timeout] |[![tokio-badge]][tokio]| [![cat-asynchronous-badge]][cat-asynchronous] |
18+
| [Join Sets][ex-join-set] |[![tokio-badge]][tokio]| [![cat-asynchronous-badge]][cat-asynchronous] |
19+
20+
[ex-async-intro]: asynchronous/intro.html
21+
[ex-tokio-macro]: asynchronous/rt.html#tokio-runtime
22+
[ex-tokio-builder]: asynchronous/rt.html#builder-approach
23+
[ex-fs]: asynchronous/fs.html
24+
[ex-fs-create]: asynchronous/fs.html#create-files-and-directories
25+
[ex-fs-read]: asynchronous/fs.html#read-files
26+
[ex-fs-write]: asynchronous/fs.html#write-files
27+
[ex-fs-remove]: asynchronous/fs.html#remove-files-and-directories
28+
[ex-fs-rw-traits]: asynchronous/fs.html#asyncread-and-asyncwrite
29+
[ex-channel]: asynchronous/channel.html
30+
[ex-channel-bounded]: asynchronous/channel.html#bounded-channels
31+
[ex-channel-unbounded]: asynchronous/channel.html#unbounded-channels
32+
[ex-ftc]: asynchronous/ftc.html
33+
[ex-timeout]: asynchronous/timeout.html
34+
[ex-join-set]: asynchronous/join.html#join-sets
35+
36+
{{#include links.md}}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Message Passing
2+
3+
When your program has multiple tasks running at the same time, they sometimes need to talk to each
4+
other. Channels are how you do that, one task sends a message, another receives it.
5+
Think of it like a pipe: you put something in one end, and it comes out the other.
6+
7+
{{#include channel/bounded.md}}
8+
{{#include channel/unbounded.md}}
9+
10+
{{#include ../links.md}}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
## Bounded Channels
2+
3+
[![tokio-badge]][tokio] [![std-badge]][std]
4+
5+
A [`bounded channel`] has a limit on how many messages it can hold at once. If the channel is full,
6+
the sender has to wait until there is room before it can send another message.
7+
8+
Think of it like a physical mailbox. It can only hold a fixed number of letters. If it's full,
9+
the postman has to wait until someone clears it out before dropping in another letter.
10+
11+
In this example, two book stores send books through a channel with a capacity of 5.
12+
A shelf collects whatever comes through.
13+
14+
```rust,edition2018
15+
use std::io;
16+
use tokio::sync::mpsc::channel;
17+
18+
struct Book {
19+
title: &'static str,
20+
}
21+
22+
impl Book {
23+
fn new(title: &'static str) -> Self {
24+
Self { title }
25+
}
26+
}
27+
28+
#[tokio::main]
29+
async fn main() -> io::Result<()> {
30+
let (book_sender, mut book_receiver) = channel(5);
31+
32+
// Each store gets its own copy of the sender.
33+
let store_one_book_sender = book_sender.clone();
34+
let book_store_one = tokio::task::spawn(async move {
35+
if let Err(err) = store_one_book_sender
36+
.send(Book::new("Shawshank Redemption"))
37+
.await
38+
{
39+
eprintln!("Failed to send book from store one: {}", err);
40+
}
41+
});
42+
43+
let book_store_two = tokio::task::spawn(async move {
44+
if let Err(err) = book_sender.send(Book::new("Secret Recipe")).await {
45+
eprintln!("Failed to send book from store two: {}", err);
46+
}
47+
});
48+
49+
let mut shelf: Vec<Book> = Vec::new();
50+
// Collect every book that arrives until both stores are done sending.
51+
while let Some(new_book) = book_receiver.recv().await {
52+
shelf.push(new_book);
53+
}
54+
55+
book_store_one.await?;
56+
book_store_two.await?;
57+
58+
for book in &shelf {
59+
println!("Title: {}", book.title);
60+
}
61+
62+
Ok(())
63+
}
64+
```
65+
66+
> Add `tokio` to `Cargo.toml` with the [`macros`] and [`sync`] features enabled.
67+
> ```toml
68+
> [dependencies]
69+
> tokio = { version = "*", features = ["macros", "sync"] }
70+
> ```
71+
72+
[`bounded channel`]: https://docs.rs/tokio/*/tokio/sync/mpsc/fn.channel.html
73+
[`macros`]: https://docs.rs/crate/tokio/*/features#macros
74+
[`sync`]: https://docs.rs/crate/tokio/*/features#sync
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
## Unbounded Channels
2+
3+
[![tokio-badge]][tokio] [![std-badge]][std]
4+
5+
An [`unbounded channel`] has no limit on how many messages it can hold. The sender never has to wait,
6+
it can always drop a message in, no matter how many are already sitting there.
7+
8+
Think of it like a digital inbox. It just keeps growing as new messages arrive. There's no cap,
9+
but if messages pile up faster than they're being read, your program will use more and more memory.
10+
Sending on an unbounded channel will always succeed as long as the receiving end is still open.
11+
If the receiver is slow, messages simply queue up and wait.
12+
13+
In this example, two people send messages through a channel. An inbox collects whatever comes
14+
through.
15+
16+
```rust,edition2018
17+
use std::io;
18+
use tokio::sync::mpsc::unbounded_channel;
19+
20+
struct Message {
21+
from: &'static str,
22+
text: &'static str,
23+
}
24+
25+
impl Message {
26+
fn new(from: &'static str, text: &'static str) -> Self {
27+
Self { from, text }
28+
}
29+
}
30+
31+
#[tokio::main]
32+
async fn main() -> io::Result<()> {
33+
let (message_sender, mut message_receiver) = unbounded_channel();
34+
35+
let alice_message_sender = message_sender.clone();
36+
let person_one = tokio::task::spawn(async move {
37+
if let Err(err) = alice_message_sender.send(Message::new("Alice", "Meeting postponed")) {
38+
eprintln!("Failed to send message from Alice: {}", err);
39+
}
40+
});
41+
42+
let person_two = tokio::task::spawn(async move {
43+
if let Err(err) = message_sender.send(Message::new("Bob", "Secret Leaked")) {
44+
eprintln!("Failed to send message from Bob: {}", err);
45+
}
46+
});
47+
48+
let mut inbox: Vec<Message> = Vec::new();
49+
while let Some(new_book) = message_receiver.recv().await {
50+
inbox.push(new_book);
51+
}
52+
53+
person_one.await?;
54+
person_two.await?;
55+
56+
for msg in &inbox {
57+
println!("{} says: {}", msg.from, msg.text);
58+
}
59+
60+
Ok(())
61+
}
62+
```
63+
64+
> Add `tokio` to `Cargo.toml` with the [`macros`] and [`sync`] features enabled.
65+
> ```toml
66+
> [dependencies]
67+
> tokio = { version = "*", features = ["macros", "sync"] }
68+
> ```
69+
70+
[`macros`]: https://docs.rs/crate/tokio/*/features#macros
71+
[`sync`]: https://docs.rs/crate/tokio/*/features#sync
72+
[`unbounded channel`]: https://docs.rs/tokio/*/tokio/sync/mpsc/fn.unbounded_channel.html
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# File IO
2+
3+
{{#include fs/create.md}}
4+
{{#include fs/read.md}}
5+
{{#include fs/write.md}}
6+
{{#include fs/remove.md}}
7+
{{#include fs/rw_traits.md}}
8+
9+
{{#include ../links.md}}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## Create Files and Directories
2+
3+
[![tokio-badge]][tokio] [![std-badge]][std]
4+
5+
Creating files and directories on disk takes time. Tokio provides non-blocking versions of these
6+
operations so your program does not have to stop and wait while the work is done.
7+
8+
[`File::create`] creates a new file. If the file already exists, it is overwritten.
9+
[`create_dir`] creates a single directory. If it already exists, it fails.
10+
[`create_dir_all`] creates a directory and any missing parent directories along the path.
11+
12+
```rust,edition2018,no_run
13+
use std::io;
14+
use tokio::fs::File;
15+
16+
#[tokio::main]
17+
async fn main() -> io::Result<()> {
18+
// create a file
19+
File::create("data.txt").await?;
20+
21+
// create a single directory
22+
tokio::fs::create_dir("my_dir").await?;
23+
24+
// create directory and missing parents
25+
tokio::fs::create_dir_all("my_dir/sub_dir/inner").await?;
26+
27+
Ok(())
28+
}
29+
```
30+
31+
32+
> Add `tokio` to `Cargo.toml` with the [`macros`] and [`fs`] features enabled.
33+
> ```toml
34+
> [dependencies]
35+
> tokio = { version = "*", features = ["macros", "fs"] }
36+
> ```
37+
38+
[`File::create`]: https://docs.rs/tokio/*/tokio/fs/struct.File.html#method.create
39+
[`create_dir_all`]: https://docs.rs/tokio/*/tokio/fs/fn.create_dir_all.html
40+
[`create_dir`]: https://docs.rs/tokio/*/tokio/fs/fn.create_dir.html
41+
[`fs`]: https://docs.rs/crate/tokio/*/features#fs
42+
[`macros`]: https://docs.rs/crate/tokio/*/features#macros
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## Read files
2+
3+
[![tokio-badge]][tokio] [![std-badge]][std]
4+
5+
Reading a file from disk takes time. Tokio provides non-blocking versions of file reads so your
6+
program can keep doing other work while waiting for the data to come back.
7+
8+
- [`read`] loads the file into raw bytes. Useful when you need to process the data directly.
9+
- [`read_to_string`] loads the file into plain text. Useful when you know the file contains readable
10+
characters.
11+
12+
```rust,edition2018,no_run
13+
use std::io;
14+
15+
fn process_data(data: &[u8]) {
16+
println!("Data Length: {}", data.len());
17+
}
18+
19+
#[tokio::main]
20+
async fn main() -> io::Result<()> {
21+
// read to a Vec<u8>
22+
let content = tokio::fs::read("data.txt").await?;
23+
process_data(&content);
24+
25+
// read to a String
26+
let str_content = tokio::fs::read_to_string("data.txt").await?;
27+
process_data(str_content.as_bytes());
28+
29+
Ok(())
30+
}
31+
```
32+
33+
> Add `tokio` to `Cargo.toml` with the [`macros`] and [`fs`] features enabled.
34+
> ```toml
35+
> [dependencies]
36+
> tokio = { version = "*", features = ["macros", "fs"] }
37+
> ```
38+
39+
[`fs`]: https://docs.rs/crate/tokio/*/features#fs
40+
[`macros`]: https://docs.rs/crate/tokio/*/features#macros
41+
[`read_to_string`]: https://docs.rs/tokio/*/tokio/fs/fn.read_to_string.html
42+
[`read`]: https://docs.rs/tokio/*/tokio/fs/fn.read.html

0 commit comments

Comments
 (0)