Repository: google/comprehensive-rust Branch: main Commit: 646605edf379 Files: 824 Total size: 18.2 MB Directory structure: gitextract_wyjk7nt0/ ├── .cargo/ │ └── config.toml ├── .github/ │ ├── CODEOWNERS │ ├── dependabot.yml │ ├── labeler.yml │ ├── pandoc/ │ │ ├── README.md │ │ ├── ja.yaml │ │ ├── ko.yaml │ │ ├── zh-CN.yaml │ │ └── zh-TW.yaml │ ├── typos.toml │ └── workflows/ │ ├── apt-get-install/ │ │ └── action.yml │ ├── build.sh │ ├── build.yml │ ├── check-msgid-changes.py │ ├── check-msgid-changes.yml │ ├── install-mdbook/ │ │ └── action.yml │ ├── labeler.yml │ ├── lint.yml │ ├── publish.yml │ └── setup-rust-cache/ │ └── action.yml ├── .gitignore ├── CONTRIBUTING.md ├── Cargo.toml ├── GEMINI.md ├── LICENSE ├── LICENSE-CC-BY ├── README.md ├── STYLE.md ├── TRANSLATIONS.md ├── book.toml ├── dprint.json ├── mdbook-course/ │ ├── Cargo.toml │ ├── README.md │ └── src/ │ ├── bin/ │ │ ├── course-content.rs │ │ ├── course-schedule.rs │ │ └── mdbook-course.rs │ ├── course.rs │ ├── frontmatter.rs │ ├── lib.rs │ ├── markdown.rs │ ├── replacements.rs │ └── timing_info.rs ├── mdbook-exerciser/ │ ├── Cargo.toml │ ├── README.md │ └── src/ │ ├── lib.rs │ └── main.rs ├── po/ │ ├── ar.po │ ├── bn.po │ ├── da.po │ ├── de.po │ ├── el.po │ ├── es.po │ ├── fa.po │ ├── fr.po │ ├── id.po │ ├── it.po │ ├── ja.po │ ├── ko.po │ ├── pl.po │ ├── pt-BR.po │ ├── ro.po │ ├── ru.po │ ├── tr.po │ ├── uk.po │ ├── vi.po │ ├── zh-CN.po │ └── zh-TW.po ├── rustfmt.toml ├── src/ │ ├── README.md │ ├── SUMMARY.md │ ├── android/ │ │ ├── aidl/ │ │ │ ├── birthday-service.md │ │ │ ├── birthday_service/ │ │ │ │ ├── Android.bp │ │ │ │ ├── aidl/ │ │ │ │ │ ├── Android.bp │ │ │ │ │ └── com/ │ │ │ │ │ └── example/ │ │ │ │ │ └── birthdayservice/ │ │ │ │ │ ├── BirthdayInfo.aidl │ │ │ │ │ ├── IBirthdayInfoProvider.aidl │ │ │ │ │ └── IBirthdayService.aidl │ │ │ │ └── src/ │ │ │ │ ├── client.rs │ │ │ │ ├── lib.rs │ │ │ │ └── server.rs │ │ │ ├── example-service/ │ │ │ │ ├── changing-definition.md │ │ │ │ ├── changing-implementation.md │ │ │ │ ├── client.md │ │ │ │ ├── deploy.md │ │ │ │ ├── implementation.md │ │ │ │ ├── interface.md │ │ │ │ ├── server.md │ │ │ │ ├── service-bindings.md │ │ │ │ └── service.md │ │ │ ├── types/ │ │ │ │ ├── arrays.md │ │ │ │ ├── file-descriptor.md │ │ │ │ ├── objects.md │ │ │ │ ├── parcelables.md │ │ │ │ └── primitives.md │ │ │ └── types.md │ │ ├── aidl.md │ │ ├── bpfmt.sh │ │ ├── build-rules/ │ │ │ ├── binary/ │ │ │ │ ├── Android.bp │ │ │ │ └── src/ │ │ │ │ └── main.rs │ │ │ ├── binary.md │ │ │ ├── library/ │ │ │ │ ├── Android.bp │ │ │ │ └── src/ │ │ │ │ ├── lib.rs │ │ │ │ └── main.rs │ │ │ └── library.md │ │ ├── build-rules.md │ │ ├── build_all.sh │ │ ├── interoperability/ │ │ │ ├── cpp/ │ │ │ │ ├── android-build-cpp.md │ │ │ │ ├── android-build-rust.md │ │ │ │ ├── android-cpp-genrules.md │ │ │ │ ├── bridge.md │ │ │ │ ├── cpp-bridge.md │ │ │ │ ├── cpp-exception.md │ │ │ │ ├── generated-cpp.md │ │ │ │ ├── rust-bridge.md │ │ │ │ ├── rust-result.md │ │ │ │ ├── shared-enums.md │ │ │ │ ├── shared-types.md │ │ │ │ └── type-mapping.md │ │ │ ├── cpp.md │ │ │ ├── java/ │ │ │ │ ├── Android.bp │ │ │ │ ├── HelloWorld.java │ │ │ │ └── src/ │ │ │ │ └── lib.rs │ │ │ ├── java.md │ │ │ ├── with-c/ │ │ │ │ ├── bindgen/ │ │ │ │ │ ├── Android.bp │ │ │ │ │ ├── c-library.md │ │ │ │ │ ├── libbirthday.c │ │ │ │ │ ├── libbirthday.h │ │ │ │ │ ├── libbirthday_wrapper.h │ │ │ │ │ └── main.rs │ │ │ │ ├── bindgen.md │ │ │ │ ├── c-library.md │ │ │ │ ├── hand-written.md │ │ │ │ ├── run-our-binary.md │ │ │ │ ├── rust/ │ │ │ │ │ ├── analyze/ │ │ │ │ │ │ ├── Android.bp │ │ │ │ │ │ └── main.c │ │ │ │ │ └── libanalyze/ │ │ │ │ │ ├── Android.bp │ │ │ │ │ ├── analyze.h │ │ │ │ │ └── analyze.rs │ │ │ │ ├── rust-library.md │ │ │ │ └── rust.md │ │ │ └── with-c.md │ │ ├── interoperability.md │ │ ├── logging/ │ │ │ ├── Android.bp │ │ │ └── src/ │ │ │ └── main.rs │ │ ├── logging.md │ │ ├── setup.md │ │ ├── testing/ │ │ │ ├── Android.bp │ │ │ ├── Cargo.toml │ │ │ ├── googletest.md │ │ │ ├── googletest.rs │ │ │ ├── mockall.rs │ │ │ ├── mocking.md │ │ │ └── src/ │ │ │ └── lib.rs │ │ └── testing.md │ ├── android.md │ ├── bare-metal/ │ │ ├── alloc-example/ │ │ │ ├── .cargo/ │ │ │ │ └── config.toml │ │ │ ├── Cargo.toml │ │ │ └── src/ │ │ │ └── main.rs │ │ ├── alloc.md │ │ ├── android/ │ │ │ └── vmbase.md │ │ ├── android.md │ │ ├── aps/ │ │ │ ├── aarch64-rt/ │ │ │ │ └── exceptions.md │ │ │ ├── aarch64-rt.md │ │ │ ├── better-uart/ │ │ │ │ ├── bitflags.md │ │ │ │ ├── driver.md │ │ │ │ └── registers.md │ │ │ ├── better-uart.md │ │ │ ├── entry-point.md │ │ │ ├── examples/ │ │ │ │ ├── .cargo/ │ │ │ │ │ └── config.toml │ │ │ │ ├── Cargo.toml │ │ │ │ ├── Makefile │ │ │ │ ├── image.ld │ │ │ │ └── src/ │ │ │ │ ├── asm.rs │ │ │ │ ├── entry.S │ │ │ │ ├── exceptions.S │ │ │ │ ├── exceptions.rs │ │ │ │ ├── exceptions_rt.rs │ │ │ │ ├── idmap.S │ │ │ │ ├── logger.rs │ │ │ │ ├── main_improved.rs │ │ │ │ ├── main_logger.rs │ │ │ │ ├── main_minimal.rs │ │ │ │ ├── main_psci.rs │ │ │ │ ├── main_rt.rs │ │ │ │ ├── main_safemmio.rs │ │ │ │ ├── pl011.rs │ │ │ │ ├── pl011_minimal.rs │ │ │ │ └── pl011_struct.rs │ │ │ ├── exceptions.md │ │ │ ├── inline-assembly.md │ │ │ ├── logging/ │ │ │ │ └── using.md │ │ │ ├── logging.md │ │ │ ├── mmio.md │ │ │ ├── other-projects.md │ │ │ ├── safemmio/ │ │ │ │ ├── driver.md │ │ │ │ ├── registers.md │ │ │ │ └── using.md │ │ │ ├── uart/ │ │ │ │ ├── traits.md │ │ │ │ └── using.md │ │ │ └── uart.md │ │ ├── aps.md │ │ ├── microcontrollers/ │ │ │ ├── board-support.md │ │ │ ├── debugging.md │ │ │ ├── embedded-hal.md │ │ │ ├── examples/ │ │ │ │ ├── .cargo/ │ │ │ │ │ └── config.toml │ │ │ │ ├── Cargo.toml │ │ │ │ ├── Embed.toml │ │ │ │ └── src/ │ │ │ │ └── bin/ │ │ │ │ ├── board_support.rs │ │ │ │ ├── hal.rs │ │ │ │ ├── interrupts/ │ │ │ │ │ └── mod.rs │ │ │ │ ├── minimal.rs │ │ │ │ ├── mmio.rs │ │ │ │ ├── pac.rs │ │ │ │ └── typestate.rs │ │ │ ├── hals.md │ │ │ ├── mmio.md │ │ │ ├── other-projects.md │ │ │ ├── pacs.md │ │ │ ├── probe-rs.md │ │ │ └── type-state.md │ │ ├── microcontrollers.md │ │ ├── minimal.md │ │ ├── no_std.md │ │ ├── useful-crates/ │ │ │ ├── aarch64-paging.md │ │ │ ├── allocator-example/ │ │ │ │ ├── Cargo.toml │ │ │ │ └── src/ │ │ │ │ └── main.rs │ │ │ ├── buddy_system_allocator.md │ │ │ ├── spin.md │ │ │ ├── tinyvec.md │ │ │ ├── zerocopy-example/ │ │ │ │ ├── Cargo.toml │ │ │ │ └── src/ │ │ │ │ └── main.rs │ │ │ └── zerocopy.md │ │ └── useful-crates.md │ ├── bare-metal.md │ ├── borrowing/ │ │ ├── Cargo.toml │ │ ├── borrowck.md │ │ ├── examples.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── interior-mutability/ │ │ │ ├── cell.md │ │ │ └── refcell.md │ │ ├── interior-mutability.md │ │ ├── shared.md │ │ └── solution.md │ ├── borrowing.md │ ├── cargo/ │ │ ├── code-samples.md │ │ ├── running-locally.md │ │ └── rust-ecosystem.md │ ├── cargo.md │ ├── chromium/ │ │ ├── adding-third-party-crates/ │ │ │ ├── checking-in.md │ │ │ ├── configuring-cargo-toml.md │ │ │ ├── configuring-gnrt-config-toml.md │ │ │ ├── depending-on-a-crate.md │ │ │ ├── downloading-crates.md │ │ │ ├── generating-gn-build-rules.md │ │ │ ├── keeping-up-to-date.md │ │ │ ├── resolving-problems/ │ │ │ │ ├── build-scripts-which-generate-code.md │ │ │ │ └── build-scripts-which-take-arbitrary-actions.md │ │ │ ├── resolving-problems.md │ │ │ └── reviews-and-audits.md │ │ ├── adding-third-party-crates.md │ │ ├── build-rules/ │ │ │ ├── depending.md │ │ │ ├── unsafe.md │ │ │ └── vscode.md │ │ ├── build-rules.md │ │ ├── cargo.md │ │ ├── interoperability-with-cpp/ │ │ │ ├── error-handling-png.md │ │ │ ├── error-handling-qr.md │ │ │ ├── error-handling.md │ │ │ ├── example-bindings.md │ │ │ ├── limitations-of-cxx.md │ │ │ └── using-cxx-in-chromium.md │ │ ├── interoperability-with-cpp.md │ │ ├── policy.md │ │ ├── setup.md │ │ ├── testing/ │ │ │ ├── build-gn.md │ │ │ ├── chromium-import-macro.md │ │ │ └── rust-gtest-interop.md │ │ └── testing.md │ ├── chromium.md │ ├── closures/ │ │ ├── capturing.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── solution.md │ │ ├── syntax.md │ │ └── traits.md │ ├── closures.md │ ├── concurrency/ │ │ ├── async/ │ │ │ ├── async-await.md │ │ │ ├── futures.md │ │ │ ├── runtimes/ │ │ │ │ └── tokio.md │ │ │ ├── runtimes.md │ │ │ ├── state-machine.md │ │ │ └── tasks.md │ │ ├── async-control-flow/ │ │ │ ├── channels.md │ │ │ ├── join.md │ │ │ └── select.md │ │ ├── async-control-flow.md │ │ ├── async-exercises/ │ │ │ ├── afternoon.md │ │ │ ├── chat-app.md │ │ │ ├── chat-async/ │ │ │ │ ├── Cargo.toml │ │ │ │ └── src/ │ │ │ │ └── bin/ │ │ │ │ ├── client.rs │ │ │ │ └── server.rs │ │ │ ├── dining-philosophers.md │ │ │ ├── dining-philosophers.rs │ │ │ └── solutions.md │ │ ├── async-exercises.md │ │ ├── async-pitfalls/ │ │ │ ├── async-traits.md │ │ │ ├── blocking-executor.md │ │ │ ├── cancellation.md │ │ │ └── pin.md │ │ ├── async-pitfalls.md │ │ ├── async.md │ │ ├── channels/ │ │ │ ├── bounded.md │ │ │ ├── senders-receivers.md │ │ │ └── unbounded.md │ │ ├── channels.md │ │ ├── send-sync/ │ │ │ ├── examples.md │ │ │ ├── marker-traits.md │ │ │ ├── send.md │ │ │ └── sync.md │ │ ├── send-sync.md │ │ ├── shared-state/ │ │ │ ├── arc.md │ │ │ ├── example.md │ │ │ └── mutex.md │ │ ├── shared-state.md │ │ ├── sync-exercises/ │ │ │ ├── Cargo.toml │ │ │ ├── dining-philosophers.md │ │ │ ├── dining-philosophers.rs │ │ │ ├── link-checker.md │ │ │ ├── link-checker.rs │ │ │ └── solutions.md │ │ ├── sync-exercises.md │ │ ├── threads/ │ │ │ ├── plain.md │ │ │ └── scoped.md │ │ ├── threads.md │ │ ├── welcome-async.md │ │ └── welcome.md │ ├── control-flow-basics/ │ │ ├── Cargo.toml │ │ ├── blocks-and-scopes.md │ │ ├── break-continue/ │ │ │ └── labels.md │ │ ├── break-continue.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── functions.md │ │ ├── if.md │ │ ├── loops/ │ │ │ ├── for.md │ │ │ └── loop.md │ │ ├── loops.md │ │ ├── macros.md │ │ ├── match.md │ │ └── solution.md │ ├── control-flow-basics.md │ ├── credits.md │ ├── error-handling/ │ │ ├── Cargo.toml │ │ ├── anyhow.md │ │ ├── error.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── panics.md │ │ ├── result.md │ │ ├── solution.md │ │ ├── thiserror.md │ │ ├── try-conversions.md │ │ └── try.md │ ├── error-handling.md │ ├── exercises/ │ │ ├── bare-metal/ │ │ │ ├── afternoon.md │ │ │ ├── compass/ │ │ │ │ ├── .cargo/ │ │ │ │ │ └── config.toml │ │ │ │ ├── Cargo.toml │ │ │ │ ├── Embed.toml │ │ │ │ └── src/ │ │ │ │ └── main.rs │ │ │ ├── compass.md │ │ │ ├── morning.md │ │ │ ├── rtc/ │ │ │ │ ├── .cargo/ │ │ │ │ │ └── config.toml │ │ │ │ ├── Cargo.toml │ │ │ │ ├── Makefile │ │ │ │ ├── build.rs │ │ │ │ ├── memory.ld │ │ │ │ └── src/ │ │ │ │ ├── exceptions.rs │ │ │ │ ├── logger.rs │ │ │ │ ├── main.rs │ │ │ │ └── pl031.rs │ │ │ ├── rtc.md │ │ │ ├── solutions-afternoon.md │ │ │ └── solutions-morning.md │ │ └── chromium/ │ │ ├── bringing-it-together.md │ │ ├── build-rules.md │ │ ├── interoperability-with-cpp.md │ │ ├── solutions.md │ │ ├── testing.md │ │ └── third-party.md │ ├── generics/ │ │ ├── Cargo.toml │ │ ├── dyn-trait.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── generic-data.md │ │ ├── generic-functions.md │ │ ├── generic-traits.md │ │ ├── impl-trait.md │ │ ├── solution.md │ │ └── trait-bounds.md │ ├── generics.md │ ├── glossary.md │ ├── hello-world/ │ │ ├── benefits.md │ │ ├── playground.md │ │ └── what-is-rust.md │ ├── hello-world.md │ ├── idiomatic/ │ │ ├── foundations-api-design/ │ │ │ ├── meaningful-doc-comments/ │ │ │ │ ├── anatomy-of-a-doc-comment.md │ │ │ │ ├── avoid-redundancy.md │ │ │ │ ├── exercise.md │ │ │ │ ├── library-vs-application-docs.md │ │ │ │ ├── name-drop-signpost.md │ │ │ │ ├── what-isnt-docs.md │ │ │ │ ├── what-why-not-how-where.md │ │ │ │ └── who-are-you-writing-for.md │ │ │ ├── meaningful-doc-comments.md │ │ │ ├── predictable-api/ │ │ │ │ ├── common-traits/ │ │ │ │ │ ├── clone.md │ │ │ │ │ ├── copy.md │ │ │ │ │ ├── debug.md │ │ │ │ │ ├── display.md │ │ │ │ │ ├── from-into.md │ │ │ │ │ ├── hash.md │ │ │ │ │ ├── partialeq-eq.md │ │ │ │ │ ├── partialord-ord.md │ │ │ │ │ ├── serde.md │ │ │ │ │ └── try-from-into.md │ │ │ │ ├── common-traits.md │ │ │ │ ├── naming-conventions/ │ │ │ │ │ ├── as-and-ref.md │ │ │ │ │ ├── by.md │ │ │ │ │ ├── exercise.md │ │ │ │ │ ├── from.md │ │ │ │ │ ├── get.md │ │ │ │ │ ├── into.md │ │ │ │ │ ├── into_inner.md │ │ │ │ │ ├── is.md │ │ │ │ │ ├── mut.md │ │ │ │ │ ├── new.md │ │ │ │ │ ├── push.md │ │ │ │ │ ├── raw_parts.md │ │ │ │ │ ├── to.md │ │ │ │ │ ├── try.md │ │ │ │ │ ├── unchecked.md │ │ │ │ │ ├── with-closure.md │ │ │ │ │ ├── with-constructor.md │ │ │ │ │ ├── with-copy-setter.md │ │ │ │ │ └── with-word.md │ │ │ │ └── naming-conventions.md │ │ │ └── predictable-api.md │ │ ├── foundations-api-design.md │ │ ├── leveraging-the-type-system/ │ │ │ ├── borrow-checker-invariants/ │ │ │ │ ├── aliasing-xor-mutability.md │ │ │ │ ├── generalizing-ownership.md │ │ │ │ ├── phantomdata-01-types.md │ │ │ │ ├── phantomdata-02-types-implemented.md │ │ │ │ ├── phantomdata-03-lifetimes.md │ │ │ │ ├── phantomdata-04-borrowedfd.md │ │ │ │ └── single-use-values.md │ │ │ ├── borrow-checker-invariants.md │ │ │ ├── extension-traits/ │ │ │ │ ├── extending-foreign-types.md │ │ │ │ ├── extending-other-traits.md │ │ │ │ ├── method-resolution-conflicts.md │ │ │ │ ├── should-i-define-an-extension-trait.md │ │ │ │ └── trait-method-conflicts.md │ │ │ ├── extension-traits.md │ │ │ ├── newtype-pattern/ │ │ │ │ ├── is-it-encapsulated.md │ │ │ │ ├── parse-don-t-validate.md │ │ │ │ └── semantic-confusion.md │ │ │ ├── newtype-pattern.md │ │ │ ├── raii/ │ │ │ │ ├── drop_bomb.md │ │ │ │ ├── drop_bomb_forget.md │ │ │ │ ├── drop_guards.md │ │ │ │ ├── drop_option.md │ │ │ │ ├── drop_skipped.md │ │ │ │ ├── forget_and_drop.md │ │ │ │ ├── mutex.md │ │ │ │ └── scope_guard.md │ │ │ ├── raii.md │ │ │ ├── token-types/ │ │ │ │ ├── branded-01-motivation.md │ │ │ │ ├── branded-02-phantomdata.md │ │ │ │ ├── branded-03-impl.md │ │ │ │ ├── branded-04-in-action.md │ │ │ │ ├── mutex-guard.md │ │ │ │ └── permission-tokens.md │ │ │ ├── token-types.md │ │ │ ├── typestate-pattern/ │ │ │ │ ├── typestate-advanced.md │ │ │ │ ├── typestate-example.md │ │ │ │ ├── typestate-generics/ │ │ │ │ │ ├── complete.md │ │ │ │ │ ├── property.md │ │ │ │ │ ├── root.md │ │ │ │ │ └── struct.md │ │ │ │ ├── typestate-generics.md │ │ │ │ └── typestate-generics.rs │ │ │ └── typestate-pattern.md │ │ ├── leveraging-the-type-system.md │ │ ├── polymorphism/ │ │ │ ├── from-oop-to-rust/ │ │ │ │ ├── composition.md │ │ │ │ ├── dynamic-dispatch/ │ │ │ │ │ ├── any-trait.md │ │ │ │ │ ├── dyn-compatible.md │ │ │ │ │ ├── dyn-trait.md │ │ │ │ │ ├── dyn-vs-generics.md │ │ │ │ │ ├── heterogeneous.md │ │ │ │ │ ├── limits.md │ │ │ │ │ └── pitfalls.md │ │ │ │ ├── inheritance.md │ │ │ │ ├── problem-solving.md │ │ │ │ ├── sealed-traits.md │ │ │ │ ├── sealing-with-enums.md │ │ │ │ ├── sticking-with-traits.md │ │ │ │ ├── supertraits.md │ │ │ │ ├── switch-perspective.md │ │ │ │ └── why-no-inheritance.md │ │ │ ├── from-oop-to-rust.md │ │ │ ├── refresher/ │ │ │ │ ├── blanket-impls.md │ │ │ │ ├── conditional-methods.md │ │ │ │ ├── default-impls.md │ │ │ │ ├── deriving-traits.md │ │ │ │ ├── monomorphization.md │ │ │ │ ├── orphan-rule.md │ │ │ │ ├── sized.md │ │ │ │ ├── supertraits.md │ │ │ │ ├── trait-bounds.md │ │ │ │ └── traits.md │ │ │ └── refresher.md │ │ ├── polymorphism.md │ │ └── welcome.md │ ├── index.md │ ├── iterators/ │ │ ├── Cargo.toml │ │ ├── collect.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── helpers.md │ │ ├── intoiterator.md │ │ ├── iterator.md │ │ ├── motivation.md │ │ └── solution.md │ ├── iterators.md │ ├── lifetimes/ │ │ ├── Cargo.toml │ │ ├── borrow-both.md │ │ ├── borrow-one.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── lifetime-elision.md │ │ ├── multiple-borrows.md │ │ ├── returning-borrows.md │ │ ├── simple-borrows.md │ │ ├── solution.md │ │ └── struct-lifetimes.md │ ├── lifetimes.md │ ├── memory-management/ │ │ ├── Cargo.toml │ │ ├── approaches.md │ │ ├── clone.md │ │ ├── copy-types.md │ │ ├── drop.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── move.md │ │ ├── ownership.md │ │ ├── review.md │ │ └── solution.md │ ├── memory-management.md │ ├── methods-and-traits/ │ │ ├── Cargo.toml │ │ ├── deriving.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── methods.md │ │ ├── solution.md │ │ ├── traits/ │ │ │ ├── associated-types.md │ │ │ ├── implementing.md │ │ │ └── supertraits.md │ │ └── traits.md │ ├── methods-and-traits.md │ ├── modules/ │ │ ├── Cargo.toml │ │ ├── encapsulation.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── filesystem.md │ │ ├── modules.md │ │ ├── paths.md │ │ ├── solution.md │ │ └── visibility.md │ ├── modules.md │ ├── other-resources.md │ ├── pattern-matching/ │ │ ├── Cargo.toml │ │ ├── destructuring-enums.md │ │ ├── destructuring-structs.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── infallible.md │ │ ├── let-control-flow/ │ │ │ ├── if-let.md │ │ │ ├── let-else.md │ │ │ └── while-let.md │ │ ├── let-control-flow.md │ │ ├── match.md │ │ └── solution.md │ ├── pattern-matching.md │ ├── references/ │ │ ├── Cargo.toml │ │ ├── dangling.md │ │ ├── exclusive.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── shared.md │ │ ├── slices.md │ │ ├── solution.md │ │ └── strings.md │ ├── references.md │ ├── running-the-course/ │ │ ├── course-structure.md │ │ ├── keyboard-shortcuts.md │ │ └── translations.md │ ├── running-the-course.md │ ├── smart-pointers/ │ │ ├── Cargo.toml │ │ ├── box.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── rc.md │ │ ├── solution.md │ │ └── trait-objects.md │ ├── smart-pointers.md │ ├── std-traits/ │ │ ├── Cargo.toml │ │ ├── casting.md │ │ ├── comparisons.md │ │ ├── default.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── from-and-into.md │ │ ├── operators.md │ │ ├── read-and-write.md │ │ └── solution.md │ ├── std-traits.md │ ├── std-types/ │ │ ├── Cargo.toml │ │ ├── docs.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── hashmap.md │ │ ├── option.md │ │ ├── result.md │ │ ├── solution.md │ │ ├── std.md │ │ ├── string.md │ │ └── vec.md │ ├── std-types.md │ ├── testing/ │ │ ├── Cargo.toml │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── lints.md │ │ ├── other.md │ │ ├── solution.md │ │ └── unit-tests.md │ ├── testing.md │ ├── thanks.md │ ├── tuples-and-arrays/ │ │ ├── Cargo.toml │ │ ├── arrays.md │ │ ├── destructuring.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── iteration.md │ │ ├── solution.md │ │ └── tuples.md │ ├── tuples-and-arrays.md │ ├── types-and-values/ │ │ ├── Cargo.toml │ │ ├── arithmetic.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── hello-world.md │ │ ├── inference.md │ │ ├── solution.md │ │ ├── values.md │ │ └── variables.md │ ├── types-and-values.md │ ├── unsafe-deep-dive/ │ │ ├── Cargo.toml │ │ ├── case-studies/ │ │ │ └── intrusive-linked-list.md │ │ ├── case-studies.md │ │ ├── ffi/ │ │ │ ├── README.md │ │ │ ├── abs.md │ │ │ ├── c-library-example.md │ │ │ ├── cpp-library-example.md │ │ │ ├── language-differences/ │ │ │ │ ├── cpp-and-c.md │ │ │ │ ├── representations.md │ │ │ │ ├── rust-and-c.md │ │ │ │ ├── rust-and-cpp.md │ │ │ │ └── semantics.md │ │ │ ├── language-differences.md │ │ │ ├── language-interop.md │ │ │ ├── rand.md │ │ │ ├── strategies.md │ │ │ └── type-safety.md │ │ ├── ffi.md │ │ ├── initialization/ │ │ │ ├── how-to-initialize-memory.md │ │ │ ├── maybeuninit/ │ │ │ │ ├── arrays.md │ │ │ │ ├── write-vs-assignment.md │ │ │ │ └── zeroed-method.md │ │ │ ├── maybeuninit.md │ │ │ └── partial-initialization.md │ │ ├── initialization.md │ │ ├── introduction/ │ │ │ ├── characteristics-of-unsafe-rust/ │ │ │ │ ├── dangerous.md │ │ │ │ ├── sometimes-necessary.md │ │ │ │ └── sometimes-useful.md │ │ │ ├── characteristics-of-unsafe-rust.md │ │ │ ├── defining-unsafe-rust.md │ │ │ ├── definition.md │ │ │ ├── impact-on-workflow.md │ │ │ ├── may_overflow.md │ │ │ ├── purpose.md │ │ │ ├── responsibility-shift.md │ │ │ ├── two-roles.md │ │ │ ├── warm-up/ │ │ │ │ ├── unsafe-block.md │ │ │ │ ├── unsafe-fn.md │ │ │ │ ├── unsafe-impl.md │ │ │ │ └── unsafe-trait.md │ │ │ └── warm-up.md │ │ ├── introduction.md │ │ ├── memory-lifecycle.md │ │ ├── motivations.md │ │ ├── pinning/ │ │ │ ├── README.md │ │ │ ├── definition-of-pin.md │ │ │ ├── drop-and-not-unpin-worked-example.md │ │ │ ├── phantompinned.md │ │ │ ├── pin-and-drop.md │ │ │ ├── self-referential-buffer/ │ │ │ │ ├── cpp.md │ │ │ │ ├── rust-offset.md │ │ │ │ ├── rust-pin.md │ │ │ │ ├── rust-raw-pointers.md │ │ │ │ └── rust.md │ │ │ ├── self-referential-buffer.md │ │ │ ├── unpin-trait.md │ │ │ ├── what-a-move-is.md │ │ │ ├── what-pinning-is.md │ │ │ └── why-difficult.md │ │ ├── pinning.md │ │ ├── rules-of-the-game/ │ │ │ ├── 3-shapes-of-sound-rust.md │ │ │ ├── copying-memory/ │ │ │ │ ├── crying-wolf.md │ │ │ │ ├── documented-safety-preconditions.md │ │ │ │ ├── encapsulated-unsafe.md │ │ │ │ ├── exposed-unsafe.md │ │ │ │ └── safe.md │ │ │ ├── copying-memory.md │ │ │ ├── rust-is-sound.md │ │ │ ├── soundness-proof/ │ │ │ │ ├── corollary.md │ │ │ │ ├── soundness.md │ │ │ │ └── unsoundness.md │ │ │ └── soundness-proof.md │ │ ├── rules-of-the-game.md │ │ ├── safety-preconditions/ │ │ │ ├── ascii.md │ │ │ ├── common-preconditions.md │ │ │ ├── defining.md │ │ │ ├── determining.md │ │ │ ├── getter.md │ │ │ ├── references.md │ │ │ ├── semantic-preconditions.md │ │ │ └── u8-to-bool.md │ │ ├── safety-preconditions.md │ │ ├── setup.md │ │ └── welcome.md │ ├── unsafe-rust/ │ │ ├── Cargo.toml │ │ ├── dereferencing.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── mutable-static.md │ │ ├── solution.md │ │ ├── unions.md │ │ ├── unsafe-functions/ │ │ │ ├── calling.md │ │ │ ├── extern-c.md │ │ │ └── rust.md │ │ ├── unsafe-functions.md │ │ ├── unsafe-traits.md │ │ └── unsafe.md │ ├── unsafe-rust.md │ ├── user-defined-types/ │ │ ├── Cargo.toml │ │ ├── aliases.md │ │ ├── const.md │ │ ├── enums.md │ │ ├── exercise.md │ │ ├── exercise.rs │ │ ├── named-structs.md │ │ ├── solution.md │ │ ├── static.md │ │ └── tuple-structs.md │ ├── user-defined-types.md │ ├── welcome-day-1-afternoon.md │ ├── welcome-day-1.md │ ├── welcome-day-2-afternoon.md │ ├── welcome-day-2.md │ ├── welcome-day-3-afternoon.md │ ├── welcome-day-3.md │ ├── welcome-day-4-afternoon.md │ └── welcome-day-4.md ├── tests/ │ ├── README.md │ ├── package.json │ ├── src/ │ │ ├── generic-page.test.ts │ │ ├── objects/ │ │ │ ├── playground.ts │ │ │ └── slide.ts │ │ ├── playground.test.ts │ │ ├── redbox.test.ts │ │ ├── slide-style-guide.test.ts │ │ ├── slides/ │ │ │ ├── slide-exemptions.list.ts │ │ │ └── slides.list.ts │ │ └── speaker-notes.test.ts │ ├── tsconfig.json │ ├── wdio.conf-mdbook.ts │ └── wdio.conf.ts ├── theme/ │ ├── book.js │ ├── css/ │ │ ├── language-picker.css │ │ ├── redbox.css │ │ ├── rtl.css │ │ ├── speaker-notes.css │ │ └── svgbob.css │ ├── head.hbs │ ├── index.hbs │ ├── redbox.js │ ├── save-playgrounds.js │ └── speaker-notes.js ├── third_party/ │ ├── README.md │ ├── cxx/ │ │ ├── LICENSE-APACHE │ │ ├── LICENSE-MIT │ │ ├── README.md │ │ ├── blobstore/ │ │ │ ├── Android.bp │ │ │ ├── BUILD │ │ │ ├── Cargo.toml │ │ │ ├── build.rs │ │ │ ├── include/ │ │ │ │ └── blobstore.h │ │ │ └── src/ │ │ │ ├── blobstore.cc │ │ │ └── main.rs │ │ └── book/ │ │ ├── snippets.cc │ │ └── snippets.rs │ └── mdbook/ │ ├── LICENSE │ └── README.md └── xtask/ ├── Cargo.toml ├── README.md └── src/ └── main.rs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .cargo/config.toml ================================================ [alias] xtask = "run --package xtask --" [env] # To provide an anchor to the root of the workspace when working with paths. # See https://github.com/rust-lang/cargo/issues/3946#issuecomment-973132993 CARGO_WORKSPACE_DIR = { value = "", relative = true } ================================================ FILE: .github/CODEOWNERS ================================================ # Translations po/ar.po @younies po/bn.po @mirwasi @sudiptachatterjee po/da.po @mgeisler @voss @thedataking po/de.po @ronaldfw @fechu po/el.po @Mandragorian po/es.po @deavid @vzz1x2 po/fa.po @DannyRavi @hamidrezakp @moaminsharifi @mehrad77 @javad-jafari po/fr.po @sakex po/it.po @detro @nicomazz po/ja.po @keiichiw @chikoski @kantasv @HidenoriKobayashi po/ko.po @jiyongp @jooyunghan @namhyung 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 @rexoplans1 po/uk.po @dyeroshenko po/vi.po @daivinhtran @qu-ngx po/zh-CN.po @wnghl @anlunx @kongy @noahdragon @superwhd @emmali01 @candysonya @AgainstEntropy po/zh-TW.po @edong @hueich @kuanhungchen @victorhsieh @mingyc # Dependency changes (mostly dependabot PRs) Cargo.toml @djmitche @mgeisler @qwandor Cargo.lock @djmitche @mgeisler @qwandor src/bare-metal/alloc-example/Cargo.toml @djmitche @mgeisler @qwandor src/bare-metal/alloc-example/Cargo.lock @djmitche @mgeisler @qwandor src/bare-metal/aps/examples/Cargo.toml @djmitche @mgeisler @qwandor src/bare-metal/aps/examples/Cargo.lock @djmitche @mgeisler @qwandor src/bare-metal/microcontrollers/examples/Cargo.toml @djmitche @mgeisler @qwandor src/bare-metal/microcontrollers/examples/Cargo.lock @djmitche @mgeisler @qwandor src/exercises/bare-metal/compass/Cargo.toml @djmitche @mgeisler @qwandor src/exercises/bare-metal/compass/Cargo.lock @djmitche @mgeisler @qwandor src/exercises/bare-metal/rtc/Cargo.toml @djmitche @mgeisler @qwandor src/exercises/bare-metal/rtc/Cargo.lock @djmitche @mgeisler @qwandor .github/workflows @djmitche @mgeisler @qwandor ================================================ FILE: .github/dependabot.yml ================================================ # Please see the documentation for all configuration options: # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: cargo directory: / schedule: interval: monthly commit-message: prefix: cargo groups: minor: update-types: - minor patch: update-types: - patch - package-ecosystem: cargo directory: /src/bare-metal/alloc-example/ schedule: interval: monthly commit-message: prefix: cargo groups: minor: update-types: - minor patch: update-types: - patch - package-ecosystem: cargo directory: /src/bare-metal/aps/examples/ schedule: interval: monthly commit-message: prefix: cargo groups: minor: update-types: - minor patch: update-types: - patch - package-ecosystem: cargo directory: /src/bare-metal/microcontrollers/examples/ schedule: interval: monthly commit-message: prefix: cargo groups: minor: update-types: - minor patch: update-types: - patch - package-ecosystem: cargo directory: /src/exercises/bare-metal/compass/ schedule: interval: monthly commit-message: prefix: cargo groups: minor: update-types: - minor patch: update-types: - patch - package-ecosystem: cargo directory: /src/exercises/bare-metal/rtc/ schedule: interval: monthly commit-message: prefix: cargo groups: minor: update-types: - minor patch: update-types: - patch - package-ecosystem: github-actions directory: / schedule: interval: monthly ================================================ FILE: .github/labeler.yml ================================================ translation: - changed-files: - any-glob-to-any-file: po/*.po "translation/ar": - changed-files: - any-glob-to-any-file: po/ar.po "translation/bn": - changed-files: - any-glob-to-any-file: po/bn.po "translation/da": - changed-files: - any-glob-to-any-file: po/da.po "translation/de": - changed-files: - any-glob-to-any-file: po/de.po "translation/el": - changed-files: - any-glob-to-any-file: po/el.po "translation/es": - changed-files: - any-glob-to-any-file: po/es.po "translation/fa": - changed-files: - any-glob-to-any-file: po/fa.po "translation/fr": - changed-files: - any-glob-to-any-file: po/fr.po "translation/id": - changed-files: - any-glob-to-any-file: po/id.po "translation/it": - changed-files: - any-glob-to-any-file: po/it.po "translation/ja": - changed-files: - any-glob-to-any-file: po/ja.po "translation/ko": - changed-files: - any-glob-to-any-file: po/ko.po "translation/pl": - changed-files: - any-glob-to-any-file: po/pl.po "translation/pt-BR": - changed-files: - any-glob-to-any-file: po/pt-BR.po "translation/ro": - changed-files: - any-glob-to-any-file: po/ro.po "translation/ru": - changed-files: - any-glob-to-any-file: po/ru.po "translation/tr": - changed-files: - any-glob-to-any-file: po/tr.po "translation/uk": - changed-files: - any-glob-to-any-file: po/uk.po "translation/vi": - changed-files: - any-glob-to-any-file: po/vi.po "translation/zh-CN": - changed-files: - any-glob-to-any-file: po/zh-CN.po "translation/zh-TW": - changed-files: - any-glob-to-any-file: po/zh-TW.po ================================================ FILE: .github/pandoc/README.md ================================================ # Config Overrides for `mdbook-pandoc` The configuration file fragments here are used to override the configuration in `book.toml`. See `.github/workflows/build.sh` for details. ================================================ FILE: .github/pandoc/ja.yaml ================================================ variables: CJKmainfont: "Noto Serif CJK JP" CJKsansfont: "Noto Sans CJK JP" CJKmonofont: "Noto Sans Mono CJK JP" ================================================ FILE: .github/pandoc/ko.yaml ================================================ variables: CJKmainfont: "Noto Serif CJK KR" CJKsansfont: "Noto Sans CJK KR" CJKmonofont: "Noto Sans Mono CJK KR" ================================================ FILE: .github/pandoc/zh-CN.yaml ================================================ variables: CJKmainfont: "Noto Serif CJK SC" CJKsansfont: "Noto Sans CJK SC" CJKmonofont: "Noto Sans Mono CJK SC" ================================================ FILE: .github/pandoc/zh-TW.yaml ================================================ variables: CJKmainfont: "Noto Serif CJK TC" CJKsansfont: "Noto Sans CJK TC" CJKmonofont: "Noto Sans Mono CJK TC" ================================================ FILE: .github/typos.toml ================================================ [default.extend-identifiers] # False positives. mis = "mis" MIS = "MIS" inout = "inout" esource = "esource" BARs = "BARs" [type.po] # Localized content should not be checked for typos. English # in these files should be validated manually. extend-glob = ["*.po"] check-file = false [files] # Typos in third party packages should be fixed upstream. extend-exclude = ["third_party/*", "theme/book.js"] ================================================ FILE: .github/workflows/apt-get-install/action.yml ================================================ 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 < /dev/null <> $GITHUB_ENV - name: Installing ${{ inputs.packages }} shell: bash run: | sudo apt-get install --quiet --yes --no-install-recommends ${{ inputs.packages }} ================================================ FILE: .github/workflows/build.sh ================================================ #!/usr/bin/env bash set -Eeuo pipefail # Usage: build.sh # # Build the course as of the date specified specified in the # POT-Creation-Date header of po/$book_lang.po. The output can be # found in $dest_dir. # # The src/ and third_party/ directories are left in a dirty state so # you can run `mdbook test` and other commands afterwards. # # See also TRANSLATIONS.md. book_lang=${1:?"Usage: $0 "} dest_dir=${2:?"Usage: $0 "} if [ "$book_lang" = "en" ]; then echo "::group::Building English course" else pot_creation_date=$(grep --max-count 1 '^"POT-Creation-Date:' "po/$book_lang.po" | sed -E 's/".*: (.*)\\n"/\1/') pot_creation_date=${pot_creation_date:-now} echo "::group::Building $book_lang translation as of $pot_creation_date" # Back-date the sources to POT-Creation-Date. The content lives in two # directories: rm -r src/ third_party/ git restore --source "$(git rev-list -n 1 --before "$pot_creation_date" @)" src/ third_party/ book.toml # Set language and adjust site URL. Clear the redirects since they are # in sync with the source files, not the translation. export MDBOOK_BOOK__LANGUAGE=$book_lang export MDBOOK_OUTPUT__HTML__SITE_URL=/comprehensive-rust/$book_lang/ export MDBOOK_OUTPUT__HTML__REDIRECT='{}' # Include language-specific Pandoc configuration if [ -f ".github/pandoc/$book_lang.yaml" ]; then export MDBOOK_OUTPUT__PANDOC__PROFILE__PDF__DEFAULTS=".github/pandoc/$book_lang.yaml" fi fi # Enable mdbook-pandoc to build PDF version of the course export MDBOOK_OUTPUT__PANDOC__DISABLED=false mdbook build -d "$dest_dir" mv "$dest_dir/pandoc/pdf/comprehensive-rust.pdf" "$dest_dir/html/" (cd "$dest_dir/exerciser" && zip --recurse-paths ../html/comprehensive-rust-exercises.zip comprehensive-rust-exercises/) echo "::endgroup::" ================================================ FILE: .github/workflows/build.yml ================================================ name: Test permissions: contents: read on: pull_request: push: branches: - main workflow_dispatch: env: CARGO_TERM_COLOR: always jobs: cargo: strategy: matrix: os: - ubuntu-latest - macos-latest runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v6 - name: Update Rust run: rustup update - name: Setup Rust cache uses: ./.github/workflows/setup-rust-cache - name: Build Rust code run: cargo build - name: Test Rust code run: cargo test bare-metal: runs-on: ubuntu-latest strategy: matrix: include: - directory: src/bare-metal/alloc-example target: aarch64-unknown-none - directory: src/bare-metal/aps/examples target: aarch64-unknown-none - directory: src/bare-metal/microcontrollers/examples target: thumbv7em-none-eabihf - directory: src/exercises/bare-metal/compass target: thumbv7em-none-eabihf - directory: src/exercises/bare-metal/rtc target: aarch64-unknown-none steps: - name: Checkout uses: actions/checkout@v6 - name: Install toolchain run: | rustup update rustup target add ${{ matrix.target }} - name: Setup Rust cache uses: ./.github/workflows/setup-rust-cache - name: Install dependencies uses: ./.github/workflows/apt-get-install with: packages: gcc-aarch64-linux-gnu - name: Build Rust code working-directory: ${{ matrix.directory }} run: cargo build find-languages: runs-on: ubuntu-latest outputs: languages: ${{ steps.find-languages.outputs.languages }} steps: - name: Checkout uses: actions/checkout@v6 - name: Find languages id: find-languages shell: python run: | import os, json, pathlib languages = ["en"] + [p.stem for p in pathlib.Path("po").iterdir() if p.suffix == ".po"] github_output = open(os.environ["GITHUB_OUTPUT"], "a") github_output.write("languages=") json.dump(sorted(languages), github_output) build: runs-on: ubuntu-latest needs: - find-languages strategy: matrix: language: ${{ fromJSON(needs.find-languages.outputs.languages) }} fail-fast: false env: # Opt-in for checking links in translations - add the language below. LINK_CHECKED_LANGUAGES: '["en", "fa"]' steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 # We need the full history for build.sh below. - name: Update Rust run: rustup update - name: Setup Rust cache uses: ./.github/workflows/setup-rust-cache with: key: ${{ contains(fromJSON(env.LINK_CHECKED_LANGUAGES), matrix.language) }} - name: Install dependencies uses: ./.github/workflows/apt-get-install with: packages: gettext - name: Install mdbook uses: ./.github/workflows/install-mdbook - name: Test format of ${{ matrix.language }} translation if: matrix.language != 'en' run: msgfmt --statistics -o /dev/null po/${{ matrix.language }}.po - name: Test extracting English strings if: matrix.language == 'en' run: | MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot"}}' mdbook build -d po msgfmt -o /dev/null --statistics po/messages.pot - name: Build ${{ matrix.language }} translation run: | .github/workflows/build.sh ${{ matrix.language }} book/comprehensive-rust-${{ matrix.language }} # Upload the book now to retain it in case mdbook test fails. - name: Upload book uses: actions/upload-artifact@v7 with: name: comprehensive-rust-${{ matrix.language }} path: book/ - name: Test code snippets env: MDBOOK_BOOK__LANGUAGE: ${{ matrix.language }} run: mdbook test web-tests: runs-on: ubuntu-latest needs: build steps: - name: Checkout uses: actions/checkout@v6 - name: Setup Node uses: actions/setup-node@v6 with: node-version: 22 cache: "npm" cache-dependency-path: "tests/package-lock.json" - name: Install test framework run: npm install working-directory: ./tests - name: Download english book uses: actions/download-artifact@v8 with: name: comprehensive-rust-en path: book/ - name: Test Javascript run: cargo xtask web-tests --dir book/comprehensive-rust-en/html po-diff: name: Translation diff runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 - name: Update Rust run: rustup update - name: Setup Rust cache uses: ./.github/workflows/setup-rust-cache - name: Install mdbook uses: ./.github/workflows/install-mdbook - name: Copy latest version of translations run: cp -r po new-po - name: Checkout base version run: git checkout ${{ github.event.pull_request.base.sha }} - name: Translation diff run: i18n-report diff po/ new-po/ > $GITHUB_STEP_SUMMARY ================================================ FILE: .github/workflows/check-msgid-changes.py ================================================ # Copyright 2023 Google LLC # SPDX-License-Identifier: Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Find changed msgid fields without a change in POT-Creation-Date. When following the instructions in https://github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md, one of two things should happen: - The `msgid` fields change because `msgmerge --update` was used. This will also update the POT-Creation-Date field since a new timestamp is merged in from the messages.pot file. - Translations are added or updated. This should not change the `msgid` fields: only the `msgstr` fields should change. If the PO editor being used inadvertently changes the wrapping of both `msgid` and `msgstr` fields, then `dprint fmt` can be used to normalize them all. The code here detects if both of these happen at the same time: if one or more `msgid` fields changed without a corresponding change to the POT-Creation-Date field. If this happens, the translator should fix it by running: dprint fmt Commit and push to the branch again. """ import os # TODO: move the `git reset` from the action code to here. Infact, we # should be able to determine this with read-only operations. # TODO: use Git plumbing commands instead of porcelain, see # https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git.html. for filename in os.popen("git diff --name-only").read().split(): if not filename.endswith(".po"): continue # If POT-Creation-Date has changed, then we assume that the commit # is the result of `msgmerge --update`. It is expected that the # `msgid` fields change when `msgmerge` is run, so there is # nothing to check. if "POT-Creation-Date" in os.popen( f"git diff --unified=0 {filename}").read(): print( f"Assuming {filename} was changed automatically, skipping msgid check" ) continue changed_lines = { i + 1 for i, line in enumerate( os.popen(f"git blame {filename}").readlines()) if line.startswith("00000000") } # Look for a changed line between `msgid` and `msgstr`. saw_msgid = False with open(filename, "r") as f: line = f.readline() line_number = 1 while line: if line.startswith("msgid"): saw_msgid = True elif line.startswith("msgstr"): saw_msgid = False if saw_msgid and line_number in changed_lines: print(f"Changed msgid in file {filename}:{line_number}!") print( "Please read https://github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md#creating-and-updating-translations." ) exit(1) line_number += 1 line = f.readline() ================================================ FILE: .github/workflows/check-msgid-changes.yml ================================================ name: Prevent unintended msgid changes permissions: contents: read on: pull_request: paths: - "po/*.po" jobs: check-msgid-changes: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 - name: Reset git run: git reset origin/main - name: Check po file changes run: python3 .github/workflows/check-msgid-changes.py ================================================ FILE: .github/workflows/install-mdbook/action.yml ================================================ name: Install mdbook and dependencies 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 --binstall shell: bash - name: Install mdbook-pandoc dependencies uses: ./.github/workflows/apt-get-install with: packages: > fonts-noto fonts-noto-cjk fonts-noto-color-emoji fonts-noto-extra fonts-symbola librsvg2-bin texlive texlive-fonts-recommended texlive-lang-arabic texlive-lang-cjk texlive-lang-japanese texlive-luatex - name: Install mdbook-pandoc run: | 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 ================================================ FILE: .github/workflows/labeler.yml ================================================ name: "Pull Request Labeler" on: - pull_request_target jobs: triage: permissions: contents: read pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/labeler@v6 with: sync-labels: true ================================================ FILE: .github/workflows/lint.yml ================================================ name: Lint permissions: contents: read on: pull_request: push: branches: - main env: CARGO_TERM_COLOR: always jobs: clippy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 - 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@v6 - 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@v6 - name: Check for typos uses: crate-ci/typos@v1.44.0 with: config: ./.github/typos.toml ================================================ FILE: .github/workflows/publish.yml ================================================ name: Publish # See also TRANSLATIONS.md. on: push: branches: - main workflow_dispatch: permissions: contents: read pages: write id-token: write # Allow one concurrent deployment concurrency: group: pages cancel-in-progress: true env: CARGO_TERM_COLOR: always # Update the language picker in index.hbs to link new languages. LANGUAGES: ar bn da de el es fa fr id it ja ko pl pt-BR ro ru tr uk vi zh-CN zh-TW jobs: publish: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 # We need the full history for build.sh below. - name: Update Rust run: rustup update - name: Setup Rust cache uses: ./.github/workflows/setup-rust-cache - name: Install Gettext uses: ./.github/workflows/apt-get-install with: packages: gettext - name: Install mdbook uses: ./.github/workflows/install-mdbook - name: Build course in English run: .github/workflows/build.sh en book - name: Build all translations run: | for po_lang in ${{ env.LANGUAGES }}; do .github/workflows/build.sh $po_lang book/$po_lang mv book/$po_lang/html book/html/$po_lang done - name: Build translation report run: i18n-report report book/html/translation-report.html po/*.po - name: Build synced translation report run: | cp -r po synced-po MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot", "granularity": 0}}' mdbook build -d synced-po for file in synced-po/*.po; do msgmerge --update $file synced-po/messages.pot ; done i18n-report report book/html/synced-translation-report.html synced-po/*.po - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload artifact uses: actions/upload-pages-artifact@v4 with: path: book/html - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ================================================ FILE: .github/workflows/setup-rust-cache/action.yml ================================================ name: Setup Rust cache description: Configure the rust-cache workflow. inputs: key: description: Additional caching key required: false default: runs: using: composite steps: - name: Setup Rust cache uses: Swatinem/rust-cache@v2 with: # Only save the cache on the main branch to avoid PRs filling # up the cache. save-if: ${{ github.ref == 'refs/heads/main' }} # Further, save the cache per key - e.g. language grouping. key: ${{ inputs.key }} ================================================ FILE: .gitignore ================================================ # Build artifacts /book/ target/ *.bin # Translation artifacts po/*.mo po/*.po~ # macOS artifacts .DS_Store # Jetbrains IDEs project files .idea/ .iml .iws count.dat # Nodejs Files (dprint) node_modules/ package.json !tests/package.json pnpm-lock.yaml # Crowdin Config (Contains API Keys) crowdin.yml # Google's Project IDX files and VSCode .idx/ .vscode/ # Python virtualenv (for mdbook-slide-evaluator local installation) .venv/ # tests/ framework artifacts tests/src/slide/slides/slides.list.ts ================================================ FILE: CONTRIBUTING.md ================================================ # How to Contribute 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 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 ## Writing Exercises Each segment ends with an exercise. Exercises are typically structured as an `exercise.rs` containing the problem and solution. This is referenced from `exercise.md` and `solution.md`, using `{{#include exercise.rs:anchor_name}}` to match ANCHOR comments in the `exercise.rs` file. Each segment also has a `Cargo.toml` file containing a `[[bin]]` or `[lib]` section referring to `exercise.rs`, and that Cargo package is referenced from the workspace the root `Cargo.toml`. The result is that `exercise.rs` is built and tested by `cargo test`. For segments on day 1, exercises should use `fn main() { .. }` and `dbg!` or `println!`, with students visually verifying the correct output. On subsequent days, prefer tests and omit `fn main() { .. }`. However, where tests would be difficult and visual verification is more natural (such as in the Logger exercise), using `fn main { .. }` is OK. Especially for exercises without tests, consider including tests in `exercise.rs` that do not appear in either `exercise.md` or `solution.md`, as these can ensure the solution is correct. ## Testing We test the course material in several ways: - `mdbook test`: This will test the code samples. Some code samples are marked with `ignore` in the Markdown file because the Playground is missing some of the crates we use. For this we have - `cargo test`: This will build and test the Rust code found in our tooling, as well as the code samples which cannot be tested using the Playground. - `npm test`: This will test the functionality of the rendered web pages. See the [testing README](tests/README.md) for details. ## Formatting Please ensure that your files are formatted consistently. We use a few tools for this: - [`dprint`] for driving the formatting. - [`rustfmt`] for formatting Rust code. - [`yapf`] for formatting Python code. - [`msgcat`] for formatting PO files. 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 [installation instructions](https://dprint.dev/install/) and install `rustfmt` via `rustup`. Install [pandoc 3.7.0.1](https://github.com/jgm/pandoc/releases/tag/3.7.0.1). On Debian, you can install the other tools using: ```sh sudo apt install yapf3 gettext texlive texlive-luatex texlive-lang-cjk texlive-lang-arabic librsvg2-bin fonts-noto ``` ### MacOS On MacOS with [Homebrew], you can install the necessary tools with: ```shell brew install dprint yapf gettext ``` ### Windows On Windows, you can should install [Gettext tools for Windows]. Install `dprint` using their [installation instructions](https://dprint.dev/install/) and install `rustfmt` via `rustup`. > _TODO: fill in how to install `yapf` on Windows._ [`dprint`]: https://dprint.dev/ [`rustfmt`]: https://github.com/rust-lang/rustfmt [`yapf`]: https://github.com/google/yapf [`msgcat`]: https://www.gnu.org/software/gettext/manual/html_node/msgcat-Invocation.html [Homebrew]: https://brew.sh/ [Gettext tools for Windows]: https://github.com/vslavik/gettext-tools-windows/releases ## Contributor License Agreement Contributions to this project must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as part of the project. Head over to to see your current agreements on file or to sign a new one. You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. ## Code Reviews All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. ## Community Guidelines This project follows [Google's Open Source Community Guidelines](https://opensource.google/conduct/). ================================================ FILE: Cargo.toml ================================================ [workspace] # Please keep the workspace members sorted. members = [ "mdbook-course", "mdbook-exerciser", "src/android/testing", "src/bare-metal/useful-crates/allocator-example", "src/bare-metal/useful-crates/zerocopy-example", "src/borrowing", "src/concurrency/async-exercises/chat-async", "src/concurrency/sync-exercises", "src/control-flow-basics", "src/error-handling", "src/generics", "src/iterators", "src/lifetimes", "src/memory-management", "src/methods-and-traits", "src/modules", "src/pattern-matching", "src/references", "src/smart-pointers", "src/std-traits", "src/std-types", "src/testing", "src/tuples-and-arrays", "src/types-and-values", "src/unsafe-rust", "src/user-defined-types", "third_party/cxx/blobstore", "xtask", ] resolver = "2" ================================================ FILE: GEMINI.md ================================================ # 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 ] [--output ] ``` (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 ] [--output ] ``` - **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 ] ``` # 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. ## Developing Exercises Exercises allow students to practice what they have learned. When adding or updating exercises, follow these structural conventions: - **File Structure:** - `exercise.md`: Contains the problem description and a code block with placeholders. - `exercise.rs`: Contains the full solution code, including a license header and `ANCHOR` tags to delimit sections. - `solution.md`: Includes the full solution code from `exercise.rs`. - `Cargo.toml`: Must define a `[[bin]]` target pointing to `exercise.rs` so that the solution code is compiled and tested. - **Content Inclusion:** - Use `{{#include exercise.rs:anchor_name}}` in `exercise.md` to show specific parts of the code (e.g., setup, main). - Use `{{#include exercise.rs:solution}}` in `solution.md` to show the solution code _without_ the license header. Ensure `exercise.rs` has a `// ANCHOR: solution` line before the first line of the solution. It is unnecessary to add a `// ANCHOR_END: solution` line at the bottom of the file. - **Testing:** - Run `cargo xtask rust-tests` to ensure the solution code compiles and runs correctly. - Run `cargo check -p ` to verify the specific exercise crate. ## 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:** - **`
`:** Used for collapsible "speaker notes". - **``:** Used to denote keyboard keys. Each key in a combination must be wrapped in its own tag, e.g., `Ctrl + S`. - **`