You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-10-09 02:42:04 +02:00
Merge branch 'main' into raii
This commit is contained in:
@@ -1,12 +1,5 @@
|
||||
[alias]
|
||||
# WARNING: Using the `xtask` alias is deprecated and will be unsupported in a
|
||||
# future version of Cargo. See https://github.com/rust-lang/cargo/issues/10049.
|
||||
xtask = "run --package xtask --"
|
||||
install-tools = "run --package xtask -- install-tools"
|
||||
web-tests = "run --package xtask -- web-tests"
|
||||
rust-tests = "run --package xtask -- rust-tests"
|
||||
serve = "run --package xtask -- serve"
|
||||
build-book = "run --package xtask -- build"
|
||||
|
||||
[env]
|
||||
# To provide an anchor to the root of the workspace when working with paths.
|
||||
|
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -14,7 +14,7 @@ po/pl.po @jkotur @dyeroshenko
|
||||
po/pt-BR.po @rastringer @hugojacob @henrif75 @joaovicmendes @azevedoalice
|
||||
po/ro.po @AlexandraImbrisca @razvanm
|
||||
po/ru.po @istolga @baltuky @zvonden @dyeroshenko
|
||||
po/tr.po @alerque @Enes1313
|
||||
po/tr.po @alerque @Enes1313 @rexoplans1
|
||||
po/uk.po @dyeroshenko
|
||||
po/vi.po @daivinhtran @qu-ngx
|
||||
po/zh-CN.po @wnghl @anlunx @kongy @noahdragon @superwhd @emmali01 @candysonya @AgainstEntropy
|
||||
|
44
.github/workflows/apt-get-install/action.yml
vendored
Normal file
44
.github/workflows/apt-get-install/action.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Setup Apt and Install Packages
|
||||
description: Configures apt, runs update once per job, and installs packages.
|
||||
|
||||
inputs:
|
||||
packages:
|
||||
description: A space-separated list of packages to install.
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Configure dpkg and apt for CI
|
||||
shell: bash
|
||||
run: |
|
||||
# Avoid time-consuming man-db updates.
|
||||
sudo tee /etc/dpkg/dpkg.cfg.d/99-no-doc > /dev/null <<EOF
|
||||
path-exclude /usr/share/doc/*
|
||||
path-exclude /usr/share/man/*
|
||||
path-exclude /usr/share/info/*
|
||||
EOF
|
||||
|
||||
# Exclude translations.
|
||||
sudo tee /etc/apt/apt.conf.d/99-no-translations > /dev/null <<EOF
|
||||
Acquire::Languages "none";
|
||||
EOF
|
||||
|
||||
# Exclude command-not-found utility.
|
||||
sudo rm -f /etc/apt/apt.conf.d/50command-not-found
|
||||
|
||||
# Remove unnecessary repository lists (we don't install Azure
|
||||
# utilities)
|
||||
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.* /etc/apt/sources.list.d/azure-cli.*
|
||||
|
||||
- name: Run apt-get update
|
||||
if: env.APT_UPDATED != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
echo "APT_UPDATED=true" >> $GITHUB_ENV
|
||||
|
||||
- name: Installing ${{ inputs.packages }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get install --quiet --yes ${{ inputs.packages }}
|
54
.github/workflows/build.yml
vendored
54
.github/workflows/build.yml
vendored
@@ -11,36 +11,6 @@ env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install formatting dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install gettext yapf3
|
||||
|
||||
- name: Install nightly rustfmt
|
||||
run: |
|
||||
rustup default nightly
|
||||
rustup component add rustfmt
|
||||
|
||||
- name: Check formatting
|
||||
uses: dprint/check@v2.3
|
||||
|
||||
typos:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check for typos
|
||||
uses: crate-ci/typos@v1.34.0
|
||||
with:
|
||||
config: ./.github/typos.toml
|
||||
|
||||
cargo:
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -50,7 +20,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Update Rust
|
||||
run: rustup update
|
||||
@@ -81,7 +51,7 @@ jobs:
|
||||
target: aarch64-unknown-none
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install toolchain
|
||||
run: |
|
||||
@@ -92,9 +62,9 @@ jobs:
|
||||
uses: ./.github/workflows/setup-rust-cache
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install gcc-aarch64-linux-gnu
|
||||
uses: ./.github/workflows/apt-get-install
|
||||
with:
|
||||
packages: gcc-aarch64-linux-gnu
|
||||
|
||||
- name: Build Rust code
|
||||
working-directory: ${{ matrix.directory }}
|
||||
@@ -106,7 +76,7 @@ jobs:
|
||||
languages: ${{ steps.find-languages.outputs.languages }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Find languages
|
||||
id: find-languages
|
||||
@@ -131,7 +101,7 @@ jobs:
|
||||
LINK_CHECKED_LANGUAGES: '["en", "fa"]'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0 # We need the full history for build.sh below.
|
||||
|
||||
@@ -143,10 +113,10 @@ jobs:
|
||||
with:
|
||||
key: ${{ contains(fromJSON(env.LINK_CHECKED_LANGUAGES), matrix.language) }}
|
||||
|
||||
- name: Install Gettext
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install gettext
|
||||
- name: Install dependencies
|
||||
uses: ./.github/workflows/apt-get-install
|
||||
with:
|
||||
packages: gettext
|
||||
|
||||
- name: Install mdbook
|
||||
uses: ./.github/workflows/install-mdbook
|
||||
@@ -202,7 +172,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
2
.github/workflows/check-msgid-changes.yml
vendored
2
.github/workflows/check-msgid-changes.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
14
.github/workflows/install-mdbook/action.yml
vendored
14
.github/workflows/install-mdbook/action.yml
vendored
@@ -5,14 +5,20 @@ description: Install mdbook with the dependencies we need.
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Ensure cargo-binstall is installed
|
||||
uses: cargo-bins/cargo-binstall@main
|
||||
|
||||
- name: Install mdbook
|
||||
run: cargo xtask install-tools
|
||||
run: cargo xtask install-tools --binstall
|
||||
shell: bash
|
||||
|
||||
- name: Install dependencies for mdbook-pandoc
|
||||
- name: Install mdbook-pandoc dependencies
|
||||
uses: ./.github/workflows/apt-get-install
|
||||
with:
|
||||
packages: texlive texlive-luatex texlive-lang-cjk texlive-lang-arabic librsvg2-bin fonts-noto
|
||||
|
||||
- name: Install mdbook-pandoc
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y texlive texlive-luatex texlive-lang-cjk texlive-lang-arabic librsvg2-bin fonts-noto
|
||||
curl -LsSf https://github.com/jgm/pandoc/releases/download/3.7.0.1/pandoc-3.7.0.1-linux-amd64.tar.gz | tar zxf -
|
||||
echo "$PWD/pandoc-3.7.0.1/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
|
55
.github/workflows/lint.yml
vendored
Normal file
55
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
clippy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Rust cache
|
||||
uses: ./.github/workflows/setup-rust-cache
|
||||
|
||||
- name: Clippy
|
||||
run: cargo clippy -- -Dwarnings
|
||||
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NIGHTLY_VERSION: nightly-2025-09-01
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install formatting dependencies
|
||||
uses: ./.github/workflows/apt-get-install
|
||||
with:
|
||||
packages: gettext yapf3
|
||||
|
||||
- name: Install pinned nightly for rustfmt
|
||||
run: |
|
||||
rustup toolchain install --profile minimal "$NIGHTLY_VERSION"
|
||||
rustup component add rustfmt --toolchain "$NIGHTLY_VERSION"
|
||||
|
||||
- name: Check formatting
|
||||
uses: dprint/check@v2.3
|
||||
|
||||
typos:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Check for typos
|
||||
uses: crate-ci/typos@v1.35.7
|
||||
with:
|
||||
config: ./.github/typos.toml
|
10
.github/workflows/publish.yml
vendored
10
.github/workflows/publish.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0 # We need the full history for build.sh below.
|
||||
|
||||
@@ -42,9 +42,9 @@ jobs:
|
||||
uses: ./.github/workflows/setup-rust-cache
|
||||
|
||||
- name: Install Gettext
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install gettext
|
||||
uses: ./.github/workflows/apt-get-install
|
||||
with:
|
||||
packages: gettext
|
||||
|
||||
- name: Install mdbook
|
||||
uses: ./.github/workflows/install-mdbook
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
uses: actions/configure-pages@v5
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
with:
|
||||
path: book/html
|
||||
|
||||
|
@@ -3,8 +3,10 @@
|
||||
We'd love to accept your patches and contributions to this project. There are
|
||||
just a few small guidelines you need to follow.
|
||||
|
||||
Make sure you can build the book, and that `mdbook serve` works. Please follow
|
||||
the [instructions in the README].
|
||||
Make sure you can build the book with `mdbook build`, that `mdbook serve` works,
|
||||
and that `dprint fmt` formats the code. Please use `cargo xtask install-tools`
|
||||
to install the necessary dependencies, following the
|
||||
[instructions in the README].
|
||||
|
||||
[instructions in the README]: README.md#building
|
||||
|
||||
@@ -53,6 +55,16 @@ this:
|
||||
|
||||
Run `dprint fmt` to automatically format all files.
|
||||
|
||||
**Note:** To make sure you have the correct version of `rustfmt` installed,
|
||||
please run:
|
||||
|
||||
```bash
|
||||
cargo xtask install-tools
|
||||
```
|
||||
|
||||
This will install the pinned nightly toolchain and add the `rustfmt` component,
|
||||
so your local formatting will match the CI.
|
||||
|
||||
### Linux
|
||||
|
||||
Install `dprint` using their
|
||||
|
1890
Cargo.lock
generated
1890
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
173
GEMINI.md
Normal file
173
GEMINI.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# Project Overview
|
||||
|
||||
This repository contains the source code for Comprehensive Rust, a family of
|
||||
courses on Rust developed by Google, starting with Rust foundations, and
|
||||
including deep dives into specialized topics like Android, Chromium, bare-metal
|
||||
development, and concurrency. The project is a Rust workspace that leverages
|
||||
`mdbook` to generate a course website.
|
||||
|
||||
## Key Technologies
|
||||
|
||||
- **Rust:** The primary programming language for the course subject, custom
|
||||
tools, and examples.
|
||||
- **mdbook:** A command-line tool to create books from Markdown files, used for
|
||||
generating the course website.
|
||||
- **Custom mdbook Preprocessors:** `mdbook-course` and `mdbook-exerciser` are
|
||||
Rust binaries that extend `mdbook`'s functionality, for example, to extract
|
||||
exercise starter code.
|
||||
- **`cargo xtask`:** A custom binary within the workspace used for project
|
||||
automation, simplifying common development tasks.
|
||||
|
||||
# Building and Running
|
||||
|
||||
The project uses `cargo xtask` for project-specific automation, like builds,
|
||||
tests, and managing translations.
|
||||
|
||||
## Setup
|
||||
|
||||
1. **Install Rust:** Follow the instructions on
|
||||
[https://rustup.rs/](https://rustup.rs/).
|
||||
2. **Clone Repository:**
|
||||
```bash
|
||||
git clone https://github.com/google/comprehensive-rust/
|
||||
cd comprehensive-rust
|
||||
```
|
||||
3. **Install Project Tools:**
|
||||
```bash
|
||||
cargo xtask install-tools
|
||||
```
|
||||
This is a necessary first step for working with this repository. It will
|
||||
install the correct versions of all tools used by the project.
|
||||
|
||||
## Commands
|
||||
|
||||
All commands are run using `cargo xtask`. Run `cargo xtask --help` for a full
|
||||
list of options.
|
||||
|
||||
- **Serve the Course Locally:** Starts a web server to view the course content.
|
||||
```bash
|
||||
cargo xtask serve [--language <ISO_639_language_code>] [--output <output_directory>]
|
||||
```
|
||||
(e.g., `cargo xtask serve -l da` for the Danish translation)
|
||||
|
||||
- **Build the Course:** Creates a static version of the course in the `book/`
|
||||
directory.
|
||||
```bash
|
||||
cargo xtask build [--language <ISO_639_language_code>] [--output <output_directory>]
|
||||
```
|
||||
|
||||
- **Run Rust Snippet Tests:** Tests all Rust code snippets included in the
|
||||
course material.
|
||||
```bash
|
||||
cargo xtask rust-tests
|
||||
```
|
||||
|
||||
- **Run Web Driver Tests:** Executes web driver tests located in the `tests/`
|
||||
directory.
|
||||
```bash
|
||||
cargo xtask web-tests [--dir <book_html_directory>]
|
||||
```
|
||||
|
||||
# Development Conventions
|
||||
|
||||
- **Project Automation:** `cargo xtask` is the primary interface for common
|
||||
development tasks.
|
||||
- **Course Content:** Markdown files in the `src/` directory, structured
|
||||
according to `src/SUMMARY.md`.
|
||||
- **Code Formatting:** `dprint fmt` is used to format all source files according
|
||||
to `rustfmt.toml` and `dprint.json`. Note that you must first install the
|
||||
project tools with `cargo xtask install-tools`.
|
||||
- **Contributions:** Refer to `CONTRIBUTING.md` for guidelines on contributing
|
||||
to the project.
|
||||
- **Style:** Refer to `STYLE.md` for style guidelines. When making changes to
|
||||
Markdown files in `src/`, always first read `STYLE.md` and follow its
|
||||
conventions.
|
||||
- **GitHub Actions:** The project uses composite GitHub Actions to simplify CI
|
||||
workflows. These actions should be preferred over hand-written commands.
|
||||
- **`apt-get-install`:** This action efficiently installs Debian packages. It
|
||||
configures `dpkg` and `apt` to skip documentation and translations, and
|
||||
ensures that `apt-get update` is run only once per job. This significantly
|
||||
speeds up CI runs.
|
||||
- **`install-mdbook`:** A composite action to install `mdbook` and its
|
||||
dependencies, including `pandoc` and `texlive`.
|
||||
- **`setup-rust-cache`:** A composite action that configures the
|
||||
`Swatinem/rust-cache` action.
|
||||
|
||||
## Markdown Conventions
|
||||
|
||||
- **Headings:**
|
||||
- **H1 (`#`):** Used for the main title of each page. Each slide has exactly
|
||||
one title.
|
||||
- **H2 (`##`):** Used for major sections. Slides do not use H2 headings to
|
||||
save vertical space; more slides are created instead.
|
||||
- **H3 (`###`):** Used for sub-sections, but not on slides.
|
||||
|
||||
- **Emphasis:**
|
||||
- **Bold (`**...**`):** Used to highlight key terms, commands, and for notes
|
||||
(e.g., `**Note:**`). The colon (`:`) is included inside the bold text for
|
||||
notes.
|
||||
- **Italic (`_..._`):** Used for general emphasis, titles of external
|
||||
articles, and for terms being defined.
|
||||
|
||||
- **Code:**
|
||||
- **Inline Code (`` `...` ``):** Used for code snippets, file names, commands,
|
||||
type names, and language keywords. Rust fragments are formatted as `rustfmt`
|
||||
would.
|
||||
- **Code Blocks (`` ```...``` ``):** Fenced code blocks are used for
|
||||
multi-line code examples, annotated with a language identifier (e.g.,
|
||||
`rust`, `c`, `ignore`).
|
||||
- **Interactive Code Blocks:** Rust examples are made interactive with
|
||||
`editable`. Examples that fail to compile are marked with `compile_fail` or
|
||||
`should_panic`.
|
||||
- **Diagrams:** The `bob` language identifier is used in code blocks to
|
||||
generate ASCII art diagrams.
|
||||
- **Formatting Control:** The `#[rustfmt::skip]` attribute is used to prevent
|
||||
`rustfmt` from formatting specific code blocks, though it is used rarely.
|
||||
|
||||
- **Lists:**
|
||||
- **Bulleted Lists:** Unordered lists are the primary way to lay out key
|
||||
points on slides.
|
||||
- **Glossary Format:** The glossary uses a specific format with a colon and
|
||||
backslash (`:\`) after each term to create a hard line break for visual
|
||||
formatting.
|
||||
|
||||
- **Other Markdown Elements:**
|
||||
- **Block Quotes (`> ...`):** Used sparingly for important notes, warnings, or
|
||||
supplementary information to draw attention.
|
||||
- **Links:** Both standard (`[text](url)`) and reference-style
|
||||
(`[text][label]`) links are used.
|
||||
- **Tables:** Markdown tables are used to present structured data.
|
||||
- **Horizontal Rules (`---`):** Not used on slides.
|
||||
|
||||
- **HTML Tags:**
|
||||
- **`<details>`:** Used for collapsible "speaker notes".
|
||||
- **`<kbd>`:** Used to denote keyboard keys. Each key in a combination must be
|
||||
wrapped in its own tag, e.g., `<kbd>Ctrl</kbd> + <kbd>S</kbd>`.
|
||||
- **`<style>`:** Used rarely for targeted custom CSS.
|
||||
- **`<img>`:** Used to embed images.
|
||||
|
||||
- **Project-Specific Conventions:**
|
||||
- **mdbook Includes:** The `{{#include ...}}` helper is used to include
|
||||
snippets from other files.
|
||||
- **mdbook Segments:** The `{{%segment ...%}}` and `{{%session ...%}}` helpers
|
||||
are used for course structuring.
|
||||
- **Frontmatter:** Files start with YAML frontmatter (enclosed in `---`) to
|
||||
provide metadata.
|
||||
- **Doc Comments:** Standard Rust doc comments (`///`, `//!`) are used.
|
||||
`/// # Safety` is used to document safety preconditions for `unsafe` code.
|
||||
- **Comments:** HTML comments (`<!-- ... -->`) are used for editor/translator
|
||||
instructions and content control (e.g., `mdbook-xgettext: skip`).
|
||||
|
||||
# Project-Specific Technical Context
|
||||
|
||||
This section contains critical, non-obvious technical details about this
|
||||
project's tooling and environment that an AI assistant needs to know to perform
|
||||
its tasks correctly.
|
||||
|
||||
## `mdbook` Behavior
|
||||
|
||||
- **Isolated Code Snippets:** `mdbook` treats each fenced Rust code block (e.g.,
|
||||
`` ```rust ... ``` ``) as a separate compilation unit. When analyzing a code
|
||||
snippet, treat it as a self-contained program. Do not assume it shares a scope
|
||||
or context with other snippets in the same file unless the surrounding text
|
||||
explicitly states otherwise.
|
61
README.md
61
README.md
@@ -18,14 +18,14 @@ Read the course at **https://google.github.io/comprehensive-rust/**.
|
||||
|
||||
## Course Format and Target Audience
|
||||
|
||||
The course is used internally at Google when teaching Rust to experienced
|
||||
software engineers. They typically have a background in C++ or Java.
|
||||
The course is used internally at Google to teach Rust to experienced software
|
||||
engineers, typically with a background in C++ or Java.
|
||||
|
||||
The course is taught in a classroom setting and we hope it will be useful for
|
||||
others who want to teach Rust to their team. The course will be less useful for
|
||||
self-study since you miss out on the discussions happening in the classroom. You
|
||||
don't see the questions and answers and you don't see the compiler errors we
|
||||
trigger when going through the code samples. We hope to improve on this via
|
||||
The course is taught in a classroom setting, and we hope it will be useful for
|
||||
others who want to teach Rust to their team. The course is less ideal for
|
||||
self-study, since you would miss out on classroom discussions. You would not see
|
||||
the questions and answers, nor the compiler errors we trigger when going through
|
||||
the code samples. We hope to improve the self-study experience via
|
||||
[speaker notes](https://github.com/google/comprehensive-rust/issues/53) and by
|
||||
[publishing videos](https://github.com/google/comprehensive-rust/issues/52).
|
||||
|
||||
@@ -40,11 +40,11 @@ Articles and blog posts from around the web which cover Comprehensive Rust:
|
||||
_[Scaling Rust Adoption Through Training](https://security.googleblog.com/2023/09/scaling-rust-adoption-through-training.html)_.
|
||||
We published a blog post with details on the development of the course.
|
||||
- 2023-10-02:
|
||||
_[In Search of Rust Developers, Companies Turn to In-House Training](https://www.darkreading.com/application-security/google-microsoft-take-refuge-in-rust-languages-better-security)_.
|
||||
_[In Search of Rust Developers, Companies Turn to In-House Training](https://www.darkreading.com/application-security/seeking-rust-developers-in-house-training)_.
|
||||
About how Microsoft, Google, and others are training people in Rust.
|
||||
- 2024-10-18:
|
||||
_[Rust Training at Scale | Rust Global @ RustConf 2024](https://youtu.be/7h5KyMqt2-Q?si=4M99HdWWxMaqN8Zr)_.
|
||||
What Google learnt from teaching Comprehensive Rust for more than two years.
|
||||
What Google learned from teaching Comprehensive Rust for more than two years.
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -57,7 +57,7 @@ The course is built using a few tools:
|
||||
- [mdbook-course](mdbook-course/)
|
||||
- [mdbook-linkcheck2](https://github.com/marxin/mdbook-linkcheck2)
|
||||
|
||||
First install Rust by following the instructions on https://rustup.rs/. Then
|
||||
First, install Rust by following the instructions on https://rustup.rs/. Then
|
||||
clone this repository:
|
||||
|
||||
```shell
|
||||
@@ -65,45 +65,36 @@ git clone https://github.com/google/comprehensive-rust/
|
||||
cd comprehensive-rust
|
||||
```
|
||||
|
||||
Then install these tools with:
|
||||
Then run the following command to install the correct versions of all tools
|
||||
mentioned above:
|
||||
|
||||
```shell
|
||||
cargo xtask install-tools
|
||||
```
|
||||
|
||||
This uses `cargo install` to install the tools, so you will find them in your
|
||||
`~/.cargo/bin/` directory afterwards.
|
||||
|
||||
## Commands
|
||||
|
||||
Here is a summary of the various commands you can run in the project.
|
||||
Here are some of the commonly used commands you can run in the project. Run
|
||||
`cargo xtask` to view all available commands.
|
||||
|
||||
| Command | Description |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `cargo install-tools` | Install all the tools the project depends on. |
|
||||
| `cargo serve` | Start a web server with the course. You'll find the content on http://localhost:3000. |
|
||||
| `cargo rust-tests` | Test the included Rust snippets. |
|
||||
| `cargo web-tests` | Run the web driver tests in the tests directory. |
|
||||
| `cargo build-book` | Create a static version of the course in the `book/` directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, run MDBOOK_BOOK__LANGUAGE=xx mdbook build -d book/xx where xx is the ISO 639 language code (e.g. da for the Danish translation). [TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions. |
|
||||
| Command | Description |
|
||||
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `cargo xtask install-tools` | Install all the tools the project depends on. |
|
||||
| `cargo xtask serve` | Start a web server with the course. You'll find the content on http://localhost:3000. To serve any of the translated versions of the course, add the language flag (--language or -l) followed by xx, where xx is the ISO 639 language code (e.g. cargo xtask serve -l da for the Danish translation). |
|
||||
| `cargo xtask rust-tests` | Test the included Rust snippets. |
|
||||
| `cargo xtask web-tests` | Run the web driver tests in the tests directory. |
|
||||
| `cargo xtask build` | Create a static version of the course in the `book/` directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, add the language flag (--language or -l) followed by xx, where xx is the ISO 639 language code (e.g. cargo xtask build -l da for the Danish translation). [TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions. |
|
||||
|
||||
> **Note** On Windows, you need to enable symlinks
|
||||
> (`git config --global core.symlinks true`) and Developer Mode.
|
||||
|
||||
> **Note** Previous versions this README recommended that you use
|
||||
> `cargo xtool <tool>`, i.e. `cargo xtool install-tools`. This causes issues
|
||||
> with pre-existing installations of `cargo-xtool` and is now deprecated.
|
||||
>
|
||||
> The new syntax is almost a 1:1 mapping, although `cargo xtool build` has
|
||||
> become `cargo build-book` to avoid conflicting with the built-in Cargo
|
||||
> subcommand.
|
||||
>
|
||||
> - `cargo xtool build` -> `cargo build-book`
|
||||
> - `cargo xtool install-tools` -> `cargo install-tools`
|
||||
> - `cargo xtool serve` -> `cargo serve`
|
||||
> - `cargo xtool run-tests` -> `cargo run-tests`
|
||||
> - `cargo xtool web-tests` -> `cargo web-tests`
|
||||
|
||||
## Contributing
|
||||
|
||||
We would like to receive your contributions. Please see
|
||||
[CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
||||
We welcome contributions. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for
|
||||
details.
|
||||
|
||||
## Contact
|
||||
|
||||
|
284
STYLE.md
284
STYLE.md
@@ -4,6 +4,91 @@ The course has been expanded and improved by tons of volunteers like you! Thank
|
||||
you for that! To help ensure a consistent style throughout the course, we have
|
||||
written down some guidelines for you to follow.
|
||||
|
||||
## Course Philosophy and Design
|
||||
|
||||
To contribute effectively, it's helpful to understand the core design principles
|
||||
of Comprehensive Rust. This is not a self-study book; it is a set of slides and
|
||||
notes for an **instructor-led course**.
|
||||
|
||||
### Target Audience
|
||||
|
||||
The course is designed for an audience of experienced software engineers who are
|
||||
new to Rust. We assume they have 2-3 years of experience in an imperative
|
||||
language like C, C++11+, Java 7+, Python, or Go.
|
||||
|
||||
We **do not** assume familiarity with functional programming concepts or
|
||||
features from more modern languages like Swift or Kotlin. Course material should
|
||||
build upon the concepts that are likely to be familiar to this audience.
|
||||
|
||||
### Goals
|
||||
|
||||
The goal of the course is to provide a solid foundation in Rust within a bounded
|
||||
time frame. This prepares students to continue learning effectively as they
|
||||
begin to apply their new skills on the job.
|
||||
|
||||
### Pedagogical Principles
|
||||
|
||||
We follow a few key principles to make the material effective for learning:
|
||||
|
||||
- **Build on a Foundation:** New Rust concepts should be connected to what a
|
||||
learner already knows, either from their prior language experience or from
|
||||
earlier parts of this course.
|
||||
- **Provide a Working Mental Model (The "No Magic" Rule):** As much as possible,
|
||||
avoid telling students to accept syntax or behavior that will be explained
|
||||
later. For everything that appears on the slides or in exercises, we must
|
||||
provide a working mental model that allows the student to understand and use
|
||||
the concept.
|
||||
- **Use a [Spiral Approach](https://en.wikipedia.org/wiki/Spiral_approach):** To
|
||||
avoid overwhelming the learner, it is highly encouraged to introduce a concept
|
||||
by first providing basic facts and a simplified mental model. The topic can
|
||||
then be revisited later to provide more detail. For example, very early in the
|
||||
course we explain the basics of `println!`, mention that it is a macro so the
|
||||
usage syntax is a bit unusual, but we don't go into details of format strings
|
||||
or macros. We explain details of format strings later, once we have covered
|
||||
traits and can mention the `Debug` and `Display` traits.
|
||||
- **Live, Interactive Instruction:** The instructor is expected to run and
|
||||
modify the code on the slides, and use compiler errors as a teaching tool. The
|
||||
audience is expected to frequently interrupt with questions, and the
|
||||
instructor would often experiment with the code on the slide to illustrate the
|
||||
answer.
|
||||
|
||||
### Pacing and Structure
|
||||
|
||||
The course is designed for approximately 5 hours of teaching per day, typically
|
||||
split into a 3-hour morning session and a 2-hour afternoon session.
|
||||
|
||||
This pacing is important context for contributors. Material should be structured
|
||||
to fit this rhythm, with clear sections that can be taught in roughly 45-50
|
||||
minute blocks to accommodate short breaks and Q&A.
|
||||
|
||||
Each slide must include a `minutes` field in its frontmatter, which specifies
|
||||
the estimated teaching time for that slide. This helps ensure the overall pacing
|
||||
of the course remains consistent.
|
||||
|
||||
### Course Structure
|
||||
|
||||
The course starts with a core **Rust Fundamentals** curriculum, followed by a
|
||||
collection of specialized **deep dives**. All students take the Fundamentals
|
||||
course and can then opt into any deep dives that are relevant to them.
|
||||
|
||||
#### The Rust Fundamentals Course
|
||||
|
||||
The **Rust Fundamentals** course provides a solid foundation in a strictly
|
||||
bounded, four-day time frame. This duration is firm, and its scope is carefully
|
||||
managed to focus on the most essential concepts for new Rust programmers.
|
||||
|
||||
The overall progression of the course starts with the parts of the Rust language
|
||||
that should be conceptually familiar to most students from other languages. Then
|
||||
we move on to more difficult parts (for example, enums with payloads and
|
||||
generics), and parts that are unique to Rust (lifetimes and the borrow checker).
|
||||
|
||||
Contributors should keep this structure in mind. The four-day schedule for the
|
||||
Fundamentals course is completely full, leaving no time slack for new topics.
|
||||
Proposals to add material to the Rust Fundamentals course must also include a
|
||||
plan to shorten or remove existing content. Refinements to existing topics are
|
||||
always welcome. Topics that are not essential for all new Rust programmers
|
||||
should be proposed as new deep dives.
|
||||
|
||||
## Course Slides
|
||||
|
||||
Please take the following into account when updating the course material.
|
||||
@@ -26,23 +111,90 @@ Use the rectangle as a rough guide for how much you can fit on a single slide.
|
||||
If you find yourself adding too much detail, move the details to the speaker
|
||||
notes (see below).
|
||||
|
||||
### Rust Code
|
||||
### One Core Idea Per Slide
|
||||
|
||||
When showing Rust code, please use the same spacing as `rustfmt`: `3 * x`
|
||||
instead of `3*x`. However, feel free to remove newlines when it can make the
|
||||
code more compact and easier to understand, e.g., you can use
|
||||
Ideally, each slide should focus on a single, clear takeaway. If a slide
|
||||
introduces a core concept and then explores an important but distinct tangent
|
||||
(e.g., a limitation or an advanced use case), that tangent should be moved to
|
||||
its own slide. This keeps the presentation focused and easier to follow.
|
||||
|
||||
<!-- dprint-ignore-start -->
|
||||
Consider the instructor's workflow. If the speaker notes require a long or
|
||||
complex series of live edits, it can be difficult for the instructor to execute
|
||||
well every time. It may be better to add a new slide that presents the desired
|
||||
state of the code.
|
||||
|
||||
```rust
|
||||
struct Person { name: String }
|
||||
```
|
||||
### Pedagogical Flow
|
||||
|
||||
<!-- dprint-ignore-end -->
|
||||
When introducing a new concept, start with a simple, relatable, and concrete
|
||||
example. A good opening example grounds the concept for the learner and provides
|
||||
motivation for the more detailed explanation that will follow.
|
||||
|
||||
if the `Person` struct is not important for your example. Please use this
|
||||
sparingly: enclose the code block in `<!-- dprint-ignore-start -->` and
|
||||
`<!-- dprint-ignore-end -->` to suppress warnings about the formatting.
|
||||
### Use Meaningful Examples
|
||||
|
||||
Code samples on the slides should be short and do something meaningful. Avoid
|
||||
using generic placeholders like `Foo`, `Bar`, and `Baz`. Using descriptive names
|
||||
from a real-world, even if simplified, domain makes the code easier to
|
||||
understand and relate to.
|
||||
|
||||
### Plan Interactive Code Snippets
|
||||
|
||||
All Rust code blocks in the course are not static text but are live, editable
|
||||
playgrounds. An important teaching method is for the instructor to edit these
|
||||
snippets live to demonstrate concepts, introduce and fix errors, and explore
|
||||
variations based on student questions.
|
||||
|
||||
Contributors should design their slides with this interactivity in mind. The
|
||||
initial state of the code should be a good starting point for a live
|
||||
demonstration.
|
||||
|
||||
### `mdbook` and `mdbook-course` Conventions
|
||||
|
||||
The project uses `mdbook` features in specific ways, as well as a custom
|
||||
preprocessor, `mdbook-course`. The following conventions are mandatory:
|
||||
|
||||
- **YAML Frontmatter:** Every slide file **must** include YAML frontmatter at
|
||||
the top. At a minimum, this must include the `minutes` field to specify the
|
||||
estimated teaching time.
|
||||
- **Outline Helpers:** Pages that serve as an index for a session or segment
|
||||
**must** use the `{{%session outline%}}` or `{{%segment outline%}}` helpers.
|
||||
- **File Includes:** Code for exercises and their solutions **must** be included
|
||||
from external files using the standard `mdbook` `{{#include ...}}` helper.
|
||||
- **Translation Directives:** To prevent an element (such as a paragraph, code
|
||||
block, or list item) from being translated, place a
|
||||
`<!-- mdbook-xgettext: skip -->` comment on a line by itself, followed by a
|
||||
blank line, immediately before the element.
|
||||
|
||||
For a complete explanation of the custom helpers and all available frontmatter
|
||||
fields, please refer to the [`mdbook-course` README](mdbook-course/README.md).
|
||||
|
||||
### Language and Tone
|
||||
|
||||
The courses are written in American English, so write "initialize", not
|
||||
"initialise".
|
||||
|
||||
Use an informal, friendly, and concise tone. Remember that the courses are meant
|
||||
to be taught by an experienced programmer to other experienced programmers. When
|
||||
possible, prefer terminology used in
|
||||
[the official Rust Book](https://doc.rust-lang.org/book/). If a less common but
|
||||
necessary term is used, provide a brief definition.
|
||||
|
||||
## Exercises
|
||||
|
||||
At the end of some sections, learners will actively engage with the material by
|
||||
completing a small exercise. The goal of an exercise is to provide hands-on
|
||||
practice with the concepts just taught.
|
||||
|
||||
Please keep the following principles in mind when creating or updating
|
||||
exercises:
|
||||
|
||||
- **Focused Scope:** An exercise should focus on the topic of the preceding
|
||||
section. It should not require knowledge of concepts that have not yet been
|
||||
taught.
|
||||
- **Short Duration:** An exercise should be solvable by the target audience in
|
||||
approximately 10-15 minutes. The goal is a quick, successful application of
|
||||
knowledge, not a complex project.
|
||||
- **Clear Instructions:** The problem description should be clear and
|
||||
unambiguous.
|
||||
|
||||
## Speaker Notes
|
||||
|
||||
@@ -50,19 +202,57 @@ We have extended `mdbook` with support for speaker notes: content added between
|
||||
`<details> ... </details>` tags is rendered in a special box that can be
|
||||
collapsed or removed entirely from the slide.
|
||||
|
||||
- Speaker notes suggest a narrative structure for the instructor.
|
||||
|
||||
- The speaker notes should expand on the topic of the slide. Use them to provide
|
||||
interesting background information for both the instructor and for students
|
||||
who look at the material outside of a class. Remember that many more people
|
||||
will read the course by themselves, so make the notes complete and useful even
|
||||
when there is no Rust expert around.
|
||||
|
||||
- Avoid using speaker notes as a script for the instructor. When teaching the
|
||||
course, instructors will only have time to glance at the notes so it is not
|
||||
useful to include full paragraphs which the instructor should read out loud.
|
||||
- For slides with evolving code examples, the notes provide a clear,
|
||||
step-by-step flow for how the code is modified and presented. This is a
|
||||
suggested flow for the instructor's live-coding session within the slide's
|
||||
interactive playground. This includes:
|
||||
|
||||
- The order in which to introduce concepts, how to motivate them.
|
||||
|
||||
- Framing of the code example: the problem it tries to solve, if not obvious.
|
||||
|
||||
- How to demonstrate variations of the code example (e.g., code that does not
|
||||
compile or illustrates a bug).
|
||||
|
||||
- How to change the code on the slide to illustrate the concepts being taught.
|
||||
|
||||
- Where to pause and engage the class with questions.
|
||||
|
||||
- Speaker notes should serve as a quick reference for instructors, not a
|
||||
verbatim script. Because instructors have limited time to glance at notes, the
|
||||
content should be concise and easy to scan.
|
||||
|
||||
**Avoid** long, narrative paragraphs meant to be read aloud:
|
||||
> **Bad:** _"In this example, we define a trait named `StrExt`. This trait has
|
||||
> a single method, `is_palindrome`, which takes a `&self` receiver and returns
|
||||
> a boolean value indicating if the string is the same forwards and
|
||||
> backwards..."_
|
||||
|
||||
**Instead, prefer** bullet points with background information or actionable
|
||||
**teaching prompts**:
|
||||
> **Good:**
|
||||
>
|
||||
> - Note: The `Ext` suffix is a common convention.
|
||||
> - Ask: What happens if the `use` statement is removed?
|
||||
> - Demo: Comment out the `use` statement to show the compiler error.
|
||||
|
||||
- Nevertheless, include all of the necessary teaching prompts for the instructor
|
||||
in the speaker notes. Unlike the main content, the speaker notes don't have to
|
||||
fit on a single slide.
|
||||
|
||||
### More to Explore
|
||||
|
||||
Move extended explanations in the notes to a "More to Explore" section:
|
||||
Use the "More to Explore" section for valuable topics that are outside the main
|
||||
scope of the class. The content should be placed within the `<details>` block as
|
||||
shown below:
|
||||
|
||||
```markdown
|
||||
<details>
|
||||
@@ -76,7 +266,61 @@ Move extended explanations in the notes to a "More to Explore" section:
|
||||
</details>
|
||||
```
|
||||
|
||||
The material there is outside the scope of the regular class.
|
||||
This section can contain a deeper explanation of a concept or provide specific
|
||||
pointers to external resources. A link should be accompanied by a brief
|
||||
explanation of what the resource contains and why it is relevant. A vague
|
||||
reference is not helpful, but a specific one can be a great tool for
|
||||
self-learners.
|
||||
|
||||
## Code Blocks Mechanics
|
||||
|
||||
Code blocks are a critical part of the course. To ensure they are consistent and
|
||||
behave as expected, please follow these conventions.
|
||||
|
||||
### Language Identifiers
|
||||
|
||||
Use the following language identifiers for fenced code blocks:
|
||||
|
||||
- **`rust`**: For Rust code examples.
|
||||
- **`shell`**: For shell commands. Use a `$` prompt for consistency. Omit the
|
||||
prompt for multi-line commands or when the output is shown.
|
||||
- **`bob`**: For ASCII art diagrams generated by `mdbook-bob`.
|
||||
- **`ignore`**: For code snippets that are not complete, self-contained programs
|
||||
or are for illustrative purposes only and should not be compiled.
|
||||
|
||||
### mdbook Annotations
|
||||
|
||||
You can add annotations to Rust code blocks to control how they are tested and
|
||||
displayed:
|
||||
|
||||
- **`editable`**: Makes the code block an interactive playground where users can
|
||||
edit and run the code. This should be used for most Rust examples.
|
||||
- **`compile_fail`**: Indicates that the code is expected to fail compilation.
|
||||
This is used to demonstrate specific compiler errors.
|
||||
- **`should_panic`**: Indicates that the code is expected to panic when run.
|
||||
- **`warnunused`**: Re-enables `unused` lints for a code block. By default, the
|
||||
course's test runner disables lints for unused variables, imports, etc., to
|
||||
avoid distracting warnings. Use this annotation only when a warning is part of
|
||||
the lesson.
|
||||
|
||||
### Rust Code Formatting
|
||||
|
||||
When showing Rust code inline, please use the same spacing as `rustfmt`: `3 * x`
|
||||
instead of `3*x`. However, feel free to remove newlines when it can make the
|
||||
code more compact and easier to understand, e.g., you can define a struct on one
|
||||
line if it is not the focus of your example:
|
||||
|
||||
<!-- dprint-ignore-start -->
|
||||
|
||||
```rust
|
||||
struct Person { name: String }
|
||||
```
|
||||
|
||||
<!-- dprint-ignore-end -->
|
||||
|
||||
Enclose the code block in `<!-- dprint-ignore-start -->` and
|
||||
`<!-- dprint-ignore-end -->` to suppress the automatic formatting. Please use
|
||||
this sparingly.
|
||||
|
||||
## Translations
|
||||
|
||||
@@ -100,6 +344,6 @@ When translating the course, please take the following into account:
|
||||
and `**strong emphasis**` like in the original.
|
||||
|
||||
- If you find mistakes or things that sound awkward in the original English
|
||||
text, please submit PRs to fix them! Fixing typos in the translation is great,
|
||||
but we want everybody to benefit from the fixes and that is why we need the
|
||||
fix to be made in the English text too.
|
||||
text, please submit PRs to fix them in the English text! Fixing typos in the
|
||||
translation is great, but we want everybody to benefit from the fixes and that
|
||||
is why we need the fix to be made in the English text too.
|
||||
|
@@ -9,7 +9,7 @@
|
||||
"command": "yapf3",
|
||||
"exts": ["py"]
|
||||
}, {
|
||||
"command": "rustup run stable rustfmt --edition 2024",
|
||||
"command": "rustup run nightly-2025-09-01 rustfmt --edition 2024",
|
||||
"exts": ["rs"]
|
||||
}]
|
||||
},
|
||||
|
@@ -9,14 +9,14 @@ repository = "https://github.com/google/comprehensive-rust"
|
||||
description = "An mdbook preprocessor for comprehensive-rust."
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.98"
|
||||
clap = "4.5.40"
|
||||
anyhow = "1.0.99"
|
||||
clap = "4.5.46"
|
||||
lazy_static = "1.5"
|
||||
log = "0.4.27"
|
||||
matter = "0.1.0-alpha4"
|
||||
mdbook = "0.4.51"
|
||||
mdbook = "0.4.52"
|
||||
pretty_env_logger = "0.5.0"
|
||||
regex = "1.11"
|
||||
serde = "1.0.219"
|
||||
serde_json = "1.0.140"
|
||||
serde_json = "1.0.143"
|
||||
serde_yaml = "0.9"
|
||||
|
@@ -48,7 +48,7 @@ fn timediff(actual: u64, target: u64, slop: u64) -> String {
|
||||
} else if actual + slop < target {
|
||||
format!("{}: ({} short)", duration(actual), duration(target - actual),)
|
||||
} else {
|
||||
format!("{}", duration(actual))
|
||||
duration(actual).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -29,7 +29,7 @@ fn main() {
|
||||
);
|
||||
let matches = app.get_matches();
|
||||
|
||||
if let Some(_) = matches.subcommand_matches("supports") {
|
||||
if matches.subcommand_matches("supports").is_some() {
|
||||
// Support all renderers.
|
||||
process::exit(0);
|
||||
}
|
||||
|
@@ -156,7 +156,7 @@ impl Courses {
|
||||
fn course_mut(&mut self, name: impl AsRef<str>) -> &mut Course {
|
||||
let name = name.as_ref();
|
||||
if let Some(found_idx) =
|
||||
self.courses.iter().position(|course| &course.name == name)
|
||||
self.courses.iter().position(|course| course.name == name)
|
||||
{
|
||||
return &mut self.courses[found_idx];
|
||||
}
|
||||
@@ -177,9 +177,7 @@ impl Courses {
|
||||
&self,
|
||||
chapter: &Chapter,
|
||||
) -> Option<(&Course, &Session, &Segment, &Slide)> {
|
||||
let Some(ref source_path) = chapter.source_path else {
|
||||
return None;
|
||||
};
|
||||
let source_path = chapter.source_path.as_ref()?;
|
||||
|
||||
for course in self {
|
||||
for session in course {
|
||||
@@ -193,7 +191,7 @@ impl Courses {
|
||||
}
|
||||
}
|
||||
|
||||
return None;
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +200,7 @@ impl<'a> IntoIterator for &'a Courses {
|
||||
type IntoIter = std::slice::Iter<'a, Course>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
(&self.courses).into_iter()
|
||||
self.courses.iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +214,7 @@ impl Course {
|
||||
fn session_mut(&mut self, name: impl AsRef<str>) -> &mut Session {
|
||||
let name = name.as_ref();
|
||||
if let Some(found_idx) =
|
||||
self.sessions.iter().position(|session| &session.name == name)
|
||||
self.sessions.iter().position(|session| session.name == name)
|
||||
{
|
||||
return &mut self.sessions[found_idx];
|
||||
}
|
||||
@@ -275,7 +273,7 @@ impl<'a> IntoIterator for &'a Course {
|
||||
type IntoIter = std::slice::Iter<'a, Session>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
(&self.sessions).into_iter()
|
||||
self.sessions.iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +346,7 @@ impl<'a> IntoIterator for &'a Session {
|
||||
type IntoIter = std::slice::Iter<'a, Segment>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
(&self.segments).into_iter()
|
||||
self.segments.iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +399,7 @@ impl<'a> IntoIterator for &'a Segment {
|
||||
type IntoIter = std::slice::Iter<'a, Slide>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
(&self.slides).into_iter()
|
||||
self.slides.iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,7 +447,7 @@ impl Slide {
|
||||
pub fn is_sub_chapter(&self, chapter: &Chapter) -> bool {
|
||||
// The first `source_path` in the slide is the "parent" chapter, so anything
|
||||
// else is a sub-chapter.
|
||||
chapter.source_path.as_ref() != self.source_paths.get(0)
|
||||
chapter.source_path.as_ref() != self.source_paths.first()
|
||||
}
|
||||
|
||||
/// Return the total duration of this slide.
|
||||
|
@@ -83,7 +83,7 @@ impl<const N: usize> Table<N> {
|
||||
for cell in iter {
|
||||
write!(f, " {} |", cell)?;
|
||||
}
|
||||
write!(f, "\n")
|
||||
writeln!(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -51,7 +51,7 @@ pub fn replace(
|
||||
["course", "outline", course_name @ ..] => {
|
||||
let course_name = course_name.join(" ");
|
||||
let Some(course) = courses.find_course(course_name) else {
|
||||
return format!("not found - {}", captures[0].to_string());
|
||||
return format!("not found - {}", &captures[0]);
|
||||
};
|
||||
course.schedule()
|
||||
}
|
||||
|
@@ -8,8 +8,8 @@ repository = "https://github.com/google/comprehensive-rust"
|
||||
description = "A tool for extracting starter code for exercises from Markdown files."
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.98"
|
||||
anyhow = "1.0.99"
|
||||
log = "0.4.27"
|
||||
mdbook = "0.4.51"
|
||||
mdbook = "0.4.52"
|
||||
pretty_env_logger = "0.5.0"
|
||||
pulldown-cmark = { version = "0.13.0", default-features = false }
|
||||
|
63
po/es.po
63
po/es.po
@@ -13653,34 +13653,32 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "Testing in Android"
|
||||
msgstr "Rust en Android"
|
||||
msgstr "Pruebas en Android"
|
||||
|
||||
#: src/android/testing.md
|
||||
msgid ""
|
||||
"Building on [Testing](../testing.md), we will now look at how unit tests "
|
||||
"work in AOSP. Use the `rust_test` module for your unit tests:"
|
||||
msgstr ""
|
||||
"Basándonos en [Pruebas](../testing.md), ahora veremos cómo funcionan las pruebas "
|
||||
"unitarias en AOSP. Usa el módulo `rust_test` para tus pruebas unitarias:"
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "_testing/Android.bp_:"
|
||||
msgstr "_hello_rust/Android.bp_:"
|
||||
msgstr "_testing/Android.bp_:"
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "\"libleftpad\""
|
||||
msgstr "\"libtextwrap\""
|
||||
msgstr "\"libleftpad\""
|
||||
|
||||
#: src/android/testing.md
|
||||
msgid "\"leftpad\""
|
||||
msgstr ""
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "\"libleftpad_test\""
|
||||
msgstr "\"libbirthday_bindgen_test\""
|
||||
msgstr "\"libleftpad_test\""
|
||||
|
||||
#: src/android/testing.md
|
||||
msgid "\"leftpad_test\""
|
||||
@@ -13691,43 +13689,36 @@ msgid "\"general-tests\""
|
||||
msgstr "\"general-tests\""
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "_testing/src/lib.rs_:"
|
||||
msgstr "_hello_rust/src/lib.rs_:"
|
||||
msgstr "_testing/src/lib.rs_:"
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "//! Left-padding library.\n"
|
||||
msgstr "//! Biblioteca de saludos.\n"
|
||||
msgstr "//! Biblioteca de relleno a la izquierda.\n"
|
||||
|
||||
#: src/android/testing.md
|
||||
msgid "/// Left-pad `s` to `width`.\n"
|
||||
msgstr ""
|
||||
msgstr "/// Rellena `s` a la izquierda hasta `width`.\n"
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "\"{s:>width$}\""
|
||||
msgstr "\"|{:^width$}|\""
|
||||
msgstr "\"{s:>width$}\""
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "\" foo\""
|
||||
msgstr "\"foo\""
|
||||
msgstr "\" foo\""
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "\"foobar\""
|
||||
msgstr "\"foo\""
|
||||
msgstr "\"foobar\""
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "You can now run the test with"
|
||||
msgstr "Ahora puedes generar automáticamente los enlaces:"
|
||||
msgstr "Ahora puedes ejecutar la prueba con"
|
||||
|
||||
#: src/android/testing.md
|
||||
#, fuzzy
|
||||
msgid "The output looks like this:"
|
||||
msgstr "El enfoque general es el siguiente:"
|
||||
msgstr "La salida se ve así:"
|
||||
|
||||
#: src/android/testing.md
|
||||
msgid ""
|
||||
@@ -13748,15 +13739,16 @@ msgid ""
|
||||
"Notice how you only mention the root of the library crate. Tests are found "
|
||||
"recursively in nested modules."
|
||||
msgstr ""
|
||||
"Observa que solo mencionas la raíz del crate de la biblioteca. Las pruebas se "
|
||||
"encuentran de forma recursiva en módulos anidados."
|
||||
|
||||
#: src/android/testing/googletest.md
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"The [GoogleTest](https://docs.rs/googletest/) crate allows for flexible test "
|
||||
"assertions using _matchers_:"
|
||||
msgstr ""
|
||||
"[googletest](https://docs.rs/googletest): biblioteca completa de aserción de "
|
||||
"pruebas en la tradición de GoogleTest para C++."
|
||||
"El crate [GoogleTest](https://docs.rs/googletest/) permite realizar aserciones de "
|
||||
"prueba flexibles utilizando _matchers_:"
|
||||
|
||||
#: src/android/testing/googletest.md
|
||||
msgid "\"baz\""
|
||||
@@ -13804,13 +13796,12 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: src/android/testing/googletest.md
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"A particularly nice feature is that mismatches in multi-line strings are "
|
||||
"shown as a diff:"
|
||||
msgstr ""
|
||||
"Una característica muy interesante es que las discrepancias en las cadenas "
|
||||
"que contienen varias líneas se muestran como un diff:"
|
||||
"Una característica especialmente útil es que las discrepancias en cadenas de "
|
||||
"varias líneas se muestran como un diff:"
|
||||
|
||||
#: src/android/testing/googletest.md
|
||||
msgid ""
|
||||
@@ -13855,7 +13846,6 @@ msgstr ""
|
||||
"podrás hacer simulaciones:"
|
||||
|
||||
#: src/android/testing/mocking.md
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Mockall is the recommended mocking library in Android (AOSP). There are "
|
||||
"other [mocking libraries available on crates.io](https://crates.io/keywords/"
|
||||
@@ -13863,13 +13853,12 @@ msgid ""
|
||||
"libraries work in a similar fashion as Mockall, meaning that they make it "
|
||||
"easy to get a mock implementation of a given trait."
|
||||
msgstr ""
|
||||
"Estos consejos son útiles para Android (AOSP), donde Mockall es la "
|
||||
"biblioteca de simulaciones recomendada. Hay otras [bibliotecas de simulación "
|
||||
"disponibles en crates.io](https://crates.io/keywords/mock), especialmente en "
|
||||
"el área de servicios de simulación de HTTP. Las demás bibliotecas de "
|
||||
"simulación funcionan de forma similar a Mockall, lo que significa que "
|
||||
"facilitan la obtención de una implementación simulada de un trait "
|
||||
"determinado."
|
||||
"Mockall es la biblioteca de simulación recomendada en Android (AOSP). Hay "
|
||||
"otras [bibliotecas de simulación disponibles en crates.io](https://crates.io/keywords/mock), "
|
||||
"particularmente en el área de simulación de servicios HTTP. Las demás "
|
||||
"bibliotecas de simulación funcionan de manera similar a Mockall, lo que "
|
||||
"significa que facilitan la obtención de una implementación simulada de un "
|
||||
"trait determinado."
|
||||
|
||||
#: src/android/testing/mocking.md
|
||||
msgid ""
|
||||
|
6
po/fa.po
6
po/fa.po
@@ -1712,7 +1712,7 @@ msgstr "۴۰ دقیقه"
|
||||
|
||||
#: src/running-the-course/course-structure.md
|
||||
msgid "Day 1 Afternoon (2 hours and 35 minutes, including breaks)"
|
||||
msgstr "روز ۱ بعد از ظهر (۲ ساعت و ۳۵ دقیقه،شامل وقت استراحت)"
|
||||
msgstr "روز ۱ بعد از ظهر (۲ ساعت و ۳۵ دقیقه، شامل وقت استراحت)"
|
||||
|
||||
#: src/running-the-course/course-structure.md src/welcome-day-1-afternoon.md
|
||||
msgid "35 minutes"
|
||||
@@ -1818,7 +1818,7 @@ msgstr ""
|
||||
"شما نیاز دارید که یک نسخه از [مخزن ASOP](https://source.android.com/docs/"
|
||||
"setup/download/downloading) بگیرید, همچنین یک نسخه از [مخزن دوره](https://"
|
||||
"github.com/google/comprehensive-rust) بگیرید و روی همون ماشین در مسیر `src/"
|
||||
"android/`مخزن ASOP قرار دهید. با این کار طمینان حاصل میکنید که سیستم build "
|
||||
"android/`مخزن ASOP قرار دهید. با این کار اطمینان حاصل میکنید که سیستم build "
|
||||
"اندروید فایل های `Android.bp` را در `src/android/` میبینید."
|
||||
|
||||
#: src/running-the-course/course-structure.md
|
||||
@@ -1909,7 +1909,7 @@ msgstr ""
|
||||
|
||||
#: src/running-the-course/course-structure.md
|
||||
msgid "Morning (3 hours and 20 minutes, including breaks)"
|
||||
msgstr "صبح (۳ ساعت و ۲۰ دقیقه، شامل وقت اسراحت)"
|
||||
msgstr "صبح (۳ ساعت و ۲۰ دقیقه، شامل وقت استراحت)"
|
||||
|
||||
#: src/running-the-course/course-structure.md src/pattern-matching.md
|
||||
#: src/std-traits.md src/smart-pointers.md src/lifetimes.md src/iterators.md
|
||||
|
79
po/ko.po
79
po/ko.po
@@ -188,7 +188,7 @@ msgstr "튜플"
|
||||
#: src/SUMMARY.md src/tuples-and-arrays/iteration.md
|
||||
#, fuzzy
|
||||
msgid "Array Iteration"
|
||||
msgstr "배열 반복"
|
||||
msgstr "배열 순회"
|
||||
|
||||
#: src/SUMMARY.md src/tuples-and-arrays/destructuring.md
|
||||
#, fuzzy
|
||||
@@ -216,7 +216,7 @@ msgstr "허상(dangling) 참조"
|
||||
#: src/SUMMARY.md src/references/exercise.md
|
||||
#, fuzzy
|
||||
msgid "Exercise: Geometry"
|
||||
msgstr "연습문제: 도형"
|
||||
msgstr "연습문제: 기하"
|
||||
|
||||
#: src/SUMMARY.md src/user-defined-types.md
|
||||
#, fuzzy
|
||||
@@ -275,7 +275,7 @@ msgstr "흐름 제어"
|
||||
|
||||
#: src/SUMMARY.md src/pattern-matching/exercise.md
|
||||
msgid "Exercise: Expression Evaluation"
|
||||
msgstr "연습문제: 표현식 평가"
|
||||
msgstr "연습문제: 수식 계산"
|
||||
|
||||
#: src/SUMMARY.md src/methods-and-traits.md
|
||||
msgid "Methods and Traits"
|
||||
@@ -312,7 +312,7 @@ msgstr "트레잇 상속하기"
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Exercise: Generic Logger"
|
||||
msgstr "연습문제: 일반 `min`"
|
||||
msgstr "연습문제: 범용 로거"
|
||||
|
||||
#: src/SUMMARY.md src/generics.md
|
||||
msgid "Generics"
|
||||
@@ -343,7 +343,7 @@ msgstr "트레잇 구현하기(`impl Trait`)"
|
||||
#: src/SUMMARY.md src/generics/exercise.md
|
||||
#, fuzzy
|
||||
msgid "Exercise: Generic `min`"
|
||||
msgstr "연습문제: 일반 `min`"
|
||||
msgstr "연습문제: 범용 `min`"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
msgid "Day 2: Afternoon"
|
||||
@@ -352,7 +352,7 @@ msgstr "2일차 오후"
|
||||
#: src/SUMMARY.md src/std-types.md
|
||||
#, fuzzy
|
||||
msgid "Standard Library Types"
|
||||
msgstr "표준 라이브러리"
|
||||
msgstr "표준 라이브러리 타입"
|
||||
|
||||
#: src/SUMMARY.md src/std-types/std.md
|
||||
msgid "Standard Library"
|
||||
@@ -394,7 +394,7 @@ msgstr "연습문제: 카운터"
|
||||
#: src/SUMMARY.md src/std-traits.md
|
||||
#, fuzzy
|
||||
msgid "Standard Library Traits"
|
||||
msgstr "표준 라이브러리"
|
||||
msgstr "표준 라이브러리 트레잇"
|
||||
|
||||
#: src/SUMMARY.md src/std-traits/comparisons.md src/async.md
|
||||
#, fuzzy
|
||||
@@ -430,7 +430,7 @@ msgstr "클로저(Closure)"
|
||||
#: src/SUMMARY.md src/std-traits/exercise.md
|
||||
#, fuzzy
|
||||
msgid "Exercise: ROT13"
|
||||
msgstr "연습문제: 바이너리 트리"
|
||||
msgstr "연습문제: ROT13"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
msgid "Day 3: Morning"
|
||||
@@ -474,7 +474,7 @@ msgstr "Drop"
|
||||
#: src/SUMMARY.md src/memory-management/exercise.md
|
||||
#, fuzzy
|
||||
msgid "Exercise: Builder Type"
|
||||
msgstr "연습문제: 빌드 타입"
|
||||
msgstr "연습문제: Builder 타입"
|
||||
|
||||
#: src/SUMMARY.md src/smart-pointers.md
|
||||
msgid "Smart Pointers"
|
||||
@@ -505,17 +505,17 @@ msgstr "3일차 오후"
|
||||
|
||||
#: src/SUMMARY.md src/borrowing.md
|
||||
msgid "Borrowing"
|
||||
msgstr "빌림"
|
||||
msgstr "대여"
|
||||
|
||||
#: src/SUMMARY.md src/borrowing/shared.md
|
||||
#, fuzzy
|
||||
msgid "Borrowing a Value"
|
||||
msgstr "빌림"
|
||||
msgstr "값 대여"
|
||||
|
||||
#: src/SUMMARY.md src/borrowing/borrowck.md
|
||||
#, fuzzy
|
||||
msgid "Borrow Checking"
|
||||
msgstr "빌림"
|
||||
msgstr "대여 검증"
|
||||
|
||||
#: src/SUMMARY.md src/borrowing/interior-mutability.md
|
||||
#, fuzzy
|
||||
@@ -525,12 +525,12 @@ msgstr "상호운용성"
|
||||
#: src/SUMMARY.md src/borrowing/exercise.md
|
||||
#, fuzzy
|
||||
msgid "Exercise: Health Statistics"
|
||||
msgstr "연습문제: 엘리베이터 이벤트"
|
||||
msgstr "연습문제: 건강검진"
|
||||
|
||||
#: src/SUMMARY.md src/slices-and-lifetimes.md
|
||||
#, fuzzy
|
||||
msgid "Slices and Lifetimes"
|
||||
msgstr "수명"
|
||||
msgstr "슬라이스와 수명"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
@@ -540,7 +540,7 @@ msgstr "슬라이스"
|
||||
#: src/SUMMARY.md src/slices-and-lifetimes/str.md
|
||||
#, fuzzy
|
||||
msgid "String References"
|
||||
msgstr "허상(dangling) 참조"
|
||||
msgstr "문자열 레퍼런스"
|
||||
|
||||
#: src/SUMMARY.md src/slices-and-lifetimes/lifetime-annotations.md
|
||||
#, fuzzy
|
||||
@@ -550,12 +550,12 @@ msgstr "함수 호출에서의 수명"
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Lifetime Elision"
|
||||
msgstr "수명"
|
||||
msgstr "수명 표기의 생략"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Struct Lifetimes"
|
||||
msgstr "수명"
|
||||
msgstr "구조체의 수명"
|
||||
|
||||
#: src/SUMMARY.md src/slices-and-lifetimes/exercise.md
|
||||
#, fuzzy
|
||||
@@ -565,7 +565,7 @@ msgstr "연습문제: Protobuf 파싱"
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Day 4: Morning"
|
||||
msgstr "1일차 오전"
|
||||
msgstr "4일차 오전"
|
||||
|
||||
#: src/SUMMARY.md src/iterators.md
|
||||
msgid "Iterators"
|
||||
@@ -587,7 +587,7 @@ msgstr "FromIterator"
|
||||
#: src/SUMMARY.md src/iterators/exercise.md
|
||||
#, fuzzy
|
||||
msgid "Exercise: Iterator Method Chaining"
|
||||
msgstr "연습문제: 반복자 메서드 체이닝"
|
||||
msgstr "연습문제: Iterator 메서드 체이닝"
|
||||
|
||||
#: src/SUMMARY.md src/modules.md src/modules/modules.md
|
||||
msgid "Modules"
|
||||
@@ -608,7 +608,7 @@ msgstr "`use`, `super`, `self`"
|
||||
#: src/SUMMARY.md src/modules/exercise.md
|
||||
#, fuzzy
|
||||
msgid "Exercise: Modules for a GUI Library"
|
||||
msgstr "연습문제: GUI 라이브러리 모듈"
|
||||
msgstr "연습문제: GUI 라이브러리 모듈 만들기"
|
||||
|
||||
#: src/SUMMARY.md src/testing.md src/chromium/testing.md
|
||||
msgid "Testing"
|
||||
@@ -621,7 +621,7 @@ msgstr "테스트 모듈"
|
||||
#: src/SUMMARY.md src/testing/other.md
|
||||
#, fuzzy
|
||||
msgid "Other Types of Tests"
|
||||
msgstr "다른 프로젝트"
|
||||
msgstr "다른 테스트 프로젝트 타입"
|
||||
|
||||
#: src/SUMMARY.md src/testing/lints.md
|
||||
#, fuzzy
|
||||
@@ -636,7 +636,7 @@ msgstr "룬 알고리즘"
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Day 4: Afternoon"
|
||||
msgstr "1일차 오후"
|
||||
msgstr "4일차 오후"
|
||||
|
||||
#: src/SUMMARY.md src/error-handling.md
|
||||
msgid "Error Handling"
|
||||
@@ -659,7 +659,7 @@ msgstr "묵시적 형변환"
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "`Error` Trait"
|
||||
msgstr "`Error`"
|
||||
msgstr "`Error` 트레잇"
|
||||
|
||||
#: src/SUMMARY.md src/error-handling/thiserror-and-anyhow.md
|
||||
#, fuzzy
|
||||
@@ -741,12 +741,12 @@ msgstr "AIDL 인터페이스"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
msgid "Service API"
|
||||
msgstr ""
|
||||
msgstr "서비스 API"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Service"
|
||||
msgstr "AIDL 서버"
|
||||
msgstr "AIDL 서비스"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
msgid "Server"
|
||||
@@ -767,16 +767,16 @@ msgstr "API 수정"
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Updating Implementations"
|
||||
msgstr "서비스 구현"
|
||||
msgstr "구헌체 업데이트"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "AIDL Types"
|
||||
msgstr "타입"
|
||||
msgstr "AIDL 타입"
|
||||
|
||||
#: src/SUMMARY.md src/android/aidl/types/primitives.md
|
||||
msgid "Primitive Types"
|
||||
msgstr ""
|
||||
msgstr "원시 타입"
|
||||
|
||||
#: src/SUMMARY.md src/android/aidl/types/arrays.md
|
||||
#, fuzzy
|
||||
@@ -832,7 +832,7 @@ msgstr "C++와의 상호운용성"
|
||||
#: src/SUMMARY.md src/android/interoperability/cpp/bridge.md
|
||||
#, fuzzy
|
||||
msgid "The Bridge Module"
|
||||
msgstr "테스트 모듈"
|
||||
msgstr "브리지 모듈"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
msgid "Rust Bridge"
|
||||
@@ -859,12 +859,12 @@ msgstr "공유 Enum"
|
||||
#: src/SUMMARY.md src/android/interoperability/cpp/rust-result.md
|
||||
#, fuzzy
|
||||
msgid "Rust Error Handling"
|
||||
msgstr "오류처리"
|
||||
msgstr "Rust 오류처리"
|
||||
|
||||
#: src/SUMMARY.md src/android/interoperability/cpp/cpp-exception.md
|
||||
#, fuzzy
|
||||
msgid "C++ Error Handling"
|
||||
msgstr "오류처리"
|
||||
msgstr "C++ 오류처리"
|
||||
|
||||
#: src/SUMMARY.md src/android/interoperability/cpp/type-mapping.md
|
||||
msgid "Additional Types"
|
||||
@@ -909,12 +909,12 @@ msgstr "정책"
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Unsafe Code"
|
||||
msgstr "안전하지 않은 러스트"
|
||||
msgstr "안전하지 않은 코드"
|
||||
|
||||
#: src/SUMMARY.md src/chromium/build-rules/depending.md
|
||||
#, fuzzy
|
||||
msgid "Depending on Rust Code from Chromium C++"
|
||||
msgstr "Chromium C++의 Rust 코드에 의존"
|
||||
msgstr "Chromium C++에 의존하는 Rust 코드"
|
||||
|
||||
#: src/SUMMARY.md src/chromium/build-rules/vscode.md
|
||||
#, fuzzy
|
||||
@@ -941,7 +941,7 @@ msgstr ""
|
||||
#: src/SUMMARY.md src/chromium/interoperability-with-cpp.md
|
||||
#, fuzzy
|
||||
msgid "Interoperability with C++"
|
||||
msgstr "C와의 상호운용성"
|
||||
msgstr "C++와의 상호운용성"
|
||||
|
||||
#: src/SUMMARY.md src/chromium/interoperability-with-cpp/example-bindings.md
|
||||
#, fuzzy
|
||||
@@ -955,17 +955,17 @@ msgstr "CXX 제한사항"
|
||||
#: src/SUMMARY.md src/chromium/interoperability-with-cpp/error-handling.md
|
||||
#, fuzzy
|
||||
msgid "CXX Error Handling"
|
||||
msgstr "오류처리"
|
||||
msgstr "CXX에서의 오류처리"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Error Handling: QR Example"
|
||||
msgstr "오류처리"
|
||||
msgstr "오류처리 예제: QR"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
msgid "Error Handling: PNG Example"
|
||||
msgstr "오류처리"
|
||||
msgstr "오류처리 예제: PNG"
|
||||
|
||||
#: src/SUMMARY.md
|
||||
#, fuzzy
|
||||
@@ -1440,7 +1440,7 @@ msgid ""
|
||||
"based browsers. This includes interoperability with C++ and how to include "
|
||||
"third-party crates in Chromium."
|
||||
msgstr ""
|
||||
"[Chromium의 Rust](../chromium.md) 심층 분석은 Chromium 브라우저의 일부로 Rust"
|
||||
"[Chromium의 Rust](chromium.md) 심층 분석은 Chromium 브라우저의 일부로 Rust"
|
||||
"를 사용하는 방법에 관한 반나절 과정입니다. 여기에는 Chromium의 'gn' 빌드 시스"
|
||||
"템에서 Rust를 사용하여 서드 파티 라이브러리(\"crates\")와 C++ 상호 운용성을 "
|
||||
"가져오는 방법이 포함되어 있습니다."
|
||||
@@ -2253,7 +2253,8 @@ msgid ""
|
||||
"Dependencies can also be resolved from alternative [registries](https://doc."
|
||||
"rust-lang.org/cargo/reference/registries.html), git, folders, and more."
|
||||
msgstr ""
|
||||
"의존성은 다양한 [저장소](registries), git 프로젝트, 디렉터리 등에서 제공될 "
|
||||
"의존성은 다양한 [저장소](https://doc."
|
||||
"rust-lang.org/cargo/reference/registries.html), git 프로젝트, 디렉터리 등에서 제공될 "
|
||||
"수 있습니다."
|
||||
|
||||
#: src/cargo/rust-ecosystem.md
|
||||
|
21
po/vi.po
21
po/vi.po
@@ -4785,34 +4785,38 @@ msgstr ""
|
||||
|
||||
#: src/welcome-day-2.md
|
||||
msgid "Welcome to Day 2"
|
||||
msgstr ""
|
||||
msgstr "Chào mừng tới Ngày 2"
|
||||
|
||||
#: src/welcome-day-2.md
|
||||
msgid ""
|
||||
"Now that we have seen a fair amount of Rust, today will focus on Rust's type "
|
||||
"system:"
|
||||
msgstr ""
|
||||
"Chúng ta đã có kiến thức tổng quan về Rust, hôm nay sẽ tập trung vào hệ "
|
||||
"thống kiểu trong Rust:"
|
||||
|
||||
#: src/welcome-day-2.md
|
||||
msgid "Pattern matching: extracting data from structures."
|
||||
msgstr ""
|
||||
msgstr "So khớp mẫu (Pattern matching): trích xuất dữ liệu từ các cấu trúc."
|
||||
|
||||
#: src/welcome-day-2.md
|
||||
msgid "Methods: associating functions with types."
|
||||
msgstr ""
|
||||
msgstr "Phương thức (Methods): liên kết hàm với các kiểu dữ liệu."
|
||||
|
||||
#: src/welcome-day-2.md
|
||||
msgid "Traits: behaviors shared by multiple types."
|
||||
msgstr ""
|
||||
msgstr "Traits: hành vi được chia sẻ bởi nhiều kiểu dữ liệu."
|
||||
|
||||
#: src/welcome-day-2.md
|
||||
msgid "Generics: parameterizing types on other types."
|
||||
msgstr ""
|
||||
msgstr "Generics: tham số hóa các kiểu dữ liệu trên các kiểu khác nhau."
|
||||
|
||||
#: src/welcome-day-2.md
|
||||
msgid ""
|
||||
"Standard library types and traits: a tour of Rust's rich standard library."
|
||||
msgstr ""
|
||||
"Các kiểu thư viện chuẩn và traits: sơ bộ về thư viện chuẩn phong phú của "
|
||||
"Rust."
|
||||
|
||||
#: src/welcome-day-2.md src/welcome-day-4-afternoon.md
|
||||
msgid ""
|
||||
@@ -7113,21 +7117,24 @@ msgstr ""
|
||||
|
||||
#: src/welcome-day-3.md
|
||||
msgid "Welcome to Day 3"
|
||||
msgstr ""
|
||||
msgstr "Chào mừng tới Ngày 3"
|
||||
|
||||
#: src/welcome-day-3.md
|
||||
msgid "Today, we will cover:"
|
||||
msgstr ""
|
||||
msgstr "Chủ đề chúng ta sẽ học hôm nay là:"
|
||||
|
||||
#: src/welcome-day-3.md
|
||||
msgid ""
|
||||
"Memory management, lifetimes, and the borrow checker: how Rust ensures "
|
||||
"memory safety."
|
||||
msgstr ""
|
||||
"Quản lý bộ nhớ, vòng đời (lifetimes), và quá trình kiểm mượn (the borrow "
|
||||
"checker): cách mà Rust đảm bảo được tính an toàn bộ nhớ."
|
||||
|
||||
#: src/welcome-day-3.md
|
||||
msgid "Smart pointers: standard library pointer types."
|
||||
msgstr ""
|
||||
"Con trỏ thông minh (smart pointers): các kiểu con trỏ trong thư viện chuẩn."
|
||||
|
||||
#: src/welcome-day-3.md
|
||||
msgid ""
|
||||
|
@@ -1,4 +1,5 @@
|
||||
# Please use a nightly rustfmt for these settings.
|
||||
unstable_features = true
|
||||
imports_granularity = "module"
|
||||
wrap_comments = true
|
||||
|
||||
|
@@ -108,6 +108,12 @@
|
||||
# Day 2: Afternoon
|
||||
|
||||
- [Welcome](welcome-day-2-afternoon.md)
|
||||
- [Closures](closures.md)
|
||||
- [Closure Syntax](closures/syntax.md)
|
||||
- [Capturing](closures/capturing.md)
|
||||
- [Closure Traits](closures/traits.md)
|
||||
- [Exercise: Log Filter](closures/exercise.md)
|
||||
- [Solution](closures/solution.md)
|
||||
- [Standard Library Types](std-types.md)
|
||||
- [Standard Library](std-types/std.md)
|
||||
- [Documentation](std-types/docs.md)
|
||||
@@ -118,12 +124,6 @@
|
||||
- [`HashMap`](std-types/hashmap.md)
|
||||
- [Exercise: Counter](std-types/exercise.md)
|
||||
- [Solution](std-types/solution.md)
|
||||
- [Closures](closures.md)
|
||||
- [Closure Syntax](closures/syntax.md)
|
||||
- [Capturing](closures/capturing.md)
|
||||
- [Closure Traits](closures/traits.md)
|
||||
- [Exercise: Log Filter](closures/exercise.md)
|
||||
- [Solution](closures/solution.md)
|
||||
- [Standard Library Traits](std-traits.md)
|
||||
- [Comparisons](std-traits/comparisons.md)
|
||||
- [Operators](std-traits/operators.md)
|
||||
@@ -442,6 +442,31 @@
|
||||
- [Drop Guards](idiomatic/leveraging-the-type-system/raii/drop_guards.md)
|
||||
- [Drop Bomb](idiomatic/leveraging-the-type-system/raii/drop_bomb.md)
|
||||
- [Scope Guard](idiomatic/leveraging-the-type-system/raii/scope_guard.md)
|
||||
- [Typestate Pattern](idiomatic/leveraging-the-type-system/typestate-pattern.md)
|
||||
- [Typestate Pattern Example](idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md)
|
||||
- [Beyond Simple Typestate](idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md)
|
||||
- [Typestate Pattern with Generics](idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md)
|
||||
- [Serializer: implement Root](idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md)
|
||||
- [Serializer: implement Struct](idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md)
|
||||
- [Serializer: implement Property](idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md)
|
||||
- [Serializer: Complete implementation](idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md)
|
||||
|
||||
---
|
||||
|
||||
# Unsafe
|
||||
|
||||
- [Welcome](unsafe-deep-dive/welcome.md)
|
||||
- [Setup](unsafe-deep-dive/setup.md)
|
||||
- [Motivations](unsafe-deep-dive/motivations.md)
|
||||
- [Interoperability](unsafe-deep-dive/motivations/interop.md)
|
||||
- [Data Structures](unsafe-deep-dive/motivations/data-structures.md)
|
||||
- [Performance](unsafe-deep-dive/motivations/performance.md)
|
||||
- [Foundations](unsafe-deep-dive/foundations.md)
|
||||
- [What is unsafe?](unsafe-deep-dive/foundations/what-is-unsafe.md)
|
||||
- [When is unsafe used?](unsafe-deep-dive/foundations/when-is-unsafe-used.md)
|
||||
- [Data structures are safe](unsafe-deep-dive/foundations/data-structures-are-safe.md)
|
||||
- [Actions might not be](unsafe-deep-dive/foundations/actions-might-not-be.md)
|
||||
- [Less powerful than it seems](unsafe-deep-dive/foundations/less-powerful.md)
|
||||
|
||||
---
|
||||
|
||||
|
@@ -1,18 +1,16 @@
|
||||
# AIDL
|
||||
|
||||
The
|
||||
[Android Interface Definition Language
|
||||
(AIDL)](https://developer.android.com/guide/components/aidl) is supported in
|
||||
Rust:
|
||||
Rust supports the
|
||||
[Android Interface Definition Language (AIDL)](https://developer.android.com/guide/components/aidl):
|
||||
|
||||
- Rust code can call existing AIDL servers,
|
||||
- Rust code can call existing AIDL servers.
|
||||
- You can create new AIDL servers in Rust.
|
||||
|
||||
<details>
|
||||
|
||||
- AIDL is what enables Android apps to interact with each other.
|
||||
- AIDL enables Android apps to interact with each other.
|
||||
|
||||
- Since Rust is supported as a first-class citizen in this ecosystem, Rust
|
||||
services can be called by any other process on the phone.
|
||||
- Since Rust is a first-class citizen in this ecosystem, other processes on the
|
||||
device can call Rust services.
|
||||
|
||||
</details>
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# Birthday Service Tutorial
|
||||
|
||||
To illustrate how to use Rust with Binder, we're going to walk through the
|
||||
process of creating a Binder interface. We're then going to both implement the
|
||||
described service and write client code that talks to that service.
|
||||
To illustrate using Rust with Binder, we will create a Binder interface. Then,
|
||||
we'll implement the service and write a client that talks to it.
|
||||
|
@@ -1,11 +1,10 @@
|
||||
// ANCHOR: libbirthdayservice
|
||||
rust_library {
|
||||
name: "libbirthdayservice",
|
||||
srcs: ["src/lib.rs"],
|
||||
crate_name: "birthdayservice",
|
||||
srcs: ["src/lib.rs"],
|
||||
rustlibs: [
|
||||
"com.example.birthdayservice-rust",
|
||||
"libbinder_rs",
|
||||
],
|
||||
}
|
||||
// ANCHOR_END: libbirthdayservice
|
||||
@@ -17,7 +16,6 @@ rust_binary {
|
||||
srcs: ["src/server.rs"],
|
||||
rustlibs: [
|
||||
"com.example.birthdayservice-rust",
|
||||
"libbinder_rs",
|
||||
"libbirthdayservice",
|
||||
],
|
||||
prefer_rlib: true, // To avoid dynamic link error.
|
||||
@@ -31,7 +29,6 @@ rust_binary {
|
||||
srcs: ["src/client.rs"],
|
||||
rustlibs: [
|
||||
"com.example.birthdayservice-rust",
|
||||
"libbinder_rs",
|
||||
],
|
||||
prefer_rlib: true, // To avoid dynamic link error.
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# Changing API
|
||||
|
||||
Let us extend the API with more functionality: we want to let clients specify a
|
||||
list of lines for the birthday card:
|
||||
Let's extend the API: we'll let clients specify a list of lines for the birthday
|
||||
card:
|
||||
|
||||
```java
|
||||
package com.example.birthdayservice;
|
||||
|
@@ -16,21 +16,21 @@ _birthday_service/Android.bp_:
|
||||
|
||||
<details>
|
||||
|
||||
The process for taking a user-defined service implementation (in this case the
|
||||
The process for taking a user-defined service implementation (in this case, the
|
||||
`BirthdayService` type, which implements the `IBirthdayService`) and starting it
|
||||
as a Binder service has multiple steps, and may appear more complicated than
|
||||
as a Binder service has multiple steps. This may appear more complicated than
|
||||
students are used to if they've used Binder from C++ or another language.
|
||||
Explain to students why each step is necessary.
|
||||
|
||||
1. Create an instance of your service type (`BirthdayService`).
|
||||
1. Wrap the service object in corresponding `Bn*` type (`BnBirthdayService` in
|
||||
this case). This type is generated by Binder and provides the common Binder
|
||||
functionality that would be provided by the `BnBinder` base class in C++. We
|
||||
don't have inheritance in Rust, so instead we use composition, putting our
|
||||
`BirthdayService` within the generated `BnBinderService`.
|
||||
1. Call `add_service`, giving it a service identifier and your service object
|
||||
2. Wrap the service object in the corresponding `Bn*` type (`BnBirthdayService`
|
||||
in this case). This type is generated by Binder and provides common Binder
|
||||
functionality, similar to the `BnBinder` base class in C++. Since Rust
|
||||
doesn't have inheritance, we use composition, putting our `BirthdayService`
|
||||
within the generated `BnBinderService`.
|
||||
3. Call `add_service`, giving it a service identifier and your service object
|
||||
(the `BnBirthdayService` object in the example).
|
||||
1. Call `join_thread_pool` to add the current thread to Binder's thread pool and
|
||||
4. Call `join_thread_pool` to add the current thread to Binder's thread pool and
|
||||
start listening for connections.
|
||||
|
||||
</details>
|
||||
|
@@ -25,7 +25,7 @@ trait to talk to the service.
|
||||
<details>
|
||||
|
||||
- Point out how the generated function signature, specifically the argument and
|
||||
return types, correspond the interface definition.
|
||||
return types, correspond to the interface definition.
|
||||
- `String` for an argument results in a different Rust type than `String` as a
|
||||
return type.
|
||||
|
||||
|
@@ -25,7 +25,7 @@ _birthday_service/Android.bp_:
|
||||
each of the segments is necessary.
|
||||
- Note that `wishHappyBirthday` and other AIDL IPC methods take `&self` (instead
|
||||
of `&mut self`).
|
||||
- This is necessary because binder responds to incoming requests on a thread
|
||||
- This is necessary because Binder responds to incoming requests on a thread
|
||||
pool, allowing for multiple requests to be processed in parallel. This
|
||||
requires that the service methods only get a shared reference to `self`.
|
||||
- Any state that needs to be modified by the service will have to be put in
|
||||
@@ -33,6 +33,6 @@ _birthday_service/Android.bp_:
|
||||
- The correct approach for managing service state depends heavily on the
|
||||
details of your service.
|
||||
- TODO: What does the `binder::Interface` trait do? Are there methods to
|
||||
override? Where source?
|
||||
override? Where is the source?
|
||||
|
||||
</details>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# Array Types
|
||||
|
||||
The array types (`T[]`, `byte[]`, and `List<T>`) get translated to the
|
||||
The array types (`T[]`, `byte[]`, and `List<T>`) are translated to the
|
||||
appropriate Rust array type depending on how they are used in the function
|
||||
signature:
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# Build Rules
|
||||
|
||||
The Android build system (Soong) supports Rust via a number of modules:
|
||||
The Android build system (Soong) supports Rust through several modules:
|
||||
|
||||
| Module Type | Description |
|
||||
| ----------------- | -------------------------------------------------------------------------------------------------- |
|
||||
@@ -17,13 +17,13 @@ We will look at `rust_binary` and `rust_library` next.
|
||||
|
||||
<details>
|
||||
|
||||
Additional items speaker may mention:
|
||||
Additional items the speaker may mention:
|
||||
|
||||
- Cargo is not optimized for multi-language repos, and also downloads packages
|
||||
from the internet.
|
||||
- Cargo is not optimized for multi-language repositories, and also downloads
|
||||
packages from the internet.
|
||||
|
||||
- For compliance and performance, Android must have crates in-tree. It must also
|
||||
interop with C/C++/Java code. Soong fills that gap.
|
||||
interoperate with C/C++/Java code. Soong fills that gap.
|
||||
|
||||
- Soong has many similarities to [Bazel](https://bazel.build/), which is the
|
||||
open-source variant of Blaze (used in google3).
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# Rust Binaries
|
||||
|
||||
Let us start with a simple application. At the root of an AOSP checkout, create
|
||||
Let's start with a simple application. At the root of an AOSP checkout, create
|
||||
the following files:
|
||||
|
||||
_hello_rust/Android.bp_:
|
||||
@@ -33,7 +33,7 @@ Hello from Rust!
|
||||
that all modules have documentation. Try removing it and see what error you
|
||||
get.
|
||||
|
||||
- Stress that the Rust build rules look like the other Soong rules. This is on
|
||||
purpose to make it as easy to use Rust as C++ or Java.
|
||||
- Stress that the Rust build rules look like the other Soong rules. This is by
|
||||
design, to make using Rust as easy as C++ or Java.
|
||||
|
||||
</details>
|
||||
|
@@ -6,8 +6,8 @@ that you can:
|
||||
- Call Rust functions from other languages.
|
||||
- Call functions written in other languages from Rust.
|
||||
|
||||
When you call functions in a foreign language we say that you're using a
|
||||
_foreign function interface_, also known as FFI.
|
||||
When you call functions in a foreign language, you're using a _foreign function
|
||||
interface_, also known as FFI.
|
||||
|
||||
<details>
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
# With C++
|
||||
|
||||
The [CXX crate][1] makes it possible to do safe interoperability between Rust
|
||||
and C++.
|
||||
The [CXX crate][1] enables safe interoperability between Rust and C++.
|
||||
|
||||
The overall approach looks like this:
|
||||
|
||||
|
@@ -30,9 +30,9 @@ We will look at better options next.
|
||||
- The [`"C"` part][extern-abi] of the `extern` block tells Rust that `abs` can
|
||||
be called using the C [ABI] (application binary interface).
|
||||
|
||||
- The `safe fn abs` part tells that Rust that `abs` is a safe function. By
|
||||
default, extern functions are considered unsafe, but since `abs(x)` is valid
|
||||
for any `x`, we can declare it safe.
|
||||
- The `safe fn abs` part tells Rust that `abs` is a safe function. By default,
|
||||
extern functions are unsafe, but since `abs(x)` can't trigger undefined
|
||||
behavior with any `x`, we can declare it safe.
|
||||
|
||||
</details>
|
||||
|
||||
|
@@ -25,6 +25,6 @@ fn main() {
|
||||
// remains valid. `print_card` doesn't store either pointer to use later
|
||||
// after it returns.
|
||||
unsafe {
|
||||
print_card(&card as *const card);
|
||||
print_card(&card);
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
# A better UART driver
|
||||
|
||||
The PL011 actually has [a bunch more registers][1], and adding offsets to
|
||||
construct pointers to access them is error-prone and hard to read. Plus, some of
|
||||
them are bit fields which would be nice to access in a structured way.
|
||||
The PL011 actually has [more registers][1], and adding offsets to construct
|
||||
pointers to access them is error-prone and hard to read. Additionally, some of
|
||||
them are bit fields, which would be nice to access in a structured way.
|
||||
|
||||
| Offset | Register name | Width |
|
||||
| ------ | ------------- | ----- |
|
||||
@@ -23,7 +23,7 @@ them are bit fields which would be nice to access in a structured way.
|
||||
|
||||
<details>
|
||||
|
||||
- There are also some ID registers which have been omitted for brevity.
|
||||
- There are also some ID registers that have been omitted for brevity.
|
||||
|
||||
</details>
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# Getting Ready to Rust
|
||||
|
||||
Before we can start running Rust code, we need to do some initialisation.
|
||||
Before we can start running Rust code, we need to do some initialization.
|
||||
|
||||
```armasm
|
||||
{{#include examples/src/entry.S:entry}}
|
||||
@@ -12,21 +12,21 @@ This code is in `src/bare-metal/aps/examples/src/entry.S`. It's not necessary to
|
||||
understand this in detail -- the takeaway is that typically some low-level setup
|
||||
is needed to meet Rust's expectations of the system.
|
||||
|
||||
- This is the same as it would be for C: initialising the processor state,
|
||||
- This is the same as it would be for C: initializing the processor state,
|
||||
zeroing the BSS, and setting up the stack pointer.
|
||||
- The BSS (block starting symbol, for historical reasons) is the part of the
|
||||
object file which containing statically allocated variables which are
|
||||
initialised to zero. They are omitted from the image, to avoid wasting space
|
||||
object file that contains statically allocated variables that are
|
||||
initialized to zero. They are omitted from the image, to avoid wasting space
|
||||
on zeroes. The compiler assumes that the loader will take care of zeroing
|
||||
them.
|
||||
- The BSS may already be zeroed, depending on how memory is initialised and the
|
||||
- The BSS may already be zeroed, depending on how memory is initialized and the
|
||||
image is loaded, but we zero it to be sure.
|
||||
- We need to enable the MMU and cache before reading or writing any memory. If
|
||||
we don't:
|
||||
- Unaligned accesses will fault. We build the Rust code for the
|
||||
`aarch64-unknown-none` target which sets `+strict-align` to prevent the
|
||||
compiler generating unaligned accesses, so it should be fine in this case,
|
||||
but this is not necessarily the case in general.
|
||||
`aarch64-unknown-none` target that sets `+strict-align` to prevent the
|
||||
compiler from generating unaligned accesses, so it should be fine in this
|
||||
case, but this is not necessarily the case in general.
|
||||
- If it were running in a VM, this can lead to cache coherency issues. The
|
||||
problem is that the VM is accessing memory directly with the cache disabled,
|
||||
while the host has cacheable aliases to the same memory. Even if the host
|
||||
@@ -34,14 +34,14 @@ is needed to meet Rust's expectations of the system.
|
||||
fills, and then changes from one or the other will get lost when the cache
|
||||
is cleaned or the VM enables the cache. (Cache is keyed by physical address,
|
||||
not VA or IPA.)
|
||||
- For simplicity, we just use a hardcoded pagetable (see `idmap.S`) which
|
||||
- For simplicity, we just use a hardcoded pagetable (see `idmap.S`) that
|
||||
identity maps the first 1 GiB of address space for devices, the next 1 GiB for
|
||||
DRAM, and another 1 GiB higher up for more devices. This matches the memory
|
||||
layout that QEMU uses.
|
||||
- We also set up the exception vector (`vbar_el1`), which we'll see more about
|
||||
later.
|
||||
- All examples this afternoon assume we will be running at exception level 1
|
||||
(EL1). If you need to run at a different exception level you'll need to modify
|
||||
`entry.S` accordingly.
|
||||
(EL1). If you need to run at a different exception level, you'll need to
|
||||
modify `entry.S` accordingly.
|
||||
|
||||
</details>
|
||||
|
12
src/bare-metal/aps/examples/Cargo.lock
generated
12
src/bare-metal/aps/examples/Cargo.lock
generated
@@ -4,9 +4,9 @@ version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aarch64-paging"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3b8f725e9256b2fac2d25e013e22a6a391b8c07e23c4c5eac6e037a78a28801"
|
||||
checksum = "1f02b5bfa3a481fdade5948a994ce93aa6c76f67fc19f3a9b270565cf7dfc657"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"thiserror",
|
||||
@@ -38,9 +38,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "arm-pl011-uart"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff5b0f1e39ec186e409c6fd80bbb83aa00622ca71c9c0561b5571df3b5f5391f"
|
||||
checksum = "8797e113733a36b5fa906c81aefc126d255b88dd1c10a737749aa22ec7736b6a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"embedded-hal-nb",
|
||||
@@ -58,9 +58,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.1"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
|
@@ -7,10 +7,10 @@ edition = "2024"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
aarch64-paging = { version = "0.9.1", default-features = false }
|
||||
aarch64-paging = { version = "0.10.0", default-features = false }
|
||||
aarch64-rt = "0.2.2"
|
||||
arm-pl011-uart = "0.3.1"
|
||||
bitflags = "2.9.1"
|
||||
arm-pl011-uart = "0.3.2"
|
||||
bitflags = "2.9.3"
|
||||
log = "0.4.27"
|
||||
safe-mmio = "0.2.5"
|
||||
smccc = "0.2.0"
|
||||
|
@@ -16,7 +16,7 @@ for all these functions.)
|
||||
- PSCI is the Arm Power State Coordination Interface, a standard set of
|
||||
functions to manage system and CPU power states, among other things. It is
|
||||
implemented by EL3 firmware and hypervisors on many systems.
|
||||
- The `0 => _` syntax means initialise the register to 0 before running the
|
||||
- The `0 => _` syntax means initialize the register to 0 before running the
|
||||
inline assembly code, and ignore its contents afterwards. We need to use
|
||||
`inout` rather than `in` because the call could potentially clobber the
|
||||
contents of the registers.
|
||||
@@ -24,7 +24,7 @@ for all these functions.)
|
||||
because it is called from our entry point in `entry.S`.
|
||||
- Just `#[no_mangle]` would be sufficient but
|
||||
[RFC3325](https://rust-lang.github.io/rfcs/3325-unsafe-attributes.html) uses
|
||||
this notation to draw reviewer attention to attributes which might cause
|
||||
this notation to draw reviewer attention to attributes that might cause
|
||||
undefined behavior if used incorrectly.
|
||||
- `_x0`–`_x3` are the values of registers `x0`–`x3`, which are conventionally
|
||||
used by the bootloader to pass things like a pointer to the device tree.
|
||||
|
@@ -9,7 +9,7 @@ We can do this by implementing the `Log` trait.
|
||||
|
||||
<details>
|
||||
|
||||
- The first unwrap in `log` will succeed because we initialise `LOGGER` before
|
||||
- The first unwrap in `log` will succeed because we initialize `LOGGER` before
|
||||
calling `set_logger`. The second will succeed because `Uart::write_str` always
|
||||
returns `Ok`.
|
||||
|
||||
|
@@ -28,7 +28,7 @@ unsafe {
|
||||
compiler may assume that the value read is the same as the value just
|
||||
written, and not bother actually reading memory.
|
||||
- Some existing crates for volatile access to hardware do hold references, but
|
||||
this is unsound. Whenever a reference exist, the compiler may choose to
|
||||
this is unsound. Whenever a reference exists, the compiler may choose to
|
||||
dereference it.
|
||||
- Use `&raw` to get struct field pointers from a pointer to the struct.
|
||||
- For compatibility with old versions of Rust you can use the [`addr_of!`] macro
|
||||
|
@@ -5,9 +5,9 @@
|
||||
- Supports x86, aarch64 and RISC-V.
|
||||
- Relies on LinuxBoot rather than having many drivers itself.
|
||||
- [Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials)
|
||||
- Initialisation, UART driver, simple bootloader, JTAG, exception levels,
|
||||
- Initialization, UART driver, simple bootloader, JTAG, exception levels,
|
||||
exception handling, page tables.
|
||||
- Some dodginess around cache maintenance and initialisation in Rust, not
|
||||
- Some caveats around cache maintenance and initialization in Rust, not
|
||||
necessarily a good example to copy for production code.
|
||||
- [`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)
|
||||
- Static analysis to determine maximum stack usage.
|
||||
|
@@ -17,14 +17,14 @@ Now let's use the new `Registers` struct in our driver.
|
||||
- These MMIO accesses are generally a wrapper around `read_volatile` and
|
||||
`write_volatile`, though on aarch64 they are instead implemented in assembly
|
||||
to work around a bug where the compiler can emit instructions that prevent
|
||||
MMIO virtualisation.
|
||||
MMIO virtualization.
|
||||
- The `field!` and `field_shared!` macros internally use `&raw mut` and
|
||||
`&raw const` to get pointers to individual fields without creating an
|
||||
intermediate reference, which would be unsound.
|
||||
- `field!` needs a mutable reference to a `UniqueMmioPointer`, and returns a
|
||||
`UniqueMmioPointer` which allows reads with side effects and writes.
|
||||
`UniqueMmioPointer` that allows reads with side effects and writes.
|
||||
- `field_shared!` works with a shared reference to either a `UniqueMmioPointer`
|
||||
or a `SharedMmioPointer`. It returns a `SharedMmioPointer` which only allows
|
||||
or a `SharedMmioPointer`. It returns a `SharedMmioPointer` that only allows
|
||||
pure reads.
|
||||
|
||||
</details>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# safe-mmio
|
||||
|
||||
The [`safe-mmio`] crate provides types to wrap registers which can be read or
|
||||
The [`safe-mmio`] crate provides types to wrap registers that can be read or
|
||||
written safely.
|
||||
|
||||
| | Can't read | Read has no side-effects | Read has side-effects |
|
||||
@@ -23,7 +23,7 @@ written safely.
|
||||
operations; we recommend the `safe-mmio` crate.
|
||||
- The difference between `ReadPure` or `ReadOnly` (and likewise between
|
||||
`ReadPureWrite` and `ReadWrite`) is whether reading a register can have
|
||||
side-effects which change the state of the device. E.g. reading the data
|
||||
side-effects that change the state of the device, e.g., reading the data
|
||||
register pops a byte from the receive FIFO. `ReadPure` means that reads have
|
||||
no side-effects, they are purely reading data.
|
||||
|
||||
|
@@ -12,7 +12,7 @@ for convenience.
|
||||
<details>
|
||||
|
||||
- In this case the board support crate is just providing more useful names, and
|
||||
a bit of initialisation.
|
||||
a bit of initialization.
|
||||
- The crate may also include drivers for some on-board devices outside of the
|
||||
microcontroller itself.
|
||||
- `microbit-v2` includes a simple driver for the LED matrix.
|
||||
|
@@ -8,7 +8,7 @@ microcontroller peripherals:
|
||||
- Delay timers
|
||||
- I2C and SPI buses and devices
|
||||
|
||||
Similar traits for byte streams (e.g. UARTs), CAN buses and RNGs and broken out
|
||||
Similar traits for byte streams (e.g. UARTs), CAN buses and RNGs are broken out
|
||||
into [`embedded-io`], [`embedded-can`] and [`rand_core`] respectively.
|
||||
|
||||
Other crates then implement [drivers] in terms of these traits, e.g. an
|
||||
@@ -16,8 +16,8 @@ accelerometer driver might need an I2C or SPI device instance.
|
||||
|
||||
<details>
|
||||
|
||||
- The traits cover using the peripherals but not initialising or configuring
|
||||
them, as initialisation and configuration is usually highly platform-specific.
|
||||
- The traits cover using the peripherals but not initializing or configuring
|
||||
them, as initialization and configuration is usually highly platform-specific.
|
||||
- There are implementations for many microcontrollers, as well as other
|
||||
platforms such as Linux on Raspberry Pi.
|
||||
- [`embedded-hal-async`] provides async versions of the traits.
|
||||
|
@@ -11,12 +11,11 @@ wrappers for memory-mapped peripherals from
|
||||
<details>
|
||||
|
||||
- SVD (System View Description) files are XML files typically provided by
|
||||
silicon vendors which describe the memory map of the device.
|
||||
- They are organised by peripheral, register, field and value, with names,
|
||||
silicon vendors that describe the memory map of the device.
|
||||
- They are organized by peripheral, register, field and value, with names,
|
||||
descriptions, addresses and so on.
|
||||
- SVD files are often buggy and incomplete, so there are various projects
|
||||
which patch the mistakes, add missing details, and publish the generated
|
||||
crates.
|
||||
- SVD files are often buggy and incomplete, so there are various projects that
|
||||
patch the mistakes, add missing details, and publish the generated crates.
|
||||
- `cortex-m-rt` provides the vector table, among other things.
|
||||
- If you `cargo install cargo-binutils` then you can run
|
||||
`cargo objdump --bin pac -- -d --no-show-raw-insn` to see the resulting
|
||||
|
@@ -21,7 +21,7 @@ in your project directory.
|
||||
a range from SEGGER.
|
||||
- The Debug Access Port is usually either a 5-pin JTAG interface or 2-pin Serial
|
||||
Wire Debug.
|
||||
- probe-rs is a library which you can integrate into your own tools if you want
|
||||
- probe-rs is a library that you can integrate into your own tools if you want
|
||||
to.
|
||||
- The
|
||||
[Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/)
|
||||
@@ -29,6 +29,6 @@ in your project directory.
|
||||
microcontroller.
|
||||
- cargo-embed is a binary built using the probe-rs library.
|
||||
- RTT (Real Time Transfers) is a mechanism to transfer data between the debug
|
||||
host and the target through a number of ringbuffers.
|
||||
host and the target through a number of ring buffers.
|
||||
|
||||
</details>
|
||||
|
@@ -7,12 +7,12 @@
|
||||
<details>
|
||||
|
||||
- Pins don't implement `Copy` or `Clone`, so only one instance of each can
|
||||
exist. Once a pin is moved out of the port struct nobody else can take it.
|
||||
exist. Once a pin is moved out of the port struct, nobody else can take it.
|
||||
- Changing the configuration of a pin consumes the old pin instance, so you
|
||||
can’t keep use the old instance afterwards.
|
||||
- The type of a value indicates the state that it is in: e.g. in this case, the
|
||||
can't use the old instance afterwards.
|
||||
- The type of a value indicates the state it is in: e.g., in this case, the
|
||||
configuration state of a GPIO pin. This encodes the state machine into the
|
||||
type system, and ensures that you don't try to use a pin in a certain way
|
||||
type system and ensures that you don't try to use a pin in a certain way
|
||||
without properly configuring it first. Illegal state transitions are caught at
|
||||
compile time.
|
||||
- You can call `is_high` on an input pin and `set_high` on an output pin, but
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Useful crates
|
||||
|
||||
We'll look at a few crates which solve some common problems in bare-metal
|
||||
We'll look at a few crates that solve some common problems in bare-metal
|
||||
programming.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# `buddy_system_allocator`
|
||||
|
||||
[`buddy_system_allocator`][1] is a crate implementing a basic buddy system
|
||||
[`buddy_system_allocator`][1] is a crate that implements a basic buddy system
|
||||
allocator. It can be used both to implement [`GlobalAlloc`][3] (using
|
||||
[`LockedHeap`][2]) so you can use the standard `alloc` crate (as we saw
|
||||
[before][4]), or for allocating other address space (using
|
||||
|
@@ -25,8 +25,8 @@ fn main() {
|
||||
|
||||
- Be careful to avoid deadlock if you take locks in interrupt handlers.
|
||||
- `spin` also has a ticket lock mutex implementation; equivalents of `RwLock`,
|
||||
`Barrier` and `Once` from `std::sync`; and `Lazy` for lazy initialisation.
|
||||
- The [`once_cell`][2] crate also has some useful types for late initialisation
|
||||
`Barrier` and `Once` from `std::sync`; and `Lazy` for lazy initialization.
|
||||
- The [`once_cell`][2] crate also has some useful types for late initialization
|
||||
with a slightly different approach to `spin::once::Once`.
|
||||
- The Rust Playground includes `spin`, so this example will run fine inline.
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
# `tinyvec`
|
||||
|
||||
Sometimes you want something which can be resized like a `Vec`, but without heap
|
||||
Sometimes you want something that can be resized like a `Vec`, but without heap
|
||||
allocation. [`tinyvec`][1] provides this: a vector backed by an array or slice,
|
||||
which could be statically allocated or on the stack, which keeps track of how
|
||||
which could be statically allocated or on the stack, that keeps track of how
|
||||
many elements are used and panics if you try to use more than are allocated.
|
||||
|
||||
<!-- mdbook-xgettext: skip -->
|
||||
@@ -23,7 +23,7 @@ fn main() {
|
||||
<details>
|
||||
|
||||
- `tinyvec` requires that the element type implement `Default` for
|
||||
initialisation.
|
||||
initialization.
|
||||
- The Rust Playground includes `tinyvec`, so this example will run fine inline.
|
||||
|
||||
</details>
|
||||
|
@@ -65,9 +65,9 @@ fn main() {
|
||||
|
||||
## More to Explore
|
||||
|
||||
- Technically multiple mutable references to a piece of data can exist at the
|
||||
- Technically, multiple mutable references to a piece of data can exist at the
|
||||
same time via re-borrowing. This is what allows you to pass a mutable
|
||||
reference into a function without invaliding the original reference.
|
||||
reference into a function without invalidating the original reference.
|
||||
[This playground example][1] demonstrates that behavior.
|
||||
- Rust uses the exclusive reference constraint to ensure that data races do not
|
||||
occur in multi-threaded code, since only one thread can have mutable access to
|
||||
|
@@ -12,7 +12,7 @@ fits into this training.
|
||||
|
||||
This will give you the Cargo build tool (`cargo`) and the Rust compiler
|
||||
(`rustc`). You will also get `rustup`, a command line utility that you can use
|
||||
to install to different compiler versions.
|
||||
to install different compiler versions.
|
||||
|
||||
After installing Rust, you should configure your editor or IDE to work with
|
||||
Rust. Most editors do this by talking to [rust-analyzer], which provides
|
||||
|
@@ -5,7 +5,7 @@ which can be executed through your browser. This makes the setup much easier and
|
||||
ensures a consistent experience for everyone.
|
||||
|
||||
Installing Cargo is still encouraged: it will make it easier for you to do the
|
||||
exercises. On the last day, we will do a larger exercise which shows you how to
|
||||
exercises. On the last day, we will do a larger exercise that shows you how to
|
||||
work with dependencies and for that you need Cargo.
|
||||
|
||||
The code blocks in this course are fully interactive:
|
||||
@@ -16,8 +16,8 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
You can use <kbd>Ctrl + Enter</kbd> to execute the code when focus is in the
|
||||
text box.
|
||||
You can use <kbd>Ctrl</kbd> + <kbd>Enter</kbd> to execute the code when focus is
|
||||
in the text box.
|
||||
|
||||
<details>
|
||||
|
||||
|
@@ -38,7 +38,7 @@ examples in this training:
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
4. Replace the boiler-plate code in `src/main.rs` with your own code. For
|
||||
4. Replace the boilerplate code in `src/main.rs` with your own code. For
|
||||
example, using the example on the previous page, make `src/main.rs` look like
|
||||
|
||||
```rust
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
The Rust ecosystem consists of a number of tools, of which the main ones are:
|
||||
|
||||
- `rustc`: the Rust compiler which turns `.rs` files into binaries and other
|
||||
- `rustc`: the Rust compiler that turns `.rs` files into binaries and other
|
||||
intermediate formats.
|
||||
|
||||
- `cargo`: the Rust dependency manager and build tool. Cargo knows how to
|
||||
|
@@ -9,6 +9,6 @@ Rust is supported for third-party libraries in Chromium, with first-party glue
|
||||
code to connect between Rust and existing Chromium C++ code.
|
||||
|
||||
> Today, we'll call into Rust to do something silly with strings. If you've got
|
||||
> a corner of the code where you're displaying a UTF8 string to the user, feel
|
||||
> a corner of the code where you're displaying a UTF-8 string to the user, feel
|
||||
> free to follow this recipe in your part of the codebase instead of the exact
|
||||
> part we talk about.
|
||||
|
@@ -11,7 +11,7 @@ Please also add an `OWNERS` file in the latter location.
|
||||
You should land all this, along with your `Cargo.toml` and `gnrt_config.toml`
|
||||
changes, into the Chromium repo.
|
||||
|
||||
**Important**: you need to use `git add -f` because otherwise `.gitignore` files
|
||||
**Important:** you need to use `git add -f` because otherwise `.gitignore` files
|
||||
may result in some files being skipped.
|
||||
|
||||
As you do so, you might find presubmit checks fail because of non-inclusive
|
||||
|
@@ -60,8 +60,8 @@ may offer an advantage"):
|
||||
|
||||
- Perhaps surprisingly, Rust is becoming increasingly popular in the industry
|
||||
for writing command line tools. The breadth and ergonomics of libraries is
|
||||
comparable to Python, while being more robust (thanks to the rich
|
||||
typesystem) and running faster (as a compiled, rather than interpreted
|
||||
comparable to Python, while being more robust (thanks to the rich type
|
||||
system) and running faster (as a compiled, rather than interpreted
|
||||
language).
|
||||
- Participating in the Rust ecosystem requires using standard Rust tools like
|
||||
Cargo. Libraries that want to get external contributions, and want to be
|
||||
|
@@ -40,7 +40,7 @@ following benefits:
|
||||
memory-safety risks.
|
||||
- `rust::String` and `CxxString` types understand and maintain differences in
|
||||
string representation across the languages (e.g. `rust::String::lossy` can
|
||||
build a Rust string from non-UTF8 input and `rust::String::c_str` can
|
||||
build a Rust string from non-UTF-8 input and `rust::String::c_str` can
|
||||
NUL-terminate a string).
|
||||
|
||||
</details>
|
||||
|
@@ -20,7 +20,7 @@ Point out:
|
||||
- Calls from C++ to Rust, and Rust types (in the top part)
|
||||
- Calls from Rust to C++, and C++ types (in the bottom part)
|
||||
|
||||
**Common misconception**: It _looks_ like a C++ header is being parsed by Rust,
|
||||
**Common misconception:** It _looks_ like a C++ header is being parsed by Rust,
|
||||
but this is misleading. This header is never interpreted by Rust, but simply
|
||||
`#include`d in the generated C++ code for the benefit of C++ compilers.
|
||||
|
||||
|
@@ -22,7 +22,7 @@ It's also recommended that you have Visual Studio code installed.
|
||||
|
||||
# About the exercises
|
||||
|
||||
This part of the course has a series of exercises which build on each other.
|
||||
This part of the course has a series of exercises that build on each other.
|
||||
We'll be doing them spread throughout the course instead of just at the end. If
|
||||
you don't have time to complete a certain part, don't worry: you can catch up in
|
||||
the next slot.
|
||||
|
@@ -44,9 +44,9 @@ used:
|
||||
the C++ and the Rust implementation (parameterizing the tests so they enable
|
||||
or disable Rust using a `ScopedFeatureList`).
|
||||
|
||||
- Hypothetical/WIP PNG integration may need to implement memory-safe
|
||||
implementation of pixel transformations that are provided by `libpng` but
|
||||
missing in the `png` crate - e.g. RGBA => BGRA, or gamma correction. Such
|
||||
functionality may benefit from separate tests authored in Rust.
|
||||
- Hypothetical/WIP PNG integration may need memory-safe implementations of pixel
|
||||
transformations that are provided by `libpng` but missing in the `png` crate -
|
||||
e.g. RGBA => BGRA, or gamma correction. Such functionality may benefit from
|
||||
separate tests authored in Rust.
|
||||
|
||||
</details>
|
||||
|
@@ -4,8 +4,8 @@ minutes: 10
|
||||
|
||||
# Exercise: Log Filter
|
||||
|
||||
Building on the generic logger from this morning, implement a `Filter` which
|
||||
uses a closure to filter log messages, sending those which pass the filtering
|
||||
Building on the generic logger from this morning, implement a `Filter` that uses
|
||||
a closure to filter log messages, sending those that pass the filtering
|
||||
predicate to an inner logger.
|
||||
|
||||
```rust,compile_fail,editable
|
||||
|
@@ -4,7 +4,7 @@ minutes: 10
|
||||
|
||||
# Closure traits
|
||||
|
||||
Closures or lambda expressions have types which cannot be named. However, they
|
||||
Closures or lambda expressions have types that cannot be named. However, they
|
||||
implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),
|
||||
[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and
|
||||
[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:
|
||||
@@ -67,7 +67,7 @@ can (i.e. you call it once), or `FnMut` else, and last `Fn`. This allows the
|
||||
most flexibility for the caller.
|
||||
|
||||
In contrast, when you have a closure, the most flexible you can have is `Fn`
|
||||
(which can be passed to a consumer of any of the 3 closure traits), then
|
||||
(which can be passed to a consumer of any of the three closure traits), then
|
||||
`FnMut`, and lastly `FnOnce`.
|
||||
|
||||
The compiler also infers `Copy` (e.g. for `add_suffix`) and `Clone` (e.g.
|
||||
|
@@ -6,5 +6,5 @@ edition = "2024"
|
||||
[dependencies]
|
||||
futures-util = { version = "0.3.31", features = ["sink"] }
|
||||
http = "1.3.1"
|
||||
tokio = { version = "1.45.1", features = ["full"] }
|
||||
tokio-websockets = { version = "0.11.4", features = ["client", "fastrand", "server", "sha1_smol"] }
|
||||
tokio = { version = "1.47.1", features = ["full"] }
|
||||
tokio-websockets = { version = "0.12.1", features = ["client", "fastrand", "server", "sha1_smol"] }
|
||||
|
@@ -41,7 +41,7 @@ async fn main() -> Result<(), tokio_websockets::Error> {
|
||||
println!("From server: {}", text);
|
||||
}
|
||||
},
|
||||
Some(Err(err)) => return Err(err.into()),
|
||||
Some(Err(err)) => return Err(err),
|
||||
None => return Ok(()),
|
||||
}
|
||||
}
|
||||
|
@@ -11,8 +11,6 @@ not have a "built-in" runtime, but several options are available:
|
||||
- [Tokio](https://tokio.rs/): performant, with a well-developed ecosystem of
|
||||
functionality like [Hyper](https://hyper.rs/) for HTTP or
|
||||
[Tonic](https://github.com/hyperium/tonic) for gRPC.
|
||||
- [async-std](https://async.rs/): aims to be a "std for async", and includes a
|
||||
basic runtime in `async::task`.
|
||||
- [smol](https://docs.rs/smol/latest/smol/): simple and lightweight
|
||||
|
||||
Several larger applications have their own runtimes. For example,
|
||||
|
@@ -33,9 +33,9 @@ fn two_d10(modifier: u32) -> TwoD10 {
|
||||
enum TwoD10 {
|
||||
// Function has not begun yet.
|
||||
Init { modifier: u32 },
|
||||
// Waitig for first `.await` to complete.
|
||||
// Waiting for first `.await` to complete.
|
||||
FirstRoll { modifier: u32, fut: RollD10Future },
|
||||
// Waitig for second `.await` to complete.
|
||||
// Waiting for second `.await` to complete.
|
||||
SecondRoll { modifier: u32, first_roll: u32, fut: RollD10Future },
|
||||
}
|
||||
|
||||
|
@@ -13,9 +13,9 @@ name = "link-checker"
|
||||
path = "link-checker.rs"
|
||||
|
||||
[dependencies]
|
||||
reqwest = { version = "0.12.21", features = ["blocking"] }
|
||||
scraper = "0.23.1"
|
||||
thiserror = "2.0.12"
|
||||
reqwest = { version = "0.12.23", features = ["blocking"] }
|
||||
scraper = "0.24.0"
|
||||
thiserror = "2.0.16"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.20.0"
|
||||
tempfile = "3.21.0"
|
||||
|
@@ -4,9 +4,9 @@ minutes: 5
|
||||
|
||||
# Blocks and Scopes
|
||||
|
||||
A block in Rust contains a sequence of expressions, enclosed by braces `{}`.
|
||||
Each block has a value and a type, which are those of the last expression of the
|
||||
block:
|
||||
- A block in Rust contains a sequence of expressions, enclosed by braces `{}`.
|
||||
- The final expression of a block determines the value and type of the whole
|
||||
block.
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
|
@@ -30,7 +30,7 @@ fn main() {
|
||||
|
||||
<details>
|
||||
|
||||
Note that `loop` is the only looping construct which can return a non-trivial
|
||||
Note that `loop` is the only looping construct that can return a non-trivial
|
||||
value. This is because it's guaranteed to only return at a `break` statement
|
||||
(unlike `while` and `for` loops, which can also return when the condition
|
||||
fails).
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# Labels
|
||||
|
||||
Both `continue` and `break` can optionally take a label argument which is used
|
||||
to break out of nested loops:
|
||||
Both `continue` and `break` can optionally take a label argument that is used to
|
||||
break out of nested loops:
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
|
@@ -22,7 +22,7 @@ For example, beginning with _n<sub>1</sub>_ = 3:
|
||||
- 2 is even, so _n<sub>8</sub>_ = 1; and
|
||||
- the sequence terminates.
|
||||
|
||||
Write a function to calculate the length of the collatz sequence for a given
|
||||
Write a function to calculate the length of the Collatz sequence for a given
|
||||
initial `n`.
|
||||
|
||||
```rust,editable,should_panic
|
||||
|
@@ -19,6 +19,6 @@ fn main() {
|
||||
<details>
|
||||
|
||||
- The `loop` statement works like a `while true` loop. Use it for things like
|
||||
servers which will serve connections forever.
|
||||
servers that will serve connections forever.
|
||||
|
||||
</details>
|
||||
|
@@ -59,7 +59,7 @@ fn main() {
|
||||
## More to Explore
|
||||
|
||||
- To further motivate the usage of `match`, you can compare the examples to
|
||||
their equivalents written with `if`. In the second case matching on a `bool`
|
||||
their equivalents written with `if`. In the second case, matching on a `bool`,
|
||||
an `if {} else {}` block is pretty similar. But in the first example that
|
||||
checks multiple cases, a `match` expression can be more concise than
|
||||
`if {} else if {} else if {} else`.
|
||||
|
@@ -3,3 +3,12 @@
|
||||
```rust,editable
|
||||
{{#include exercise.rs:solution}}
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
- Note that the argument `n` is marked as `mut`, allowing you to change the
|
||||
value of `n` in the function. Like variables, function arguments are immutable
|
||||
by default and you must add `mut` if you want to modify their value. This does
|
||||
not affect how the function is called or how the argument is passed in.
|
||||
|
||||
</details>
|
||||
|
@@ -4,9 +4,7 @@ minutes: 3
|
||||
|
||||
# Panics
|
||||
|
||||
Rust handles fatal errors with a "panic".
|
||||
|
||||
Rust will trigger a panic if a fatal error happens at runtime:
|
||||
In case of a fatal runtime error, Rust triggers a "panic":
|
||||
|
||||
```rust,editable,should_panic
|
||||
fn main() {
|
||||
@@ -17,8 +15,8 @@ fn main() {
|
||||
|
||||
- Panics are for unrecoverable and unexpected errors.
|
||||
- Panics are symptoms of bugs in the program.
|
||||
- Runtime failures like failed bounds checks can panic
|
||||
- Assertions (such as `assert!`) panic on failure
|
||||
- Runtime failures like failed bounds checks can panic.
|
||||
- Assertions (such as `assert!`) panic on failure.
|
||||
- Purpose-specific panics can use the `panic!` macro.
|
||||
- A panic will "unwind" the stack, dropping values just as if the functions had
|
||||
returned.
|
||||
|
28
src/exercises/bare-metal/rtc/Cargo.lock
generated
28
src/exercises/bare-metal/rtc/Cargo.lock
generated
@@ -4,9 +4,9 @@ version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aarch64-paging"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3b8f725e9256b2fac2d25e013e22a6a391b8c07e23c4c5eac6e037a78a28801"
|
||||
checksum = "1f02b5bfa3a481fdade5948a994ce93aa6c76f67fc19f3a9b270565cf7dfc657"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"thiserror",
|
||||
@@ -14,18 +14,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aarch64-rt"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8069db67616de3ec8d024aa717f447a6995f159a3b46b4379d600a6224640c03"
|
||||
checksum = "683c4295f0608c531130ed6daf301785844c1f71eb126eb56343838968e728c5"
|
||||
dependencies = [
|
||||
"smccc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arm-gic"
|
||||
version = "0.4.0"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd58684ee8041735b64d9e731b18c5515397ee4487f56f7cb9a409c8cbd17839"
|
||||
checksum = "6bfdb03424c95b58315a4cb0ff4ca919568a5a28ae5ba960a1ad92c9ccaf49b9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"safe-mmio",
|
||||
@@ -35,9 +35,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "arm-pl011-uart"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff5b0f1e39ec186e409c6fd80bbb83aa00622ca71c9c0561b5571df3b5f5391f"
|
||||
checksum = "8797e113733a36b5fa906c81aefc126d255b88dd1c10a737749aa22ec7736b6a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"embedded-hal-nb",
|
||||
@@ -55,9 +55,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.1"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
@@ -202,18 +202,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.12"
|
||||
version = "2.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.12"
|
||||
version = "2.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@@ -7,11 +7,11 @@ edition = "2024"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
aarch64-paging = { version = "0.9.1", default-features = false }
|
||||
aarch64-rt = "0.2.1"
|
||||
arm-gic = "0.4.0"
|
||||
arm-pl011-uart = "0.3.1"
|
||||
bitflags = "2.9.1"
|
||||
aarch64-paging = { version = "0.10.0", default-features = false }
|
||||
aarch64-rt = "0.2.2"
|
||||
arm-gic = "0.6.1"
|
||||
arm-pl011-uart = "0.3.2"
|
||||
bitflags = "2.9.3"
|
||||
chrono = { version = "0.4.41", default-features = false }
|
||||
log = "0.4.27"
|
||||
safe-mmio = "0.2.5"
|
||||
|
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use arm_gic::gicv3::GicV3;
|
||||
use arm_gic::gicv3::{GicV3, InterruptGroup};
|
||||
use log::{error, info, trace};
|
||||
use smccc::Hvc;
|
||||
use smccc::psci::system_off;
|
||||
@@ -28,8 +28,8 @@ extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn irq_current(_elr: u64, _spsr: u64) {
|
||||
trace!("irq_current");
|
||||
let intid =
|
||||
GicV3::get_and_acknowledge_interrupt().expect("No pending interrupt");
|
||||
let intid = GicV3::get_and_acknowledge_interrupt(InterruptGroup::Group1)
|
||||
.expect("No pending interrupt");
|
||||
info!("IRQ {intid:?}");
|
||||
}
|
||||
|
||||
|
@@ -33,8 +33,8 @@ should have created Chrome for pixies!
|
||||
<details>
|
||||
Students will likely need some hints here. Hints include:
|
||||
|
||||
- UTF16 vs UTF8. Students should be aware that Rust strings are always UTF8, and
|
||||
will probably decide that it's better to do the conversion on the C++ side
|
||||
- UTF-16 vs UTF-8. Students should be aware that Rust strings are always UTF-8,
|
||||
and will probably decide that it's better to do the conversion on the C++ side
|
||||
using `base::UTF16ToUTF8` and back again.
|
||||
- If students decide to do the conversion on the Rust side, they'll need to
|
||||
consider [`String::from_utf16`][1], consider error handling, and consider
|
||||
|
@@ -11,7 +11,7 @@ pub extern "C" fn hello_from_rust() {
|
||||
}
|
||||
```
|
||||
|
||||
**Important**: note that `no_mangle` here is considered a type of unsafety by
|
||||
**Important:** note that `no_mangle` here is considered a type of unsafety by
|
||||
the Rust compiler, so you'll need to allow unsafe code in your `gn` target.
|
||||
|
||||
Add this new Rust target as a dependency of `//ui/base:base`. Declare this
|
||||
|
@@ -60,7 +60,7 @@ fn main() {
|
||||
instance of the function for each different type that the generic is
|
||||
instantiated with. This means that calling a trait method from within a
|
||||
generic function still uses static dispatch, as the compiler has full type
|
||||
information and can resolve which type's trait implementation to use.
|
||||
information and can resolve that type's trait implementation to use.
|
||||
|
||||
- When using `dyn Trait`, it instead uses dynamic dispatch through a
|
||||
[virtual method table][vtable] (vtable). This means that there's a single
|
||||
|
@@ -44,7 +44,7 @@ fn main() {
|
||||
|
||||
<details>
|
||||
|
||||
- _Q:_ Why `L` is specified twice in `impl<L: Logger> .. VerbosityFilter<L>`?
|
||||
- _Q:_ Why is `L` specified twice in `impl<L: Logger> .. VerbosityFilter<L>`?
|
||||
Isn't that redundant?
|
||||
- This is because it is a generic implementation section for generic type.
|
||||
They are independently generic.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
---
|
||||
Minutes: 5
|
||||
minutes: 5
|
||||
---
|
||||
|
||||
# Generic Traits
|
||||
|
@@ -30,7 +30,7 @@ fn main() {
|
||||
|
||||
<details>
|
||||
|
||||
`impl Trait` allows you to work with types which you cannot name. The meaning of
|
||||
`impl Trait` allows you to work with types that you cannot name. The meaning of
|
||||
`impl Trait` is a bit different in the different positions.
|
||||
|
||||
- For a parameter, `impl Trait` is like an anonymous generic parameter with a
|
||||
|
150
src/glossary.md
150
src/glossary.md
@@ -31,7 +31,8 @@ h1#glossary ~ ul > li:first-line {
|
||||
- allocate:\
|
||||
Dynamic memory allocation on [the heap](memory-management/review.md).
|
||||
- argument:\
|
||||
Information that is passed into a function or method.
|
||||
Information that is passed into a [function](control-flow-basics/functions.md)
|
||||
or method.
|
||||
- associated type:\
|
||||
A type associated with a specific trait. Useful for defining the relationship
|
||||
between types.
|
||||
@@ -43,165 +44,192 @@ h1#glossary ~ ul > li:first-line {
|
||||
- borrow:\
|
||||
See [Borrowing](borrowing/shared.md).
|
||||
- borrow checker:\
|
||||
The part of the Rust compiler which checks that all borrows are valid.
|
||||
The part of the Rust compiler which checks that all
|
||||
[borrows](borrowing/borrowck.md) are valid.
|
||||
- brace:\
|
||||
`{` and `}`. Also called _curly brace_, they delimit _blocks_.
|
||||
`{` and `}`. Also called _curly brace_, they delimit
|
||||
[_blocks_](control-flow-basics/blocks-and-scopes.md).
|
||||
- build:\
|
||||
The process of converting source code into executable code or a usable
|
||||
program.
|
||||
program. See [Running Code Locally with Cargo](cargo/running-locally.md).
|
||||
- call:\
|
||||
To invoke or execute a function or method.
|
||||
To invoke or execute a [function or method](control-flow-basics/functions.md).
|
||||
- channel:\
|
||||
Used to safely pass messages [between threads](concurrency/channels.md).
|
||||
- Comprehensive Rust 🦀:\
|
||||
The courses here are jointly called Comprehensive Rust 🦀.
|
||||
- concurrency:\
|
||||
The execution of multiple tasks or processes at the same time.
|
||||
The execution of multiple tasks or processes at the same time. See
|
||||
[Welcome to Concurrency in Rust](concurrency/welcome.md).
|
||||
- Concurrency in Rust:\
|
||||
See [Concurrency in Rust](concurrency/welcome.md).
|
||||
- constant:\
|
||||
A value that does not change during the execution of a program.
|
||||
A value that does not change during the execution of a program. See
|
||||
[const](user-defined-types/const.md).
|
||||
- control flow:\
|
||||
The order in which the individual statements or instructions are executed in a
|
||||
program.
|
||||
program. See [Control Flow Basics](control-flow-basics.md).
|
||||
- crash:\
|
||||
An unexpected and unhandled failure or termination of a program.
|
||||
An unexpected and unhandled failure or termination of a program. See
|
||||
[panic](error-handling/panics.md).
|
||||
- enumeration:\
|
||||
A data type that holds one of several named constants, possibly with an
|
||||
associated tuple or struct.
|
||||
associated tuple or struct. See [enum](user-defined-types/enums.md).
|
||||
- error:\
|
||||
An unexpected condition or result that deviates from the expected behavior.
|
||||
See [Error Handling](error-handling.md).
|
||||
- error handling:\
|
||||
The process of managing and responding to errors that occur during program
|
||||
execution.
|
||||
The process of managing and responding to [errors](error-handling.md) that
|
||||
occur during program execution.
|
||||
- exercise:\
|
||||
A task or problem designed to practice and test programming skills.
|
||||
- function:\
|
||||
A reusable block of code that performs a specific task.
|
||||
A reusable block of code that performs a specific task. See
|
||||
[Functions](control-flow-basics/functions.md).
|
||||
- garbage collector:\
|
||||
A mechanism that automatically frees up memory occupied by objects that are no
|
||||
longer in use.
|
||||
longer in use. See
|
||||
[Approaches to Memory Management](memory-management/approaches.md).
|
||||
- generics:\
|
||||
A feature that allows writing code with placeholders for types, enabling code
|
||||
reuse with different data types.
|
||||
reuse with different data types. See [Generics](generics.md).
|
||||
- immutable:\
|
||||
Unable to be changed after creation.
|
||||
Unable to be changed after creation. See
|
||||
[Variables](types-and-values/variables.md).
|
||||
- integration test:\
|
||||
A type of test that verifies the interactions between different parts or
|
||||
components of a system.
|
||||
components of a system. See [Other Types of Tests](testing/other.md).
|
||||
- keyword:\
|
||||
A reserved word in a programming language that has a specific meaning and
|
||||
cannot be used as an identifier.
|
||||
- library:\
|
||||
A collection of precompiled routines or code that can be used by programs.
|
||||
A collection of precompiled routines or code that can be used by programs. See
|
||||
[Modules](modules.md).
|
||||
- macro:\
|
||||
Rust macros can be recognized by a `!` in the name. Macros are used when
|
||||
normal functions are not enough. A typical example is `format!`, which takes a
|
||||
variable number of arguments, which isn't supported by Rust functions.
|
||||
Rust [macros](control-flow-basics/macros.md) can be recognized by a `!` in the
|
||||
name. Macros are used when normal functions are not enough. A typical example
|
||||
is `format!`, which takes a variable number of arguments, which isn't
|
||||
supported by Rust functions.
|
||||
- `main` function:\
|
||||
Rust programs start executing with the `main` function.
|
||||
Rust programs start executing with the
|
||||
[`main` function](types-and-values/hello-world.md).
|
||||
- match:\
|
||||
A control flow construct in Rust that allows for pattern matching on the value
|
||||
of an expression.
|
||||
A control flow construct in Rust that allows for
|
||||
[pattern matching](pattern-matching.md) on the value of an expression.
|
||||
- memory leak:\
|
||||
A situation where a program fails to release memory that is no longer needed,
|
||||
leading to a gradual increase in memory usage.
|
||||
leading to a gradual increase in memory usage. See
|
||||
[Approaches to Memory Management](memory-management/approaches.md).
|
||||
- method:\
|
||||
A function associated with an object or a type in Rust.
|
||||
A function associated with an object or a type in Rust. See
|
||||
[Methods](methods-and-traits/methods.md).
|
||||
- module:\
|
||||
A namespace that contains definitions, such as functions, types, or traits, to
|
||||
organize code in Rust.
|
||||
organize code in Rust. See [Modules](modules.md).
|
||||
- move:\
|
||||
The transfer of ownership of a value from one variable to another in Rust.
|
||||
The transfer of ownership of a value from one variable to another in Rust. See
|
||||
[Move Semantics](memory-management/move.md).
|
||||
- mutable:\
|
||||
A property in Rust that allows variables to be modified after they have been
|
||||
declared.
|
||||
A property in Rust that allows [variables](types-and-values/variables.md) to
|
||||
be modified after they have been declared.
|
||||
- ownership:\
|
||||
The concept in Rust that defines which part of the code is responsible for
|
||||
managing the memory associated with a value.
|
||||
managing the memory associated with a value. See
|
||||
[Ownership](memory-management/ownership.md).
|
||||
- panic:\
|
||||
An unrecoverable error condition in Rust that results in the termination of
|
||||
the program.
|
||||
the program. See [Panics](error-handling/panics.md).
|
||||
- parameter:\
|
||||
A value that is passed into a function or method when it is called.
|
||||
A value that is passed into a
|
||||
[function or method](control-flow-basics/functions.md) when it is called.
|
||||
- pattern:\
|
||||
A combination of values, literals, or structures that can be matched against
|
||||
an expression in Rust.
|
||||
an expression in Rust. See [Pattern Matching](pattern-matching.md).
|
||||
- payload:\
|
||||
The data or information carried by a message, event, or data structure.
|
||||
- program:\
|
||||
A set of instructions that a computer can execute to perform a specific task
|
||||
or solve a particular problem.
|
||||
or solve a particular problem. See
|
||||
[Hello, World](types-and-values/hello-world.md).
|
||||
- programming language:\
|
||||
A formal system used to communicate instructions to a computer, such as Rust.
|
||||
A formal system used to communicate instructions to a computer, such as
|
||||
[Rust](hello-world/what-is-rust.md).
|
||||
- receiver:\
|
||||
The first parameter in a Rust method that represents the instance on which the
|
||||
method is called.
|
||||
The first parameter in a Rust [method](methods-and-traits/methods.md) that
|
||||
represents the instance on which the method is called.
|
||||
- reference counting:\
|
||||
A memory management technique in which the number of references to an object
|
||||
is tracked, and the object is deallocated when the count reaches zero.
|
||||
is tracked, and the object is deallocated when the count reaches zero. See
|
||||
[Rc](smart-pointers/rc.md).
|
||||
- return:\
|
||||
A keyword in Rust used to indicate the value to be returned from a function.
|
||||
A keyword in Rust used to indicate the value to be returned from a
|
||||
[function](control-flow-basics/functions.md).
|
||||
- Rust:\
|
||||
A systems programming language that focuses on safety, performance, and
|
||||
concurrency.
|
||||
concurrency. See [What is Rust?](hello-world/what-is-rust.md).
|
||||
- Rust Fundamentals:\
|
||||
Days 1 to 4 of this course.
|
||||
Days 1 to 4 of this course. See [Welcome to Day 1](welcome-day-1.md).
|
||||
- Rust in Android:\
|
||||
See [Rust in Android](android.md).
|
||||
- Rust in Chromium:\
|
||||
See [Rust in Chromium](chromium.md).
|
||||
- safe:\
|
||||
Refers to code that adheres to Rust's ownership and borrowing rules,
|
||||
preventing memory-related errors.
|
||||
preventing memory-related errors. See [Unsafe Rust](unsafe-rust.md).
|
||||
- scope:\
|
||||
The region of a program where a variable is valid and can be used.
|
||||
The region of a program where a variable is valid and can be used. See
|
||||
[Blocks and Scopes](control-flow-basics/blocks-and-scopes.md).
|
||||
- standard library:\
|
||||
A collection of modules providing essential functionality in Rust.
|
||||
A collection of modules providing essential functionality in Rust. See
|
||||
[Standard Library](std-types/std.md).
|
||||
- static:\
|
||||
A keyword in Rust used to define static variables or items with a `'static`
|
||||
lifetime.
|
||||
lifetime. See [static](user-defined-types/static.md).
|
||||
- string:\
|
||||
A data type storing textual data. See [Strings](references/strings.html) for
|
||||
more.
|
||||
A data type storing textual data. See [Strings](references/strings.md).
|
||||
- struct:\
|
||||
A composite data type in Rust that groups together variables of different
|
||||
types under a single name.
|
||||
types under a single name. See [Structs](user-defined-types/named-structs.md).
|
||||
- test:\
|
||||
A Rust module containing functions that test the correctness of other
|
||||
functions.
|
||||
A function that tests the correctness of other code. Rust has a built-in test
|
||||
runner. See [Testing](testing.md).
|
||||
- thread:\
|
||||
A separate sequence of execution in a program, allowing concurrent execution.
|
||||
See [Threads](concurrency/threads.md).
|
||||
- thread safety:\
|
||||
The property of a program that ensures correct behavior in a multithreaded
|
||||
environment.
|
||||
environment. See [Send and Sync](concurrency/send-sync.md).
|
||||
- trait:\
|
||||
A collection of methods defined for an unknown type, providing a way to
|
||||
achieve polymorphism in Rust.
|
||||
achieve polymorphism in Rust. See [Traits](methods-and-traits/traits.md).
|
||||
- trait bound:\
|
||||
An abstraction where you can require types to implement some traits of your
|
||||
interest.
|
||||
interest. See [Trait Bounds](generics/trait-bounds.md).
|
||||
- tuple:\
|
||||
A composite data type that contains variables of different types. Tuple fields
|
||||
have no names, and are accessed by their ordinal numbers.
|
||||
have no names, and are accessed by their ordinal numbers. See
|
||||
[Tuples](tuples-and-arrays/tuples.md).
|
||||
- type:\
|
||||
A classification that specifies which operations can be performed on values of
|
||||
a particular kind in Rust.
|
||||
a particular kind in Rust. See [Types and Values](types-and-values.md).
|
||||
- type inference:\
|
||||
The ability of the Rust compiler to deduce the type of a variable or
|
||||
expression.
|
||||
expression. See [Type Inference](types-and-values/inference.md).
|
||||
- undefined behavior:\
|
||||
Actions or conditions in Rust that have no specified result, often leading to
|
||||
unpredictable program behavior.
|
||||
unpredictable program behavior. See [Unsafe Rust](unsafe-rust.md).
|
||||
- union:\
|
||||
A data type that can hold values of different types but only one at a time.
|
||||
See [Unions](unsafe-rust/unions.md).
|
||||
- unit test:\
|
||||
Rust comes with built-in support for running small unit tests and larger
|
||||
integration tests. See [Unit Tests](testing/unit-tests.html).
|
||||
integration tests. See [Unit Tests](testing/unit-tests.md).
|
||||
- unit type:\
|
||||
Type that holds no data, written as a tuple with no members.
|
||||
Type that holds no data, written as a tuple with no members. See speaker notes
|
||||
on [Functions](control-flow-basics/functions.html).
|
||||
- unsafe:\
|
||||
The subset of Rust which allows you to trigger _undefined behavior_. See
|
||||
[Unsafe Rust](unsafe-rust/unsafe.md).
|
||||
- variable:\
|
||||
A memory location storing data. Variables are valid in a _scope_.
|
||||
A memory location storing data. Variables are valid in a _scope_. See
|
||||
[Variables](types-and-values/variables.md).
|
||||
|
@@ -4,7 +4,7 @@ minutes: 10
|
||||
|
||||
# What is Rust?
|
||||
|
||||
Rust is a new programming language which had its [1.0 release in 2015][1]:
|
||||
Rust is a new programming language that had its [1.0 release in 2015][1]:
|
||||
|
||||
- Rust is a statically compiled language in a similar role as C++
|
||||
- `rustc` uses LLVM as its backend.
|
||||
|
@@ -0,0 +1,75 @@
|
||||
---
|
||||
minutes: 30
|
||||
---
|
||||
|
||||
## Typestate Pattern: Problem
|
||||
|
||||
How can we ensure that only valid operations are allowed on a value based on its
|
||||
current state?
|
||||
|
||||
```rust,editable
|
||||
use std::fmt::Write as _;
|
||||
|
||||
#[derive(Default)]
|
||||
struct Serializer {
|
||||
output: String,
|
||||
}
|
||||
|
||||
impl Serializer {
|
||||
fn serialize_struct_start(&mut self, name: &str) {
|
||||
let _ = writeln!(&mut self.output, "{name} {{");
|
||||
}
|
||||
|
||||
fn serialize_struct_field(&mut self, key: &str, value: &str) {
|
||||
let _ = writeln!(&mut self.output, " {key}={value};");
|
||||
}
|
||||
|
||||
fn serialize_struct_end(&mut self) {
|
||||
self.output.push_str("}\n");
|
||||
}
|
||||
|
||||
fn finish(self) -> String {
|
||||
self.output
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut serializer = Serializer::default();
|
||||
serializer.serialize_struct_start("User");
|
||||
serializer.serialize_struct_field("id", "42");
|
||||
serializer.serialize_struct_field("name", "Alice");
|
||||
|
||||
// serializer.serialize_struct_end(); // ← Oops! Forgotten
|
||||
|
||||
println!("{}", serializer.finish());
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
- This `Serializer` is meant to write a structured value.
|
||||
|
||||
- However, in this example we forgot to call `serialize_struct_end()` before
|
||||
`finish()`. As a result, the serialized output is incomplete or syntactically
|
||||
incorrect.
|
||||
|
||||
- One approach to fix this would be to track internal state manually, and return
|
||||
a `Result` from methods like `serialize_struct_field()` or `finish()` if the
|
||||
current state is invalid.
|
||||
|
||||
- But this has downsides:
|
||||
|
||||
- It is easy to get wrong as an implementer. Rust’s type system cannot help
|
||||
enforce the correctness of our state transitions.
|
||||
|
||||
- It also adds unnecessary burden on the user, who must handle `Result` values
|
||||
for operations that are misused in source code rather than at runtime.
|
||||
|
||||
- A better solution is to model the valid state transitions directly in the type
|
||||
system.
|
||||
|
||||
In the next slide, we will apply the **typestate pattern** to enforce correct
|
||||
usage at compile time and make it impossible to call incompatible methods or
|
||||
forget to do a required action.
|
||||
|
||||
</details>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user