rust-by-practice Documentation

Rust By Practice will evolve into Origin.

14,804 stars Rust Rust 4 files ยท ~2,691 tokens #example#examples#exercise#exercises#learning#practice#rust#study
RAW Doc

Technical Documentation: sunface/rust-by-practice

โ„น๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference

Overview (`Readme.md`)

This book was designed for easily diving into and getting skilled with Rust It's very easy to use. All you need to do is to make each exercise compile without ERRORS and Panics!

Reading online

Features

Part of our examples and exercises are borrowed from Rust By Example, thanks for your great works!

Although they are so awesome, we have our own secret weapons :)

  • There are three parts in each chapter: examples, exercises and practices

  • Besides examples, we have a lot of exercises, you can Read, Edit and Run them ONLINE

  • Covering nearly all aspects of Rust, such as async/await, threads, sync primitives, optimizing, standard libraries, tool chain, data structures and algorithms etc.

  • Every exercise has its own solutions

  • The overall difficulties are a bit higher and from easy to super hard: easy ๐ŸŒŸ medium ๐ŸŒŸ๐ŸŒŸ hard ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ super hard ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ

What we want to do is fill in the gap between learning and getting started with real projects.

Running locally

We use mdbook building our exercises. You can run locally with below steps:

  • Clone the repo
shell
$ git clone https://github.com/sunface/rust-by-practice
  • Install mdbook using Cargo
shell
$ cargo install mdbook
  • For Book in English
shell
$ cd rust-by-practice && mdbook serve en/
  • For Book in Chinese
shell
$ cd rust-by-practice && mdbook serve zh-CN/

Some of our exercises

๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ Tuple struct looks similar to tuples, it has added meaning the struct name provides but has no named fields. It's useful when you want give the whole tuple a name, but don't care the fields's names.

rust
// fix the error and fill the blanks
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
    let v = Point(___, ___, ___);
    check_color(v);
}

fn check_color(p: Color) {
    let (x, _, _) = p;
    assert_eq!(x, 0);
    assert_eq!(p.1, 127);
    assert_eq!(___, 255);
 }

๐ŸŒŸ๐ŸŒŸ Within the destructuring of a single variable, both by-move and by-reference pattern bindings can be used at the same time. Doing this will result in a partial move of the variable, which means that parts of the variable will be moved while other parts stay. In such a case, the parent variable cannot be used afterwards as a whole, however the parts that are only referenced (and not moved) can still be used.

rust
// fix errors to make it work
#[derive(Debug)]
struct File {
    name: String,
    data: String,
}
fn main() {
    let f = File {
        name: String::from("readme.md"),
        data: "Rust By Practice".to_string()
    };

    let _name = f.name;

    // ONLY modify this line
    println!("{}, {}, {:?}",f.name, f.data, f);
}

๐ŸŒŸ๐ŸŒŸ A match guard is an additional if condition specified after the pattern in a match arm that must also match, along with the pattern matching, for that arm to be chosen.

rust,editable
// fill in the blank to make the code work, `split` MUST be used
fn main() {
    let num = Some(4);
    let split = 5;
    match num {
        Some(x) __ => assert!(x < split),
        Some(x) => assert!(x >= split),
        None => (),
    }
}

Overview (`practices/doc-comments/Readme.md`)

Doc comments

A practice project used in Comments and Docs chapter.


Overview (`practices/hello-package/Readme.md`)

Hello Package

A practice project used in Crate and Module chapter.

This project will guide us to create a package with a binary crate and several library crates in it.

The project structure is as below:

shell
.
โ”œโ”€โ”€ Cargo.lock
โ”œโ”€โ”€ Cargo.toml
โ”œโ”€โ”€ Readme.md
โ”œโ”€โ”€ src
โ”‚ย ย  โ”œโ”€โ”€ back_of_house.rs
โ”‚ย ย  โ”œโ”€โ”€ front_of_house
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ hosting.rs
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ mod.rs
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ serving.rs
โ”‚ย ย  โ”œโ”€โ”€ lib.rs
โ”‚ย ย  โ””โ”€โ”€ main.rs

Overview (`zh-CN/assets/mini-redis/README.md`)

mini-redis

