1
0
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:
Glen De Cauwsemaecker
2025-09-29 09:48:53 +02:00
176 changed files with 13001 additions and 6116 deletions

View File

@@ -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
View File

@@ -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

View 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 }}

View File

@@ -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

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

173
GEMINI.md Normal file
View 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.

View File

@@ -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
View File

@@ -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.

View File

@@ -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"]
}]
},

View File

@@ -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"

View File

@@ -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()
}
}

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -83,7 +83,7 @@ impl<const N: usize> Table<N> {
for cell in iter {
write!(f, " {} |", cell)?;
}
write!(f, "\n")
writeln!(f)
}
}

View File

@@ -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()
}

View File

@@ -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 }

View File

@@ -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 ""

View File

@@ -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

View File

@@ -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

12280
po/tr.po

File diff suppressed because it is too large Load Diff

View File

@@ -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 ""

View File

@@ -1,4 +1,5 @@
# Please use a nightly rustfmt for these settings.
unstable_features = true
imports_granularity = "module"
wrap_comments = true

View File

@@ -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)
---

View File

@@ -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>

View File

@@ -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.

View File

@@ -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.
}

View File

@@ -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;

View File

@@ -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>

View File

@@ -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.

View File

@@ -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>

View File

@@ -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:

View File

@@ -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).

View File

@@ -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>

View File

@@ -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>

View File

@@ -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:

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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"

View File

@@ -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"

View File

@@ -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.

View File

@@ -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`.

View File

@@ -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

View File

@@ -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.

View File

@@ -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>

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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.

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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.

View File

@@ -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.

View File

@@ -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>

View File

@@ -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

View File

@@ -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.

View File

@@ -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"] }

View File

@@ -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(()),
}
}

View File

@@ -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,

View File

@@ -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 },
}

View File

@@ -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"

View File

@@ -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() {

View File

@@ -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).

View File

@@ -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() {

View File

@@ -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

View File

@@ -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>

View File

@@ -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`.

View File

@@ -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>

View File

@@ -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.

View File

@@ -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",

View File

@@ -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"

View File

@@ -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:?}");
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -1,5 +1,5 @@
---
Minutes: 5
minutes: 5
---
# Generic Traits

View File

@@ -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

View File

@@ -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).

View File

@@ -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.

View File

@@ -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