ๆœฌ้กน็›ฎไปŽtokio/mini-redisfork่€Œๆฅ๏ผŒไฝœไธบrust course็š„็ปƒไน ้กน็›ฎไน‹ไธ€๏ผŒๆ–‡ๆกฃๅ’Œๆณจ้‡Š่ฟ˜ๆœช่ฟ›่กŒ็ฟป่ฏ‘๏ผŒๆฌข่ฟŽๅคงๅฎถ่ดก็Œฎใ€‚

mini-redis is an incomplete, idiomatic implementation of a
Redis client and server built with
Tokio.

The intent of this project is to provide a larger example of writing a Tokio
application.

Disclaimer Please don't use mini-redis in production. This project is
intended to be a learning resource, and omits various parts of the Redis
protocol because implementing them would not introduce any new concepts. We will
not add new features because you need them in your project โ€” use one of the
fully featured alternatives instead.

Why Redis

The primary goal of this project is teaching Tokio. Doing this requires a
project with a wide range of features with a focus on implementation simplicity.
Redis, an in-memory database, provides a wide range of features and uses a
simple wire protocol. The wide range of features allows demonstrating many Tokio
patterns in a "real world" context.

The Redis wire protocol documentation can be found here.

The set of commands Redis provides can be found
here.

Running

The repository provides a server, client library, and some client executables
for interacting with the server.

Start the server:

text
RUST_LOG=debug cargo run --bin mini-redis-server

The tracing crate is used to provide structured logs.
You can substitute debug with the desired log level.

Then, in a different terminal window, the various client examples
can be executed. For example:

text
cargo run --example hello_world

Additionally, a CLI client is provided to run arbitrary commands from the
terminal. With the server running, the following works:

text
cargo run --bin mini-redis-cli set foo bar

cargo run --bin mini-redis-cli get foo

Supported commands

mini-redis currently supports the following commands.

The Redis wire protocol specification can be found
here.

There is no support for persistence yet.

Tokio patterns

The project demonstrates a number of useful patterns, including:

TCP server

server.rs starts a TCP server that accepts connections,
and spawns a new task per connection. It gracefully handles accept errors.

Client library

client.rs shows how to model an asynchronous client. The
various capabilities are exposed as async methods.

State shared across sockets

The server maintains a Db instance that is accessible from all connected
connections. The Db instance manages the key-value state as well as pub/sub
capabilities.

Framing

connection.rs and frame.rs show how to
idiomatically implement a wire protocol. The protocol is modeled using an
intermediate representation, the Frame structure. Connection takes a
TcpStream and exposes an API that sends and receives Frame values.

Graceful shutdown

The server implements graceful shutdown. tokio::signal is used to listen for
a SIGINT. Once the signal is received, shutdown begins. The server stops
accepting new connections. Existing connections are notified to shutdown
gracefully. In-flight work is completed, and the connection is closed.

Concurrent connection limiting

The server uses a Semaphore limits the maximum number of concurrent
connections. Once the limit is reached, the server stops accepting new
connections until an existing one terminates.

Pub/Sub

The server implements non-trivial pub/sub capability. The client may subscribe
to multiple channels and update its subscription at any time. The server
implements this using one broadcast channel per channel and a
StreamMap per connection. Clients are able to send subscription commands to
the server to update the active subscriptions.

Using a `std::sync::Mutex` in an async application

The server uses a std::sync::Mutex and not a Tokio mutex to synchronize
access to shared state. See db.rs for more details.

Testing asynchronous code that relies on time

In tests/server.rs, there are tests for key expiration.
These tests depend on time passing. In order to make the tests deterministic,
time is mocked out using Tokio's testing utilities.

Contributing

Contributions to mini-redis are welcome. Keep in mind, the goal of the project
is not to reach feature parity with real Redis, but to demonstrate
asynchronous Rust patterns with Tokio.

Commands or other features should only be added if doing so is useful to
demonstrate a new pattern.

Contributions should come with extensive comments targetted to new Tokio users.

Contributions that only focus on clarifying and improving comments are very
welcome.

License

This project is licensed under the MIT license.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in mini-redis by you, shall be licensed as MIT, without any
additional terms or conditions.


--- METRICS ---