From 772b383cf03965e065473e0872de14ac2b9d9908 Mon Sep 17 00:00:00 2001 From: Al Rifat Sabbir Date: Wed, 18 Mar 2026 02:26:55 +0600 Subject: [PATCH 1/3] docs: start Bengali (bn) translation --- .github/labeler.yml | 3 + po/bn.po | 38366 ++++++++++++++++++++++++++++-------------- 2 files changed, 26134 insertions(+), 12235 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 4e9e725797e7..f7fe7161237c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -85,3 +85,6 @@ translation: "translation/zh-TW": - changed-files: - any-glob-to-any-file: po/zh-TW.po +"translation/bn": + - changed-files: + - any-glob-to-any-file: po/bn.po \ No newline at end of file diff --git a/po/bn.po b/po/bn.po index f846d30dd5e9..4562ef80fdd3 100644 --- a/po/bn.po +++ b/po/bn.po @@ -1,16 +1,15 @@ msgid "" msgstr "" "Project-Id-Version: Comprehensive Rust đŸĻ€\n" -"POT-Creation-Date: 2024-03-03T20:37:57+05:30\n" -"PO-Revision-Date: \n" -"Last-Translator: Abhik Banerjee \n" -"Language-Team: abhik-99, noob_rasel\n" -"Language: bn\n" +"POT-Creation-Date: 2026-03-18T01:02:13+06:00\n" +"PO-Revision-Date: 2026-03-18 01:03+0600\n" +"Last-Translator: \n" +"Language-Team: Bengali <(nothing)>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n==0 || n==1);\n" -"X-Generator: Poedit 3.4.2\n" +"Language: bn\n" +"Plural-Forms: nplurals=1; plural=0;\n" #: src/SUMMARY.md src/index.md msgid "Welcome to Comprehensive Rust đŸĻ€" @@ -18,15 +17,15 @@ msgstr "Comprehensive Rust đŸĻ€ āĻ āφāĻĒāύāĻžāϕ⧇ āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ" #: src/SUMMARY.md src/running-the-course.md msgid "Running the Course" -msgstr "āϕ⧋āĻ°ā§āϏ āϚāĻžāϞāĻžāύ⧋" +msgstr "āϕ⧋āĻ°ā§āϏāϟāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž" #: src/SUMMARY.md src/running-the-course/course-structure.md msgid "Course Structure" -msgstr "āϕ⧋āĻ°ā§āϏ āĻāϰ āĻ—āĻ āύ" +msgstr "āϕ⧋āĻ°ā§āϏ⧇āϰ āĻ—āĻ āύ" #: src/SUMMARY.md src/running-the-course/keyboard-shortcuts.md msgid "Keyboard Shortcuts" -msgstr "āĻ•āĻŋāĻŦā§‹āĻ°ā§āĻĄ āĻļāĻ°ā§āϟāĻ•āĻžāϟ" +msgstr "āϕ⧀āĻŦā§‹āĻ°ā§āĻĄ āĻļāĻ°ā§āϟāĻ•āĻžāϟ" #: src/SUMMARY.md src/running-the-course/translations.md msgid "Translations" @@ -38,19291 +37,33851 @@ msgstr "Cargo āĻŦā§āϝāĻŦāĻšāĻžāϰ" #: src/SUMMARY.md msgid "Rust Ecosystem" -msgstr "āϰāĻžāĻ¸ā§āϟ āχāϕ⧋āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ" +msgstr "Rust āχāϕ⧋āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ" #: src/SUMMARY.md msgid "Code Samples" -msgstr "āϕ⧋āĻĄ āύāĻŽā§āύāĻž" +msgstr "āϕ⧋āĻĄ āύāĻŽā§āύāĻžāϏāĻŽā§‚āĻš" #: src/SUMMARY.md msgid "Running Cargo Locally" -msgstr "Cargo Locally āϚāĻžāϞāĻžāύ⧋ āĻšāĻšā§āϛ⧇" +msgstr "āϞ⧋āĻ•āĻžāϞ āĻŽā§‡āĻļāĻŋāύ⧇ Cargo āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž" #: src/SUMMARY.md msgid "Day 1: Morning" msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ" -#: src/SUMMARY.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-1.md src/welcome-day-2.md src/welcome-day-3.md +#: src/welcome-day-4.md src/concurrency/welcome-async.md msgid "Welcome" msgstr "āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ" -#: src/SUMMARY.md src/hello-world.md src/types-and-values/hello-world.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-1.md src/hello-world.md src/types-and-values.md +#: src/types-and-values/hello-world.md msgid "Hello, World" -msgstr "āĻšā§āϝāĻžāϞ⧋ āĻ“ā§ŸāĻžāĻ°ā§āĻ˛ā§āĻĄ" +msgstr "āĻšā§āϝāĻžāϞ⧋, āĻ“ā§ŸāĻžāĻ°ā§āĻ˛ā§āĻĄ" -#: src/SUMMARY.md src/hello-world/what-is-rust.md +#: src/SUMMARY.md src/hello-world.md src/hello-world/what-is-rust.md msgid "What is Rust?" -msgstr "āϰāĻžāĻ¸ā§āϟ āĻ•āĻŋ?" +msgstr "Rust āĻ•āĻŋ?" -#: src/SUMMARY.md src/hello-world/benefits.md +#: src/SUMMARY.md src/hello-world.md src/hello-world/benefits.md msgid "Benefits of Rust" -msgstr "āϰāĻžāĻ¸ā§āϟ āĻāϰ āϏ⧁āĻŦāĻŋāϧāĻž" +msgstr "Rust āĻāϰ āϏ⧁āĻŦāĻŋāϧāĻžāϏāĻŽā§‚āĻš" -#: src/SUMMARY.md src/hello-world/playground.md +#: src/SUMMARY.md src/hello-world.md src/hello-world/playground.md msgid "Playground" -msgstr "āĻĒā§āϞ⧇āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄ" +msgstr "āĻĒā§āϞ⧇āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄ (Playground)" -#: src/SUMMARY.md src/types-and-values.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-1.md src/types-and-values.md msgid "Types and Values" -msgstr "āϟāĻžāχāĻĒ āĻāĻŦāĻ‚ āĻŽāĻžāύ" +msgstr "" -#: src/SUMMARY.md src/types-and-values/variables.md +#: src/SUMMARY.md src/types-and-values.md src/types-and-values/variables.md msgid "Variables" -msgstr "āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ" +msgstr "" -#: src/SUMMARY.md src/types-and-values/values.md +#: src/SUMMARY.md src/types-and-values.md src/types-and-values/values.md msgid "Values" -msgstr "āĻŽāĻžāύ" +msgstr "" -#: src/SUMMARY.md src/types-and-values/arithmetic.md +#: src/SUMMARY.md src/types-and-values.md src/types-and-values/arithmetic.md msgid "Arithmetic" -msgstr "āĻ…āĻ™ā§āĻ•āĻļāĻžāĻ¸ā§āĻ¤ā§āϰ" - -#: src/SUMMARY.md src/types-and-values/strings.md -msgid "Strings" -msgstr "Strings" +msgstr "" -#: src/SUMMARY.md src/types-and-values/inference.md +#: src/SUMMARY.md src/types-and-values.md src/types-and-values/inference.md msgid "Type Inference" -msgstr "āϟāĻžāχāĻĒ āĻ…āύ⧁āĻŽāĻžāύ" +msgstr "" -#: src/SUMMARY.md src/types-and-values/exercise.md +#: src/SUMMARY.md src/types-and-values.md src/types-and-values/exercise.md msgid "Exercise: Fibonacci" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻĢāĻŋāĻŦā§‹āύāĻžāĻšā§āϚāĻŋ" +msgstr "" #: src/SUMMARY.md src/types-and-values/solution.md #: src/control-flow-basics/solution.md src/tuples-and-arrays/solution.md #: src/references/solution.md src/user-defined-types/solution.md #: src/pattern-matching/solution.md src/methods-and-traits/solution.md -#: src/generics/solution.md src/std-types/solution.md +#: src/generics/solution.md src/closures/solution.md src/std-types/solution.md #: src/std-traits/solution.md src/memory-management/solution.md -#: src/smart-pointers/solution.md src/borrowing/solution.md -#: src/slices-and-lifetimes/solution.md src/iterators/solution.md -#: src/modules/solution.md src/testing/solution.md +#: src/smart-pointers/solution.md src/lifetimes/solution.md +#: src/iterators/solution.md src/modules/solution.md src/testing/solution.md #: src/error-handling/solution.md src/unsafe-rust/solution.md msgid "Solution" -msgstr "āϏāĻŽāĻžāϧāĻžāύ" +msgstr "" -#: src/SUMMARY.md src/control-flow-basics.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-1.md src/control-flow-basics.md msgid "Control Flow Basics" -msgstr "āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§‡āϰ āĻĒā§āϰāĻŦāĻžāĻš āύāĻŋāϝāĻŧāĻ¨ā§āĻ¤ā§āϰāϪ⧇āϰ āĻŽā§ŒāϞāĻŋāĻ• āĻŦāĻŋāώāϝāĻŧ" +msgstr "" + +#: src/SUMMARY.md src/control-flow-basics.md +#: src/control-flow-basics/blocks-and-scopes.md +msgid "Blocks and Scopes" +msgstr "" #: src/SUMMARY.md msgid "`if` Expressions" -msgstr "if āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ" +msgstr "" + +#: src/SUMMARY.md src/control-flow-basics/match.md +msgid "`match` Expressions" +msgstr "" -#: src/SUMMARY.md src/control-flow-basics/loops.md +#: src/SUMMARY.md src/control-flow-basics.md src/control-flow-basics/loops.md msgid "Loops" -msgstr "āϞ⧁āĻĒā§āϏ" +msgstr "" #: src/SUMMARY.md src/control-flow-basics/loops/for.md msgid "`for`" -msgstr "`for`" +msgstr "" #: src/SUMMARY.md src/control-flow-basics/loops/loop.md msgid "`loop`" -msgstr "`loop`" +msgstr "" #: src/SUMMARY.md src/control-flow-basics/break-continue.md msgid "`break` and `continue`" -msgstr "`break` āĻāĻŦāĻ‚ `continue`" +msgstr "" #: src/SUMMARY.md src/control-flow-basics/break-continue/labels.md msgid "Labels" -msgstr "āϞ⧇āĻŦ⧇āϞ" - -#: src/SUMMARY.md src/control-flow-basics/blocks-and-scopes.md -msgid "Blocks and Scopes" -msgstr "āĻŦā§āϞāĻ• āĻāĻŦāĻ‚ āĻ¸ā§āϕ⧋āĻĒ" - -#: src/SUMMARY.md src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "Scopes and Shadowing" -msgstr "āĻĒā§āϰāϏāĻžāϰ āĻāĻŦāĻ‚ āĻĒā§āϰāϤāĻŋāĻšā§āĻ›āĻžāϝāĻŧāĻž āĻ•āϰāĻž" +msgstr "" -#: src/SUMMARY.md src/control-flow-basics/functions.md +#: src/SUMMARY.md src/control-flow-basics.md +#: src/control-flow-basics/functions.md msgid "Functions" -msgstr "āĻĢāĻžāĻ‚āĻļāύ" +msgstr "" -#: src/SUMMARY.md src/control-flow-basics/macros.md +#: src/SUMMARY.md src/control-flow-basics.md src/control-flow-basics/macros.md msgid "Macros" -msgstr "āĻŽā§āϝāĻžāĻ•ā§āϰ⧋" +msgstr "" -#: src/SUMMARY.md src/control-flow-basics/exercise.md +#: src/SUMMARY.md src/control-flow-basics.md +#: src/control-flow-basics/exercise.md msgid "Exercise: Collatz Sequence" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻ•āĻ˛ā§āϝāĻžāϟāϜ āĻāϰ āĻ•ā§āϰāĻŽ" +msgstr "" #: src/SUMMARY.md msgid "Day 1: Afternoon" -msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύāσ āĻŦāĻŋāĻ•āĻžāϞ" +msgstr "" -#: src/SUMMARY.md src/tuples-and-arrays.md -#: src/tuples-and-arrays/tuples-and-arrays.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-1-afternoon.md src/tuples-and-arrays.md msgid "Tuples and Arrays" -msgstr "āϟāĻŋāωāĻĒāϞ āĻāĻŦāĻ‚ āĻ…ā§āϝāĻžāϰ⧇" +msgstr "" + +#: src/SUMMARY.md src/tuples-and-arrays.md src/tuples-and-arrays/arrays.md +msgid "Arrays" +msgstr "" + +#: src/SUMMARY.md src/tuples-and-arrays.md src/tuples-and-arrays/tuples.md +msgid "Tuples" +msgstr "" -#: src/SUMMARY.md src/tuples-and-arrays/iteration.md +#: src/SUMMARY.md src/tuples-and-arrays.md src/tuples-and-arrays/iteration.md msgid "Array Iteration" -msgstr "āĻ…ā§āϝāĻžāϰ⧇ āĻāϰ āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ" +msgstr "" -#: src/SUMMARY.md src/tuples-and-arrays/destructuring.md +#: src/SUMMARY.md src/tuples-and-arrays.md +#: src/tuples-and-arrays/destructuring.md msgid "Patterns and Destructuring" -msgstr "āĻĸāĻ•-āĻ āĻĢ⧇āϞāĻž āĻāĻŦāĻ‚ āĻĄāĻŋāĻ¸ā§āĻŸā§āϰāĻžāĻ•āϚāĻžāϰ āĻ•āϰāĻž" +msgstr "" -#: src/SUMMARY.md src/tuples-and-arrays/exercise.md +#: src/SUMMARY.md src/tuples-and-arrays.md src/tuples-and-arrays/exercise.md msgid "Exercise: Nested Arrays" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āύ⧇āĻ¸ā§āĻŸā§‡āĻĄ āĻ…ā§āϝāĻžāϰ⧇" +msgstr "" -#: src/SUMMARY.md src/references.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-1-afternoon.md src/references.md msgid "References" -msgstr "āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ" +msgstr "" -#: src/SUMMARY.md src/references/shared.md +#: src/SUMMARY.md src/references.md src/references/shared.md msgid "Shared References" -msgstr "āĻ­āĻžāĻ— āĻ•āϰāĻž āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ" +msgstr "" -#: src/SUMMARY.md src/references/exclusive.md +#: src/SUMMARY.md src/references.md src/references/exclusive.md msgid "Exclusive References" -msgstr "āĻāĻ•āĻšā§‡āϟāĻŋāϝāĻŧāĻž āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ" +msgstr "" + +#: src/SUMMARY.md src/references.md src/references/slices.md +msgid "Slices" +msgstr "" + +#: src/SUMMARY.md src/references.md src/references/strings.md +msgid "Strings" +msgstr "" -#: src/SUMMARY.md src/references/exercise.md +#: src/SUMMARY.md src/references.md src/references/dangling.md +msgid "Reference Validity" +msgstr "" + +#: src/SUMMARY.md src/references.md src/references/exercise.md msgid "Exercise: Geometry" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻœā§āϝāĻžāĻŽāĻŋāϤāĻŋ" +msgstr "" -#: src/SUMMARY.md src/user-defined-types.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-1-afternoon.md src/user-defined-types.md msgid "User-Defined Types" -msgstr "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āĻĻā§āĻŦāĻžāϰāĻž āĻŦāĻ°ā§āĻŖāĻŋāϤ āϟāĻžāχāĻĒ" +msgstr "" -#: src/SUMMARY.md src/user-defined-types/named-structs.md +#: src/SUMMARY.md src/user-defined-types.md +#: src/user-defined-types/named-structs.md msgid "Named Structs" -msgstr "āĻ…āĻ­āĻŋāĻšāĻŋāϤ Structs (āĻ—āĻ āύ)" +msgstr "" -#: src/SUMMARY.md src/user-defined-types/tuple-structs.md +#: src/SUMMARY.md src/user-defined-types.md +#: src/user-defined-types/tuple-structs.md msgid "Tuple Structs" -msgstr "Tuple Structs" +msgstr "" -#: src/SUMMARY.md src/user-defined-types/enums.md -#: src/pattern-matching/destructuring.md +#: src/SUMMARY.md src/user-defined-types.md src/user-defined-types/enums.md +#: src/pattern-matching/destructuring-enums.md msgid "Enums" -msgstr "Enums" - -#: src/SUMMARY.md src/user-defined-types/static-and-const.md -msgid "Static and Const" -msgstr "Static āĻāĻŦāĻ‚ Const" +msgstr "" -#: src/SUMMARY.md src/user-defined-types/aliases.md +#: src/SUMMARY.md src/user-defined-types.md src/user-defined-types/aliases.md msgid "Type Aliases" -msgstr "āϟāĻžāχāĻĒ āĻāϰ āωāĻĒāύāĻžāĻŽ" +msgstr "" + +#: src/SUMMARY.md src/user-defined-types.md +msgid "Const" +msgstr "" + +#: src/SUMMARY.md src/user-defined-types.md +msgid "Static" +msgstr "" -#: src/SUMMARY.md src/user-defined-types/exercise.md +#: src/SUMMARY.md src/user-defined-types.md src/user-defined-types/exercise.md msgid "Exercise: Elevator Events" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āϞāĻŋāĻĢāϟ āĻāϰ āϘāϟāύāĻžāĻŦāϞ⧀" +msgstr "" #: src/SUMMARY.md msgid "Day 2: Morning" -msgstr "āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ" +msgstr "" -#: src/SUMMARY.md src/pattern-matching.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-2.md src/pattern-matching.md msgid "Pattern Matching" -msgstr "āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āĻŽāĻŋāϞāĻžāύ⧋" +msgstr "" + +#: src/SUMMARY.md src/pattern-matching.md src/pattern-matching/infallible.md +msgid "Irrefutable Patterns" +msgstr "" -#: src/SUMMARY.md src/pattern-matching/match.md +#: src/SUMMARY.md src/pattern-matching.md src/pattern-matching/match.md msgid "Matching Values" -msgstr "āĻŽāĻžāύ āĻŽā§‡āϞāĻžāύ⧋" +msgstr "" + +#: src/SUMMARY.md src/pattern-matching.md +msgid "Destructuring Structs" +msgstr "" -#: src/SUMMARY.md src/pattern-matching/destructuring.md -msgid "Destructuring" -msgstr "āĻĄāĻŋāĻ¸ā§āĻŸā§āϰāĻžāĻ•āϚāĻžāϰ āĻ•āϰāĻž" +#: src/SUMMARY.md src/pattern-matching.md +msgid "Destructuring Enums" +msgstr "" -#: src/SUMMARY.md src/pattern-matching/let-control-flow.md +#: src/SUMMARY.md src/pattern-matching.md +#: src/pattern-matching/let-control-flow.md msgid "Let Control Flow" -msgstr "Let āĻāϰ āĻĒā§āϰāĻŦāĻžāĻš āύāĻŋāϝāĻŧāĻ¨ā§āĻ¤ā§āϰāĻŖ" +msgstr "" + +#: src/SUMMARY.md src/pattern-matching/let-control-flow/if-let.md +msgid "`if let` Expressions" +msgstr "" + +#: src/SUMMARY.md src/pattern-matching/let-control-flow/while-let.md +msgid "`while let` Statements" +msgstr "" + +#: src/SUMMARY.md +msgid "`let else`" +msgstr "" -#: src/SUMMARY.md src/pattern-matching/exercise.md +#: src/SUMMARY.md src/pattern-matching.md src/pattern-matching/exercise.md msgid "Exercise: Expression Evaluation" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ āĻŽā§‚āĻ˛ā§āϝāĻžāϝāĻŧāύ" +msgstr "" -#: src/SUMMARY.md src/methods-and-traits.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-2.md src/methods-and-traits.md msgid "Methods and Traits" -msgstr "āĻŽā§‡āĻĨāĻĄ āĻāĻŦāĻ‚ āĻŸā§āϰ⧇āχāϟ" +msgstr "" -#: src/SUMMARY.md src/methods-and-traits/methods.md +#: src/SUMMARY.md src/methods-and-traits.md src/methods-and-traits/methods.md msgid "Methods" -msgstr "āĻŽā§‡āĻĨāĻĄāϏ" +msgstr "" -#: src/SUMMARY.md src/methods-and-traits/traits.md +#: src/SUMMARY.md src/methods-and-traits.md src/methods-and-traits/traits.md msgid "Traits" -msgstr "āĻŸā§āϰ⧇āχāϟ" +msgstr "" -#: src/SUMMARY.md -msgid "Implmementing Traits" -msgstr "āĻŸā§āϰ⧇āχāϟ āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ āĻ•āϰāĻž" +#: src/SUMMARY.md src/methods-and-traits/traits/implementing.md +msgid "Implementing Traits" +msgstr "" + +#: src/SUMMARY.md src/methods-and-traits/traits/supertraits.md +msgid "Supertraits" +msgstr "" #: src/SUMMARY.md src/methods-and-traits/traits/associated-types.md msgid "Associated Types" -msgstr "āϝ⧁āĻ•ā§āϤ āϟāĻžāχāĻĒ" +msgstr "" -#: src/SUMMARY.md src/methods-and-traits/deriving.md +#: src/SUMMARY.md src/methods-and-traits.md src/methods-and-traits/deriving.md msgid "Deriving" -msgstr "āφāĻšāϰāĻŖ āĻ•āϰāĻž" +msgstr "" -#: src/SUMMARY.md src/methods-and-traits/exercise.md +#: src/SUMMARY.md src/methods-and-traits.md msgid "Exercise: Generic Logger" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻœā§‡āύ⧇āϰāĻŋāĻ• āϤāĻĨā§āϝ āύāĻŋāĻ°ā§āĻŽāĻžāϤāĻž" +msgstr "" -#: src/SUMMARY.md src/generics.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-2.md src/generics.md msgid "Generics" -msgstr "āĻœā§‡āύ⧇āϰāĻŋāĻ•āϏ" +msgstr "" -#: src/SUMMARY.md src/generics/generic-functions.md +#: src/SUMMARY.md src/generics.md src/generics/generic-functions.md msgid "Generic Functions" -msgstr "āĻœā§‡āύ⧇āϰāĻŋāĻ• āĻĒāĻĻā§āϧāϤāĻŋ" +msgstr "" + +#: src/SUMMARY.md src/generics.md src/generics/trait-bounds.md +msgid "Trait Bounds" +msgstr "" -#: src/SUMMARY.md src/generics/generic-data.md +#: src/SUMMARY.md src/generics.md src/generics/generic-data.md msgid "Generic Data Types" -msgstr "āĻœā§‡āύ⧇āϰāĻŋāĻ• āĻĄā§‡āϟāĻž āϟāĻžāχāĻĒ" +msgstr "" -#: src/SUMMARY.md src/generics/trait-bounds.md -msgid "Trait Bounds" -msgstr "āĻŸā§āϰ⧇āχāϟ āĻāϰ āϏ⧀āĻŽāĻžāύāĻž" +#: src/SUMMARY.md src/generics.md src/generics/generic-traits.md +msgid "Generic Traits" +msgstr "" #: src/SUMMARY.md src/generics/impl-trait.md msgid "`impl Trait`" -msgstr "`impl Trait`" +msgstr "" + +#: src/SUMMARY.md src/generics/dyn-trait.md +msgid "`dyn Trait`" +msgstr "" #: src/SUMMARY.md src/generics/exercise.md msgid "Exercise: Generic `min`" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻœā§‡āύ⧇āϰāĻŋāĻ• `min`" +msgstr "" #: src/SUMMARY.md msgid "Day 2: Afternoon" -msgstr "āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āĻŦāĻŋāĻ•āĻžāϞ" +msgstr "" + +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-2-afternoon.md src/closures.md +msgid "Closures" +msgstr "" + +#: src/SUMMARY.md src/closures.md src/closures/syntax.md +msgid "Closure Syntax" +msgstr "" + +#: src/SUMMARY.md src/closures.md src/closures/capturing.md +msgid "Capturing" +msgstr "" + +#: src/SUMMARY.md src/closures.md +msgid "Closure Traits" +msgstr "" -#: src/SUMMARY.md src/std-types.md +#: src/SUMMARY.md src/closures.md src/closures/exercise.md +msgid "Exercise: Log Filter" +msgstr "" + +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-2-afternoon.md src/std-types.md msgid "Standard Library Types" -msgstr "āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋāϰ āϟāĻžāχāĻĒ" +msgstr "" -#: src/SUMMARY.md src/std-types/std.md +#: src/SUMMARY.md src/std-types.md src/std-types/std.md msgid "Standard Library" -msgstr "āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ" +msgstr "" -#: src/SUMMARY.md src/std-types/docs.md +#: src/SUMMARY.md src/std-types.md src/std-types/docs.md msgid "Documentation" -msgstr "āĻĻāϞāĻŋāϞ" +msgstr "" #: src/SUMMARY.md msgid "`Option`" -msgstr "`Option`" +msgstr "" -#: src/SUMMARY.md +#: src/SUMMARY.md src/error-handling/result.md msgid "`Result`" -msgstr "`Result`" +msgstr "" #: src/SUMMARY.md src/android/aidl/types/primitives.md #: src/android/interoperability/cpp/type-mapping.md msgid "`String`" -msgstr "`String`" +msgstr "" #: src/SUMMARY.md src/std-types/vec.md msgid "`Vec`" -msgstr "`Vec`" +msgstr "" #: src/SUMMARY.md src/std-types/hashmap.md src/bare-metal/no_std.md msgid "`HashMap`" -msgstr "`HashMap`" +msgstr "" -#: src/SUMMARY.md src/std-types/exercise.md +#: src/SUMMARY.md src/std-types.md src/std-types/exercise.md msgid "Exercise: Counter" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ: āϏāĻ‚āĻ–ā§āϝāĻžā§ŸāĻ•" +msgstr "" -#: src/SUMMARY.md src/std-traits.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-2-afternoon.md src/std-traits.md msgid "Standard Library Traits" -msgstr "āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋāϰ āĻŸā§āϰ⧇āχāϟ" +msgstr "" -#: src/SUMMARY.md src/std-traits/comparisons.md src/async.md +#: src/SUMMARY.md src/std-traits.md src/std-traits/comparisons.md +#: src/concurrency/welcome-async.md msgid "Comparisons" -msgstr "āϤ⧁āϞāύāĻžāϏāĻŽā§‚āĻš" +msgstr "" -#: src/SUMMARY.md src/std-traits/operators.md +#: src/SUMMARY.md src/std-traits.md src/std-traits/operators.md msgid "Operators" -msgstr "āĻ•āĻžāĻ°ā§āϝāĻ•āĻžāϰāĻ•" +msgstr "" #: src/SUMMARY.md src/std-traits/from-and-into.md msgid "`From` and `Into`" -msgstr "`From` āĻāĻŦāĻ‚ `Into`" +msgstr "" -#: src/SUMMARY.md src/std-traits/casting.md +#: src/SUMMARY.md src/std-traits.md src/std-traits/casting.md msgid "Casting" -msgstr "āύāĻŋāĻ•ā§āώ⧇āĻĒāĻŖ āĻ•āϰāĻž" +msgstr "" #: src/SUMMARY.md src/std-traits/read-and-write.md msgid "`Read` and `Write`" -msgstr "`Read` āĻāĻŦāĻ‚ `Write`" +msgstr "" #: src/SUMMARY.md msgid "`Default`, struct update syntax" -msgstr "`Default`, āĻ¸ā§āĻŸā§āϰāĻžāĻ•ā§āĻŸā§‡āϰ āĻšāĻžāϞāύāĻžāĻ—āĻžāĻĻ āĻ•āϰāĻŦāĻžāϰ āĻŦāĻžāĻ•ā§āϝ āĻ—āĻ āύ" - -#: src/SUMMARY.md src/std-traits/closures.md -msgid "Closures" -msgstr "āĻ•ā§āϞ⧋āϜāĻžāϰ⧇āϏ (Closures)" +msgstr "" -#: src/SUMMARY.md src/std-traits/exercise.md +#: src/SUMMARY.md src/std-traits.md src/std-traits/exercise.md msgid "Exercise: ROT13" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āϰ⧋.āĻ“.t ā§§ā§Š (ROT 13)" +msgstr "" #: src/SUMMARY.md msgid "Day 3: Morning" -msgstr "āϤ⧃āϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ" +msgstr "" -#: src/SUMMARY.md src/memory-management.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-3.md src/memory-management.md msgid "Memory Management" -msgstr "āĻŽā§‡āĻŽā§‹āϰāĻŋ āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻž" +msgstr "" -#: src/SUMMARY.md src/memory-management/review.md +#: src/SUMMARY.md src/memory-management.md src/memory-management/review.md msgid "Review of Program Memory" -msgstr "āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§‡āϰ āĻ¸ā§āĻŽā§ƒāϤāĻŋāϰ (Memory) āĻŦā§āϝāĻžāĻĒāĻžāϰ⧇ āĻĒāĻ°ā§āϝāĻžāϞ⧋āϚāύāĻž" +msgstr "" -#: src/SUMMARY.md src/memory-management/approaches.md +#: src/SUMMARY.md src/memory-management.md src/memory-management/approaches.md msgid "Approaches to Memory Management" -msgstr "āĻŽā§‡āĻŽāϰāĻŋ āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻžāϰ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻĒāĻĻā§āϧāϤāĻŋ" +msgstr "" -#: src/SUMMARY.md src/memory-management/ownership.md +#: src/SUMMARY.md src/memory-management.md src/memory-management/ownership.md msgid "Ownership" -msgstr "āĻŽāĻžāϞāĻŋāĻ•āĻžāύāĻž" +msgstr "" -#: src/SUMMARY.md src/memory-management/move.md +#: src/SUMMARY.md src/memory-management.md src/memory-management/move.md msgid "Move Semantics" -msgstr "āĻŽā§āĻ­ āĻāϰ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŦāĻŋāĻĻā§āϝāĻž" +msgstr "" #: src/SUMMARY.md msgid "`Clone`" -msgstr "`Clone`" +msgstr "" -#: src/SUMMARY.md src/memory-management/copy-types.md +#: src/SUMMARY.md src/memory-management.md src/memory-management/copy-types.md msgid "Copy Types" -msgstr "āĻ…āύ⧁āϞāĻŋāĻĒāĻŋ āϟāĻžāχāĻĒāϗ⧁āϞāĻŋ" +msgstr "" #: src/SUMMARY.md msgid "`Drop`" -msgstr "`Drop`" +msgstr "" -#: src/SUMMARY.md src/memory-management/exercise.md +#: src/SUMMARY.md src/memory-management.md src/memory-management/exercise.md msgid "Exercise: Builder Type" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āϰāϚāύāĻžāĻ•āĻžāϰ⧀ āϟāĻžāχāĻĒ" +msgstr "" -#: src/SUMMARY.md src/smart-pointers.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-3.md src/smart-pointers.md msgid "Smart Pointers" -msgstr "āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻžāύ āχāĻ™ā§āĻ—āĻŋāϤāĻ•āĻžāϰ⧀ (āĻ¸ā§āĻŽāĻžāĻ°ā§āϟ āĻĒā§Ÿā§‡āĻ¨ā§āϟāĻžāϰ)" +msgstr "" #: src/SUMMARY.md src/smart-pointers/box.md #: src/android/interoperability/cpp/type-mapping.md msgid "`Box`" -msgstr "`Box`" +msgstr "" #: src/SUMMARY.md src/smart-pointers/rc.md msgid "`Rc`" -msgstr "`Rc`" +msgstr "" -#: src/SUMMARY.md src/smart-pointers/trait-objects.md -msgid "Trait Objects" -msgstr "Trait Objects" +#: src/SUMMARY.md src/smart-pointers.md src/smart-pointers/trait-objects.md +msgid "Owned Trait Objects" +msgstr "" -#: src/SUMMARY.md src/smart-pointers/exercise.md +#: src/SUMMARY.md src/smart-pointers.md src/smart-pointers/exercise.md msgid "Exercise: Binary Tree" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻĻ⧁āχ āϚāϞāĻŦāĻŋāĻļāĻŋāĻˇā§āϟ āϤāϰ⧂" +msgstr "" #: src/SUMMARY.md msgid "Day 3: Afternoon" -msgstr "āϤ⧃āϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āĻŦāĻŋāĻ•āĻžāϞ" +msgstr "" -#: src/SUMMARY.md src/borrowing.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-3-afternoon.md src/borrowing.md msgid "Borrowing" -msgstr "āϧāĻžāϰ āύ⧇āĻ“āϝāĻŧāĻž" +msgstr "" -#: src/SUMMARY.md src/borrowing/shared.md +#: src/SUMMARY.md src/borrowing.md src/borrowing/shared.md msgid "Borrowing a Value" -msgstr "āĻāĻ•āϟāĻŋ āĻŽā§āϝāĻžāύ āϧāĻžāϰ āύ⧇āĻ“ā§ŸāĻž" +msgstr "" -#: src/SUMMARY.md src/borrowing/borrowck.md +#: src/SUMMARY.md src/borrowing.md src/borrowing/borrowck.md msgid "Borrow Checking" -msgstr "āϧāĻžāϰ āύ⧇āĻ“ā§ŸāĻž āĻŽā§āϝāĻžāύ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻž" +msgstr "" -#: src/SUMMARY.md src/borrowing/interior-mutability.md +#: src/SUMMARY.md src/borrowing.md src/borrowing/examples.md +msgid "Borrow Errors" +msgstr "" + +#: src/SUMMARY.md src/borrowing.md src/borrowing/interior-mutability.md msgid "Interior Mutability" -msgstr "āφāĻ¨ā§āϤāσāĻ•āĻžāĻ°ā§āϝāĻ•ā§āώāĻŽāϤāĻž" +msgstr "" -#: src/SUMMARY.md src/borrowing/exercise.md -msgid "Exercise: Health Statistics" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻ¸ā§āĻŦāĻžāĻ¸ā§āĻĨā§āϝ āĻĒāϰāĻŋāϏāĻ‚āĻ–ā§āϝāĻžāύ" +#: src/SUMMARY.md src/borrowing/interior-mutability/cell.md +msgid "`Cell`" +msgstr "" -#: src/SUMMARY.md src/slices-and-lifetimes.md -msgid "Slices and Lifetimes" -msgstr "āϟ⧁āĻ•āϰāĻž āĻāĻŦāĻ‚ āĻœā§€āĻŦāύāĻ•āĻžāϞ" +#: src/SUMMARY.md src/borrowing/interior-mutability/refcell.md +msgid "`RefCell`" +msgstr "" -#: src/SUMMARY.md -msgid "Slices: `&[T]`" -msgstr "āϟ⧁āĻ•āϰāĻž: `&[T]`" +#: src/SUMMARY.md src/borrowing.md src/borrowing/exercise.md +msgid "Exercise: Wizard's Inventory" +msgstr "" + +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-3-afternoon.md src/lifetimes.md +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Lifetimes" +msgstr "" -#: src/SUMMARY.md src/slices-and-lifetimes/str.md -msgid "String References" -msgstr "āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ" +#: src/SUMMARY.md src/lifetimes.md +msgid "Borrowing and Functions" +msgstr "" -#: src/SUMMARY.md src/slices-and-lifetimes/lifetime-annotations.md -msgid "Lifetime Annotations" -msgstr "āĻœā§€āĻŦāύāĻ•āĻžāϞ⧇āϰ āĻŸā§€āĻ•āĻž" +#: src/SUMMARY.md src/lifetimes.md src/lifetimes/returning-borrows.md +msgid "Returning Borrows" +msgstr "" -#: src/SUMMARY.md +#: src/SUMMARY.md src/lifetimes.md src/lifetimes/multiple-borrows.md +msgid "Multiple Borrows" +msgstr "" + +#: src/SUMMARY.md src/lifetimes.md src/lifetimes/borrow-both.md +msgid "Borrow Both" +msgstr "" + +#: src/SUMMARY.md src/lifetimes.md src/lifetimes/borrow-one.md +msgid "Borrow One" +msgstr "" + +#: src/SUMMARY.md src/lifetimes.md src/lifetimes/lifetime-elision.md msgid "Lifetime Elision" -msgstr "āĻœā§€āĻŦāύāĻ•āĻžāϞ⧇āϰ āϞ⧇āĻžāĻĒ" +msgstr "" -#: src/SUMMARY.md -msgid "Struct Lifetimes" -msgstr "āĻ¸ā§āĻŸā§āϰāĻžāĻ•ā§āĻŸā§‡āϰ āĻœā§€āĻŦāύāĻ•āĻžāϞ" +#: src/SUMMARY.md src/lifetimes.md src/lifetimes/struct-lifetimes.md +msgid "Lifetimes in Data Structures" +msgstr "" -#: src/SUMMARY.md src/slices-and-lifetimes/exercise.md +#: src/SUMMARY.md src/lifetimes.md src/lifetimes/exercise.md msgid "Exercise: Protobuf Parsing" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻĒā§āϰ⧋āĻŸā§‹āĻŦāĻžāĻĢ āĻĒāĻĻāĻžāĻ¨ā§āĻŦāϝāĻŧ āĻ•āϰāĻž" +msgstr "" #: src/SUMMARY.md msgid "Day 4: Morning" -msgstr "āϚāĻĨ⧁āĻ°ā§āϤ āĻĻāĻŋāύ: āϏāĻ•āĻžāϞāĻŦ⧇āϞāĻž" +msgstr "" -#: src/SUMMARY.md src/iterators.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-4.md src/iterators.md msgid "Iterators" -msgstr "āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋāĻ•āĻžāϰ⧀" +msgstr "" -#: src/SUMMARY.md src/iterators/iterator.md src/bare-metal/no_std.md -msgid "`Iterator`" -msgstr "`Iterator`" +#: src/SUMMARY.md src/iterators.md +msgid "Motivation" +msgstr "" + +#: src/SUMMARY.md src/iterators/iterator.md +msgid "`Iterator` Trait" +msgstr "" + +#: src/SUMMARY.md src/iterators/helpers.md +msgid "`Iterator` Helper Methods" +msgstr "" + +#: src/SUMMARY.md src/iterators/collect.md +msgid "`collect`" +msgstr "" #: src/SUMMARY.md src/iterators/intoiterator.md msgid "`IntoIterator`" -msgstr "`IntoIterator`" - -#: src/SUMMARY.md -msgid "`FromIterator`" -msgstr "`FromIterator`" +msgstr "" -#: src/SUMMARY.md src/iterators/exercise.md +#: src/SUMMARY.md src/iterators.md src/iterators/exercise.md msgid "Exercise: Iterator Method Chaining" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋāĻ•āĻžāϰ⧀ āĻŽāĻžāϞāĻžāĻŦāĻ¨ā§āϧāύ" +msgstr "" -#: src/SUMMARY.md src/modules.md src/modules/modules.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-4.md src/modules.md src/modules/modules.md msgid "Modules" -msgstr "Modules" +msgstr "" -#: src/SUMMARY.md src/modules/filesystem.md +#: src/SUMMARY.md src/modules.md src/modules/filesystem.md msgid "Filesystem Hierarchy" -msgstr "Filesystem Hierarchy" +msgstr "" -#: src/SUMMARY.md src/modules/visibility.md +#: src/SUMMARY.md src/modules.md src/modules/visibility.md msgid "Visibility" -msgstr "āĻĻ⧃āĻļā§āϝāĻŽāĻžāύāϤāĻž" +msgstr "" + +#: src/SUMMARY.md src/modules.md +msgid "Encapsulation" +msgstr "" #: src/SUMMARY.md msgid "`use`, `super`, `self`" -msgstr "`use`, `super`, `self`" +msgstr "" -#: src/SUMMARY.md src/modules/exercise.md +#: src/SUMMARY.md src/modules.md src/modules/exercise.md msgid "Exercise: Modules for a GUI Library" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻāĻ•āϟāĻŋ āϜāĻŋ.āχāω.āφāχ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ āĻŦāĻžāύāĻžāĻŦāĻžāϰ āĻŽāĻĄāĻŋāωāϞ" +msgstr "" -#: src/SUMMARY.md src/testing.md src/chromium/testing.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-4.md src/testing.md src/chromium/testing.md msgid "Testing" -msgstr "āĻŸā§‡āĻ¸ā§āϟāĻŋāĻ‚" +msgstr "" -#: src/SUMMARY.md -msgid "Test Modules" -msgstr "āĻŸā§‡āĻ¸ā§āϟ āĻŽāĻĄāĻŋāωāϞ" +#: src/SUMMARY.md src/testing.md src/testing/unit-tests.md +msgid "Unit Tests" +msgstr "" -#: src/SUMMARY.md src/testing/other.md +#: src/SUMMARY.md src/testing.md src/testing/other.md msgid "Other Types of Tests" -msgstr "āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āϟāĻžāχāĻĒ⧇āϰ āĻĒāϰ⧀āĻ•ā§āώāĻž" - -#: src/SUMMARY.md src/testing/useful-crates.md -msgid "Useful Crates" -msgstr "āωāĻĒāĻ•āĻžāϰ⧀ āĻ•ā§āϰ⧇āϟāϏāĻŽā§‚āĻš" - -#: src/SUMMARY.md src/testing/googletest.md -msgid "GoogleTest" -msgstr "GoogleTest" - -#: src/SUMMARY.md src/testing/mocking.md -msgid "Mocking" -msgstr "āωāĻĒāĻšāĻžāϏ āĻ•āϰāĻž" +msgstr "" -#: src/SUMMARY.md src/testing/lints.md +#: src/SUMMARY.md src/testing.md src/testing/lints.md msgid "Compiler Lints and Clippy" -msgstr "āϏāĻ‚āĻ•āϞāύāĻ•āĻžāϰ⧀ (āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ) āĻāϰ āϞāĻŋāĻ¨ā§āϟāϗ⧁āϞāĻŋ āĻāĻŦāĻ‚ āĻ•ā§āϞāĻŋāĻĒāĻŋ" +msgstr "" -#: src/SUMMARY.md src/testing/exercise.md +#: src/SUMMARY.md src/testing.md src/testing/exercise.md msgid "Exercise: Luhn Algorithm" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āϞ⧁āύ āĻāϰ āĻ—āĻžāĻŖāĻŋāϤāĻŋāĻ• āĻĒāϰāĻŋāĻ­āĻžāώāĻž" +msgstr "" #: src/SUMMARY.md msgid "Day 4: Afternoon" -msgstr "āϚāϤ⧁āĻ°ā§āĻĨ āĻĻāĻŋāύ: āĻĻ⧁āĻĒ⧁āϰāĻŦ⧇āϞāĻž" +msgstr "" -#: src/SUMMARY.md src/error-handling.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-4-afternoon.md src/error-handling.md +#: src/idiomatic/welcome.md msgid "Error Handling" -msgstr "āĻ¤ā§āϰ⧁āϟāĻŋ āϏāĻžāĻŽāϞāĻžāύ⧋" +msgstr "" -#: src/SUMMARY.md src/error-handling/panics.md +#: src/SUMMARY.md src/error-handling.md src/error-handling/panics.md msgid "Panics" -msgstr "Panics-āĻĒā§āϝāĻžāύāĻŋāĻ•" +msgstr "" -#: src/SUMMARY.md src/error-handling/try.md +#: src/SUMMARY.md src/error-handling.md src/error-handling/try.md msgid "Try Operator" -msgstr "Try āĻ•āĻžāĻ°ā§āϝāĻ•āĻžāϰāĻ•" +msgstr "" -#: src/SUMMARY.md src/error-handling/try-conversions.md +#: src/SUMMARY.md src/error-handling.md src/error-handling/try-conversions.md msgid "Try Conversions" -msgstr "Try āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ" +msgstr "" #: src/SUMMARY.md msgid "`Error` Trait" -msgstr "`Error` āĻŸā§āϰ⧇āχāϟ" +msgstr "" -#: src/SUMMARY.md src/error-handling/thiserror-and-anyhow.md -msgid "`thiserror` and `anyhow`" -msgstr "`thiserror` āĻāĻŦāĻ‚ `anyhow`" +#: src/SUMMARY.md src/error-handling/thiserror.md +msgid "`thiserror`" +msgstr "" + +#: src/SUMMARY.md src/error-handling/anyhow.md src/idiomatic/welcome.md +msgid "`anyhow`" +msgstr "" #: src/SUMMARY.md msgid "Exercise: Rewriting with `Result`" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: `Result` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āφāĻŦāĻžāϰ āϞ⧇āĻ–āĻž" +msgstr "" -#: src/SUMMARY.md src/unsafe-rust.md src/unsafe-rust/unsafe.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/welcome-day-4-afternoon.md src/unsafe-rust.md src/unsafe-rust/unsafe.md +#: src/unsafe-deep-dive/introduction/responsibility-shift.md msgid "Unsafe Rust" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āϰāĻžāĻ¸ā§āϟ" +msgstr "" -#: src/SUMMARY.md +#: src/SUMMARY.md src/unsafe-rust.md msgid "Unsafe" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ" +msgstr "" -#: src/SUMMARY.md src/unsafe-rust/dereferencing.md +#: src/SUMMARY.md src/unsafe-rust.md src/unsafe-rust/dereferencing.md msgid "Dereferencing Raw Pointers" -msgstr "āϰ āĻĒāϝāĻŧ⧇āĻ¨ā§āϟāĻžāϰ āĻĄāĻŋ-āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ āĻ•āϰāĻž" +msgstr "" -#: src/SUMMARY.md src/unsafe-rust/mutable-static.md +#: src/SUMMARY.md src/unsafe-rust.md src/unsafe-rust/mutable-static.md msgid "Mutable Static Variables" -msgstr "āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύāϝ⧋āĻ—ā§āϝ āĻ¸ā§āĻŸā§āϝāĻžāϟāĻŋāĻ• āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϏ" +msgstr "" -#: src/SUMMARY.md src/unsafe-rust/unions.md +#: src/SUMMARY.md src/unsafe-rust.md src/unsafe-rust/unions.md msgid "Unions" -msgstr "Unions" +msgstr "" -#: src/SUMMARY.md src/unsafe-rust/unsafe-functions.md +#: src/SUMMARY.md src/unsafe-rust.md src/unsafe-rust/unsafe-functions.md msgid "Unsafe Functions" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āĻ•āĻžāϜāĻ•āĻ°ā§āĻŽ" +msgstr "" -#: src/SUMMARY.md +#: src/SUMMARY.md src/unsafe-rust/unsafe-functions/rust.md +msgid "Unsafe Rust Functions" +msgstr "" + +#: src/SUMMARY.md src/unsafe-rust/unsafe-functions/extern-c.md +msgid "Unsafe External Functions" +msgstr "" + +#: src/SUMMARY.md src/unsafe-rust/unsafe-functions/calling.md +msgid "Calling Unsafe Functions" +msgstr "" + +#: src/SUMMARY.md src/unsafe-rust.md msgid "Unsafe Traits" -msgstr "āύāĻžāύāĻžāύ āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āĻŸā§āϰ⧇āχāϟ" +msgstr "" -#: src/SUMMARY.md +#: src/SUMMARY.md src/unsafe-rust.md msgid "Exercise: FFI Wrapper" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻāĻĢ . āĻāĻĢ . āφāχ āĻŽā§‹āĻĄāĻŧāĻ•" +msgstr "" -#: src/SUMMARY.md src/bare-metal/android.md +#: src/SUMMARY.md msgid "Android" -msgstr "Android" +msgstr "" #: src/SUMMARY.md src/android/setup.md src/chromium/setup.md msgid "Setup" -msgstr "āϏ⧇āϟāφāĻĒ" +msgstr "" #: src/SUMMARY.md src/android/build-rules.md msgid "Build Rules" -msgstr "āĻ—āĻ āύ⧇āϰ āύāĻŋāϝāĻŧāĻŽ" +msgstr "" #: src/SUMMARY.md msgid "Binary" -msgstr "āĻŦāĻžāχāύāĻžāϰāĻŋ" +msgstr "" #: src/SUMMARY.md msgid "Library" -msgstr "āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ" +msgstr "" #: src/SUMMARY.md src/android/aidl.md msgid "AIDL" -msgstr "AIDL" +msgstr "" #: src/SUMMARY.md src/android/aidl/birthday-service.md msgid "Birthday Service Tutorial" -msgstr "āϜāĻ¨ā§āĻŽāĻĻāĻŋāύ⧇āϰ āϏ⧇āĻŦāĻžāϰ āϟāĻŋāωāĻŸā§‹āϰāĻŋāϝāĻŧāĻžāϞ" +msgstr "" #: src/SUMMARY.md msgid "Interface" -msgstr "āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ" +msgstr "" #: src/SUMMARY.md msgid "Service API" -msgstr "āϏāĻžāĻ°ā§āĻ­āĻŋāϏ āĻ . āĻĒāĻŋ . āφāχ" +msgstr "" #: src/SUMMARY.md msgid "Service" -msgstr "āϏāĻžāĻ°ā§āĻ­āĻŋāϏ" +msgstr "" #: src/SUMMARY.md msgid "Server" -msgstr "āϏāĻžāĻ°ā§āĻ­āĻžāϰ" +msgstr "" #: src/SUMMARY.md src/android/aidl/example-service/deploy.md msgid "Deploy" -msgstr "āĻ¸ā§āĻĨāĻžāĻĒāύ" +msgstr "" #: src/SUMMARY.md msgid "Client" -msgstr "āĻ•ā§āϞāĻžāϝāĻŧ⧇āĻ¨ā§āϟ" +msgstr "" #: src/SUMMARY.md src/android/aidl/example-service/changing-definition.md msgid "Changing API" -msgstr "API āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ" +msgstr "" #: src/SUMMARY.md msgid "Updating Implementations" -msgstr "āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύāϗ⧁āϞāĻŋāϰ āĻšāĻžāϞ āύāĻžāĻ—āĻžāĻĻ āĻ•āϰāĻž" +msgstr "" #: src/SUMMARY.md msgid "AIDL Types" -msgstr "āĻ.āφāχ.āĻĻāĻŋ.āĻāϞ āϟāĻžāχāĻĒ" +msgstr "" #: src/SUMMARY.md src/android/aidl/types/primitives.md msgid "Primitive Types" -msgstr "āĻŦāύāĻŋāϝāĻŧāĻžāĻĻāĻŋ āϟāĻžāχāĻĒ" +msgstr "" #: src/SUMMARY.md src/android/aidl/types/arrays.md msgid "Array Types" -msgstr "āĻ…ā§āϝāĻžāϰ⧇ āĻāϰ āϟāĻžāχāĻĒ" +msgstr "" #: src/SUMMARY.md src/android/aidl/types/objects.md msgid "Sending Objects" -msgstr "āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āĻĒāĻžāĻ āĻžāύ⧋" +msgstr "" #: src/SUMMARY.md src/android/aidl/types/parcelables.md msgid "Parcelables" -msgstr "āĻĒāĻžāĻ°ā§āϏ⧇āϞāĻŦāϞ⧇āϏ (āĻĒ⧁āϞāĻŋāĻ¨ā§āĻĻāĻž āĻŦāĻžāύāĻžāύ⧋ āϝāĻžā§Ÿ āϝāĻžāϕ⧇)" +msgstr "" #: src/SUMMARY.md src/android/aidl/types/file-descriptor.md msgid "Sending Files" -msgstr "āĻāĻ•āĻžāϧāĻŋāĻ• āĻĢāĻžāχāϞ āĻĒāĻžāĻ āĻžāύ⧋" +msgstr "" + +#: src/SUMMARY.md src/android/testing/googletest.md +msgid "GoogleTest" +msgstr "" + +#: src/SUMMARY.md src/android/testing/mocking.md +msgid "Mocking" +msgstr "" #: src/SUMMARY.md src/android/logging.md src/bare-metal/aps/logging.md msgid "Logging" -msgstr "Logging" +msgstr "" #: src/SUMMARY.md src/android/interoperability.md msgid "Interoperability" -msgstr "āφāĻ¨ā§āϤāσāĻ•āĻžāĻ°ā§āϝāĻ•ā§āώāĻŽāϤāĻž" +msgstr "" #: src/SUMMARY.md msgid "With C" -msgstr "C āĻāϰ āϏāĻžāĻĨ⧇" +msgstr "" + +#: src/SUMMARY.md src/android/interoperability/with-c/c-library.md +msgid "A Simple C Library" +msgstr "" #: src/SUMMARY.md -msgid "Calling C with Bindgen" -msgstr "Bindgen āĻāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ C āϕ⧇ āĻĄāĻžāĻ•āĻž" +msgid "Bindgen" +msgstr "" + +#: src/SUMMARY.md src/android/interoperability/with-c/run-our-binary.md +msgid "Running Our Binary" +msgstr "" + +#: src/SUMMARY.md src/android/interoperability/with-c/rust-library.md +msgid "A Simple Rust Library" +msgstr "" #: src/SUMMARY.md msgid "Calling Rust from C" -msgstr "C āĻĨ⧇āϕ⧇ āϰāĻžāĻ¸ā§āϟ āϕ⧇ āĻĄāĻžāĻ•āĻž" +msgstr "" #: src/SUMMARY.md src/android/interoperability/cpp.md msgid "With C++" -msgstr "C++āĻāϰ āϏāĻžāĻĨ⧇" +msgstr "" #: src/SUMMARY.md src/android/interoperability/cpp/bridge.md msgid "The Bridge Module" -msgstr "Bridge āĻŽāĻĄāĻŋāωāϞ" +msgstr "" #: src/SUMMARY.md msgid "Rust Bridge" -msgstr "āϰāĻžāĻ¸ā§āϟ Bridge" +msgstr "" #: src/SUMMARY.md src/android/interoperability/cpp/generated-cpp.md msgid "Generated C++" -msgstr "āωāĻ¤ā§āĻĒāĻ¨ā§āύ āĻšāĻ“ā§ŸāĻž C++ āϕ⧋āĻĄ" +msgstr "" #: src/SUMMARY.md msgid "C++ Bridge" -msgstr "C++ Bridge" +msgstr "" #: src/SUMMARY.md src/android/interoperability/cpp/shared-types.md msgid "Shared Types" -msgstr "āĻ…āĻ‚āĻļ⧇ āĻŽāĻžāϞāĻŋāĻ•āĻžāύāĻžāϧ⧀āύ āϟāĻžāχāĻĒāϗ⧁āϞāĻŋ" +msgstr "" #: src/SUMMARY.md src/android/interoperability/cpp/shared-enums.md msgid "Shared Enums" -msgstr "āĻ…āĻ‚āĻļ⧇ āĻŽāĻžāϞāĻŋāĻ•āĻžāύāĻžāϧ⧀āύ āĻ—āĻŖāύāĻžāĻ•āĻžāϰ⧀ (āĻļā§‡ā§ŸāĻžāĻ°ā§āĻĄ āχāύ⧁āĻŽā§āϏ)" +msgstr "" #: src/SUMMARY.md src/android/interoperability/cpp/rust-result.md msgid "Rust Error Handling" -msgstr "āϰāĻžāĻ¸ā§āϟ āĻāϰ āĻ¤ā§āϰ⧁āϟāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž" +msgstr "" #: src/SUMMARY.md src/android/interoperability/cpp/cpp-exception.md msgid "C++ Error Handling" -msgstr "C++ āĻāϰ āĻ¤ā§āϰ⧁āϟāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž" +msgstr "" #: src/SUMMARY.md src/android/interoperability/cpp/type-mapping.md msgid "Additional Types" -msgstr "āφāϰ⧋ āĻ•āĻŋāϛ⧁ āϟāĻžāχāĻĒ" +msgstr "" #: src/SUMMARY.md -msgid "Building for Android: C++" -msgstr "āĻāĻ¨ā§āĻĄā§āϰ⧋āχāĻĄ āĻāϰ āϜāĻ¨ā§āϝ⧇ āĻŦāĻžāύāĻžāύ⧋: C++" +msgid "Building for Android: Genrules" +msgstr "" #: src/SUMMARY.md -msgid "Building for Android: Genrules" -msgstr "āĻāĻ¨ā§āĻĄā§āϰ⧋āχāĻĄ āĻāϰ āϜāĻ¨ā§āϝ⧇ āĻŦāĻžāύāĻžāύ⧋: Genrules" +msgid "Building for Android: C++" +msgstr "" #: src/SUMMARY.md msgid "Building for Android: Rust" -msgstr "āĻāĻ¨ā§āĻĄā§āϰ⧋āχāĻĄ āĻāϰ āϜāĻ¨ā§āϝ⧇ āĻŦāĻžāύāĻžāύ⧋: āϰāĻžāĻ¸ā§āϟ" +msgstr "" #: src/SUMMARY.md msgid "With Java" -msgstr "Java āĻāϰ āϏāĻžāĻĨ⧇" - -#: src/SUMMARY.md src/exercises/android/morning.md -#: src/exercises/bare-metal/morning.md src/exercises/bare-metal/afternoon.md -#: src/exercises/concurrency/morning.md src/exercises/concurrency/afternoon.md -msgid "Exercises" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ" +msgstr "" #: src/SUMMARY.md msgid "Chromium" -msgstr "Chromium" +msgstr "" #: src/SUMMARY.md src/chromium/cargo.md msgid "Comparing Chromium and Cargo Ecosystems" -msgstr "Chromium āĻāĻŦāĻ‚ Cargo āĻāϰ āĻŦāĻžāĻ¸ā§āϤ⧁āϤāĻ¨ā§āĻ¤ā§āϰāϗ⧁āϞāĻŋāϰ āĻŽāĻ§ā§āϝ⧇ āϤ⧁āϞāύāĻž" +msgstr "" #: src/SUMMARY.md msgid "Policy" -msgstr "āĻ•āĻ°ā§āĻŽāĻĒāĻ¨ā§āĻĨāĻž" +msgstr "" #: src/SUMMARY.md msgid "Unsafe Code" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āϕ⧋āĻĄ" +msgstr "" #: src/SUMMARY.md src/chromium/build-rules/depending.md msgid "Depending on Rust Code from Chromium C++" -msgstr "āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽ C++ āĻāϰ āĻĨ⧇āϕ⧇ āφāϏāĻž āϰāĻžāĻ¸ā§āϟ āϕ⧋āĻĄ āĻāϰ āĻ“āĻĒāϰ⧇ āύāĻŋāĻ°ā§āĻ­āϰ āĻ•āϰāϛ⧇" +msgstr "" #: src/SUMMARY.md src/chromium/build-rules/vscode.md msgid "Visual Studio Code" -msgstr "Visual Studio Code" +msgstr "" -#: src/SUMMARY.md src/exercises/chromium/third-party.md +#: src/SUMMARY.md src/lifetimes/exercise.md +#: src/exercises/chromium/third-party.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md msgid "Exercise" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀" +msgstr "" #: src/SUMMARY.md src/chromium/testing/rust-gtest-interop.md msgid "`rust_gtest_interop` Library" -msgstr "`rust_gtest_interop` āϕ⧋āĻĄ āϏāĻ‚āĻ—ā§āϰāĻš āĻŦāĻž āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ" +msgstr "" #: src/SUMMARY.md src/chromium/testing/build-gn.md msgid "GN Rules for Rust Tests" -msgstr "āϰāĻžāĻ¸ā§āϟ āĻ āĻĒāϰ⧀āĻ•ā§āώāĻž-āύāĻŋāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻŦāĻžāϰ āϜāĻ¨ā§āϝ⧇ āϜāĻŋ . āĻāύ āύāĻŋ⧟āĻŽāĻžāĻŦāϞ⧀" +msgstr "" #: src/SUMMARY.md src/chromium/testing/chromium-import-macro.md msgid "`chromium::import!` Macro" -msgstr "`chromium::import!` āĻŽā§āϝāĻžāĻ•ā§āϰ⧋" +msgstr "" #: src/SUMMARY.md src/chromium/interoperability-with-cpp.md msgid "Interoperability with C++" -msgstr "āϏāĻŋ++ āĻāϰ āϏāĻžāĻĨ⧇ āφāĻ¨ā§āϤāσāĻ•āĻžāĻ°ā§āϝāĻ•ā§āώāĻŽāϤāĻž" +msgstr "" #: src/SUMMARY.md src/chromium/interoperability-with-cpp/example-bindings.md msgid "Example Bindings" -msgstr "āωāĻĻāĻžāĻšāϰāĻŖ āĻŦāĻžāχāĻ¨ā§āĻĄāĻŋāĻ‚" +msgstr "" #: src/SUMMARY.md src/chromium/interoperability-with-cpp/limitations-of-cxx.md msgid "Limitations of CXX" -msgstr "āϏāĻŋ.āĻāĻ•ā§āϏ.āĻāĻ•ā§āϏ āĻāϰ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻž" +msgstr "" #: src/SUMMARY.md src/chromium/interoperability-with-cpp/error-handling.md msgid "CXX Error Handling" -msgstr "āϏāĻŋ.āĻāĻ•ā§āϏ.āĻāĻ•ā§āϏ āĻ¤ā§āϰ⧁āϟāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž" +msgstr "" #: src/SUMMARY.md msgid "Error Handling: QR Example" -msgstr "āĻ¤ā§āϰ⧁āϟāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž: āĻ•āĻŋāω.āφāϰ āωāĻĻāĻžāĻšāϰāĻŖ" +msgstr "" #: src/SUMMARY.md msgid "Error Handling: PNG Example" -msgstr "āĻ¤ā§āϰ⧁āϟāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž: āĻĒāĻŋ.āĻāύ.āϜāĻŋ āωāĻĻāĻžāĻšāϰāĻŖ" +msgstr "" #: src/SUMMARY.md msgid "Using CXX in Chromium" -msgstr "āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽ āĻ āϏāĻŋ.āĻāĻ•ā§āϏ.āĻāĻ•ā§āϏ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž" +msgstr "" #: src/SUMMARY.md src/chromium/adding-third-party-crates.md msgid "Adding Third Party Crates" -msgstr "āϤ⧃āĻ¤ā§€ā§Ÿ āĻĒāĻ•ā§āώ⧇āϰ āĻ•ā§āϰ⧇āϟ āĻœā§‹ā§œāĻž" +msgstr "" #: src/SUMMARY.md msgid "Configuring Cargo.toml" -msgstr "Cargo.toml āϏāĻœā§āϜāĻŋāϤ āĻ•āϰāĻž" +msgstr "" #: src/SUMMARY.md #: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md msgid "Configuring `gnrt_config.toml`" -msgstr "`gnrt_config.toml` āϏāĻœā§āϜāĻŋāϤ āĻ•āϰāĻž" +msgstr "" #: src/SUMMARY.md src/chromium/adding-third-party-crates/downloading-crates.md msgid "Downloading Crates" -msgstr "āĻ•ā§āϰ⧇āϟ āĻĄāĻžāωāύāϞ⧋āĻĄ āĻ•āϰāĻž" +msgstr "" #: src/SUMMARY.md #: src/chromium/adding-third-party-crates/generating-gn-build-rules.md msgid "Generating `gn` Build Rules" -msgstr "`gn` āύāĻŋāĻ°ā§āĻŽāĻžāĻŖ āύāĻŋ⧟āĻŽāĻžāĻŦāϞ⧀ āωāĻ¤ā§āĻĒāĻžāĻĻāύ āĻ•āϰāĻž" +msgstr "" #: src/SUMMARY.md src/chromium/adding-third-party-crates/resolving-problems.md msgid "Resolving Problems" -msgstr "āϏāĻŽāĻ¸ā§āϝāĻž āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰāĻž" +msgstr "" #: src/SUMMARY.md #: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md msgid "Build Scripts Which Generate Code" -msgstr "āϕ⧋āĻĄ āĻ‰ā§ŽāĻĒāĻžāĻĻāύ āĻ•āϰ⧇ āĻāĻŽāύ āύāĻŋāĻ°ā§āĻŽāĻžāĻŖ āύāĻŋ⧟āĻŽāϏāĻŽā§‚āĻš" +msgstr "" #: src/SUMMARY.md #: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md msgid "Build Scripts Which Build C++ or Take Arbitrary Actions" -msgstr "āύāĻŋāĻ°ā§āĻŽāĻžāĻŖ āύāĻŋ⧟āĻŽāϏāĻŽā§‚āĻš āϝāĻž C++ āύāĻŋāĻ°ā§āĻŽāĻžāĻŖ āĻ•āϰ⧇ āĻŦāĻž āϕ⧋āύ⧋ āχāĻšā§āĻ›āĻžāĻŽāϤ āĻ•āĻžāϜ āĻ•āϰ⧇" +msgstr "" #: src/SUMMARY.md #: src/chromium/adding-third-party-crates/depending-on-a-crate.md msgid "Depending on a Crate" -msgstr "āĻ•ā§āϰ⧇āϟ āĻāϰ āĻ“āĻĒāϰ⧇ āύāĻŋāĻ°ā§āĻ­āϰ āĻ•āϰ⧇ āϝ⧇" +msgstr "" #: src/SUMMARY.md msgid "Reviews and Audits" -msgstr "āĻĒāĻ°ā§āϝāĻžāϞ⧋āϚāύāĻž āĻāĻŦāĻ‚ āύāĻŋāϰ⧀āĻ•ā§āώāĻž" +msgstr "" #: src/SUMMARY.md msgid "Checking into Chromium Source Code" -msgstr "Chromium āĻāϰ āĻŽā§‚āϞ āϕ⧋āĻĄ āĻ āĻĸā§‹āĻ•āĻž" +msgstr "" #: src/SUMMARY.md src/chromium/adding-third-party-crates/keeping-up-to-date.md msgid "Keeping Crates Up to Date" -msgstr "āĻ•ā§āϰ⧇āϟāϗ⧁āϞāĻŋ āĻ…āĻŦāĻžāϧ āϰāĻžāĻ–āĻž" +msgstr "" #: src/SUMMARY.md msgid "Bringing It Together - Exercise" -msgstr "āϏāĻŦāĻ•āĻŋāϛ⧁ āĻāĻ•āϏāĻžāĻĨ⧇ āĻāύ⧇ āĻ•āĻŋāϛ⧁ āĻŦāĻžāύāĻžāύ⧋ - āĻ…āύ⧁āĻļā§€āϞāύ⧀" +msgstr "" #: src/SUMMARY.md src/exercises/chromium/solutions.md msgid "Exercise Solutions" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧀āϰ āϏāĻŽāĻžāϧāĻžāύāϏāĻŽā§‚āĻš" +msgstr "" #: src/SUMMARY.md msgid "Bare Metal: Morning" -msgstr "Bare Metal: āϏāĻ•āĻžāϞ" +msgstr "" #: src/SUMMARY.md src/bare-metal/no_std.md msgid "`no_std`" -msgstr "`no_std`" +msgstr "" #: src/SUMMARY.md msgid "A Minimal Example" -msgstr "āĻāĻ•āϟāĻŋ āĻ¨ā§āϝ⧂āύāϤāĻŽ āωāĻĻāĻžāĻšāϰāĻŖ" +msgstr "" #: src/SUMMARY.md src/bare-metal/no_std.md src/bare-metal/alloc.md msgid "`alloc`" -msgstr "`alloc`" +msgstr "" #: src/SUMMARY.md src/bare-metal/microcontrollers.md msgid "Microcontrollers" -msgstr "āĻŽāĻžāχāĻ•ā§āϰ⧋āĻ•āĻ¨ā§āĻŸā§āϰ⧋āϞāĻžāϰ" +msgstr "" #: src/SUMMARY.md src/bare-metal/microcontrollers/mmio.md msgid "Raw MMIO" -msgstr "āĻ…āĻĒāĻ•ā§āĻŦ āĻāĻŽ . āĻāĻŽ . āφāχ . āĻ“" +msgstr "" #: src/SUMMARY.md msgid "PACs" -msgstr "āĻĒāĻŋ . āĻ . āϏāĻŋ" +msgstr "" #: src/SUMMARY.md msgid "HAL Crates" -msgstr "HAL Crates" +msgstr "" #: src/SUMMARY.md msgid "Board Support Crates" -msgstr "Board Support Crates" +msgstr "" #: src/SUMMARY.md msgid "The Type State Pattern" -msgstr "āϟāĻžāχāĻĒ āĻāϰ āĻ…āĻŦāĻ¸ā§āĻĨāĻž āĻŦāĻŋāĻŦ⧇āϚāύāĻž āĻ•āϰ⧇ āĻāĻŽāύ āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ" +msgstr "" #: src/SUMMARY.md src/bare-metal/microcontrollers/embedded-hal.md msgid "`embedded-hal`" -msgstr "`embedded-hal`" +msgstr "" #: src/SUMMARY.md src/bare-metal/microcontrollers/probe-rs.md msgid "`probe-rs` and `cargo-embed`" -msgstr "`probe-rs` āĻāĻŦāĻ‚ `cargo-embed`" +msgstr "" #: src/SUMMARY.md src/bare-metal/microcontrollers/debugging.md msgid "Debugging" -msgstr "āĻĄāĻŋāĻŦāĻžāĻ—āĻŋāĻ‚" +msgstr "" #: src/SUMMARY.md msgid "Other Projects" -msgstr "āφāϰāĻ“ āĻĒā§āϰāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋ" +msgstr "" + +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/exercises/bare-metal/morning.md src/exercises/bare-metal/afternoon.md +#: src/concurrency/welcome.md src/concurrency/sync-exercises.md +#: src/concurrency/welcome-async.md src/concurrency/async-exercises.md +msgid "Exercises" +msgstr "" #: src/SUMMARY.md src/exercises/bare-metal/compass.md #: src/exercises/bare-metal/solutions-morning.md msgid "Compass" -msgstr "āĻ•āĻŽā§āĻĒāĻžāϏ" +msgstr "" -#: src/SUMMARY.md +#: src/SUMMARY.md src/concurrency/sync-exercises.md +#: src/concurrency/sync-exercises/solutions.md +#: src/concurrency/async-exercises.md +#: src/concurrency/async-exercises/solutions.md msgid "Solutions" -msgstr "āϏāĻŽāĻžāϧāĻžāύāϏāĻŽā§‚āĻš" +msgstr "" #: src/SUMMARY.md msgid "Bare Metal: Afternoon" -msgstr "āĻŦā§‡ā§ŸāĻžāϰ āĻŽā§‡āϟāĻžāϞ: āĻĻ⧁āĻĒ⧁āϰāĻŦ⧇āϞāĻž" +msgstr "" #: src/SUMMARY.md msgid "Application Processors" -msgstr "āĻāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āĻĒā§āϰāϏ⧇āϏāϰ" +msgstr "" #: src/SUMMARY.md src/bare-metal/aps/entry-point.md msgid "Getting Ready to Rust" -msgstr "āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āϜāĻ¨ā§āϝ⧇ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ āĻšāĻ“ā§ŸāĻž" +msgstr "" #: src/SUMMARY.md msgid "Inline Assembly" -msgstr "Inline Assembly" +msgstr "" #: src/SUMMARY.md msgid "MMIO" -msgstr "MMIO" +msgstr "" #: src/SUMMARY.md msgid "Let's Write a UART Driver" -msgstr "āϚāϞ⧁āύ āĻāĻ•āϟāĻŋ UART Driver āϞāĻŋāĻ–āĻŋ" +msgstr "" #: src/SUMMARY.md msgid "More Traits" -msgstr "āφāϰāĻ“ Traits" +msgstr "" + +#: src/SUMMARY.md src/bare-metal/aps/safemmio/using.md +msgid "Using It" +msgstr "" #: src/SUMMARY.md msgid "A Better UART Driver" -msgstr "āĻāĻ•āϟāĻŋ āωāĻ¨ā§āύāϤāϰ UART āĻĄā§āϰāĻžāχāĻ­āĻžāϰ" +msgstr "" #: src/SUMMARY.md src/bare-metal/aps/better-uart/bitflags.md msgid "Bitflags" -msgstr "Bitflags" +msgstr "" #: src/SUMMARY.md msgid "Multiple Registers" -msgstr "āĻāĻ•āĻžāϧāĻŋāĻ• āϰ⧇āϜāĻŋāĻ¸ā§āϟāĻžāϰāϏ" +msgstr "" #: src/SUMMARY.md src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md msgid "Driver" -msgstr "āϚāĻžāϞāĻ• āĻŦāĻž āĻĄā§āϰāĻžāχāĻ­āĻžāϰ" +msgstr "" -#: src/SUMMARY.md -msgid "Using It" -msgstr "āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž" +#: src/SUMMARY.md src/bare-metal/aps/safemmio/registers.md +msgid "safe-mmio" +msgstr "" -#: src/SUMMARY.md src/bare-metal/aps/exceptions.md +#: src/SUMMARY.md src/error-handling/result.md src/bare-metal/aps/exceptions.md +#: src/bare-metal/aps/aarch64-rt/exceptions.md msgid "Exceptions" -msgstr "āĻŦā§āϝāϤāĻŋāĻ•ā§āϰāĻŽ" +msgstr "" + +#: src/SUMMARY.md src/bare-metal/aps/aarch64-rt.md +msgid "aarch64-rt" +msgstr "" + +#: src/SUMMARY.md +msgid "Useful Crates" +msgstr "" #: src/SUMMARY.md src/bare-metal/useful-crates/zerocopy.md msgid "`zerocopy`" -msgstr "`zerocopy`" +msgstr "" #: src/SUMMARY.md src/bare-metal/useful-crates/aarch64-paging.md msgid "`aarch64-paging`" -msgstr "`aarch64-paging`" +msgstr "" #: src/SUMMARY.md src/bare-metal/useful-crates/buddy_system_allocator.md msgid "`buddy_system_allocator`" -msgstr "`buddy_system_allocator`" +msgstr "" #: src/SUMMARY.md src/bare-metal/useful-crates/tinyvec.md msgid "`tinyvec`" -msgstr "`tinyvec`" +msgstr "" #: src/SUMMARY.md src/bare-metal/useful-crates/spin.md msgid "`spin`" -msgstr "`spin`" +msgstr "" + +#: src/SUMMARY.md src/bare-metal/android.md +msgid "Bare-Metal on Android" +msgstr "" #: src/SUMMARY.md msgid "`vmbase`" -msgstr "`vmbase`" +msgstr "" #: src/SUMMARY.md msgid "RTC Driver" -msgstr "RTC Driver" +msgstr "" #: src/SUMMARY.md msgid "Concurrency: Morning" -msgstr "Concurrency: āϏāĻ•āĻžāϞ" +msgstr "" -#: src/SUMMARY.md src/concurrency/threads.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/concurrency/welcome.md src/concurrency/threads.md msgid "Threads" -msgstr "āϏāĻŽā§āĻĒāĻžāĻĻāύāĻžāϰ āϏ⧁āϤ⧋" +msgstr "" + +#: src/SUMMARY.md src/concurrency/threads.md src/concurrency/threads/plain.md +msgid "Plain Threads" +msgstr "" -#: src/SUMMARY.md src/concurrency/scoped-threads.md +#: src/SUMMARY.md src/concurrency/threads.md src/concurrency/threads/scoped.md msgid "Scoped Threads" -msgstr "āĻ¸ā§āϕ⧋āĻĒāĻĄ Threads" +msgstr "" -#: src/SUMMARY.md src/concurrency/channels.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/concurrency/welcome.md src/concurrency/channels.md msgid "Channels" -msgstr "āύāĻžāϞāĻž āĻŦāĻž āĻšā§āϝāĻžāύ⧇āϞ" +msgstr "" + +#: src/SUMMARY.md src/concurrency/channels.md +#: src/concurrency/channels/senders-receivers.md +msgid "Senders and Receivers" +msgstr "" -#: src/SUMMARY.md src/concurrency/channels/unbounded.md +#: src/SUMMARY.md src/concurrency/channels.md +#: src/concurrency/channels/unbounded.md msgid "Unbounded Channels" -msgstr "āϏ⧀āĻŽāĻžāĻšā§€āύ āĻšā§āϝāĻžāύ⧇āϞ" +msgstr "" -#: src/SUMMARY.md src/concurrency/channels/bounded.md +#: src/SUMMARY.md src/concurrency/channels.md +#: src/concurrency/channels/bounded.md msgid "Bounded Channels" -msgstr "āφāĻŦāĻĻā§āϧ āĻšā§āϝāĻžāύ⧇āϞ" +msgstr "" #: src/SUMMARY.md src/concurrency/send-sync.md msgid "`Send` and `Sync`" -msgstr "`Send` āĻāĻŦāĻ‚ `Sync`" +msgstr "" + +#: src/SUMMARY.md src/concurrency/send-sync.md +#: src/concurrency/send-sync/marker-traits.md +msgid "Marker Traits" +msgstr "" #: src/SUMMARY.md src/concurrency/send-sync/send.md msgid "`Send`" -msgstr "`Send`" +msgstr "" #: src/SUMMARY.md src/concurrency/send-sync/sync.md msgid "`Sync`" -msgstr "`Sync`" +msgstr "" -#: src/SUMMARY.md src/concurrency/send-sync/examples.md +#: src/SUMMARY.md src/concurrency/send-sync.md +#: src/concurrency/send-sync/examples.md msgid "Examples" -msgstr "āωāĻĻāĻžāĻšāϰāĻŖāϏāĻŽā§‚āĻš" +msgstr "" -#: src/SUMMARY.md src/concurrency/shared_state.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/concurrency/welcome.md src/concurrency/shared-state.md msgid "Shared State" -msgstr "āĻ…āĻ‚āĻļāĻŋāĻĻāĻžāϰ⧀ āĻŽāĻžāϞāĻŋāĻ•āĻžāύāĻž āĻŦāĻŋāĻ­āĻžāϜāĻŋāϤ āĻ…āĻŦāĻ¸ā§āĻĨāĻž āĻŦāĻž āĻ¸ā§āĻŸā§‡āϟ" +msgstr "" -#: src/SUMMARY.md src/concurrency/shared_state/arc.md +#: src/SUMMARY.md src/concurrency/shared-state/arc.md msgid "`Arc`" -msgstr "`Arc`" +msgstr "" -#: src/SUMMARY.md src/concurrency/shared_state/mutex.md +#: src/SUMMARY.md src/concurrency/shared-state/mutex.md msgid "`Mutex`" -msgstr "`Mutex`" +msgstr "" #: src/SUMMARY.md src/memory-management/review.md -#: src/error-handling/try-conversions.md -#: src/concurrency/shared_state/example.md +#: src/error-handling/try-conversions.md src/concurrency/shared-state.md +#: src/concurrency/shared-state/example.md msgid "Example" -msgstr "āωāĻĻāĻžāĻšāϰāĻŖ" +msgstr "" -#: src/SUMMARY.md src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/solutions-morning.md +#: src/SUMMARY.md src/concurrency/sync-exercises.md +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/solutions.md +#: src/concurrency/async-exercises.md msgid "Dining Philosophers" -msgstr "Dining āĻĻāĻžāĻ°ā§āĻļāύāĻŋāĻ•" +msgstr "" -#: src/SUMMARY.md src/exercises/concurrency/link-checker.md +#: src/SUMMARY.md src/concurrency/sync-exercises.md +#: src/concurrency/sync-exercises/link-checker.md msgid "Multi-threaded Link Checker" -msgstr "āĻŽāĻžāĻ˛ā§āϟāĻŋ āĻĨā§āϰ⧇āĻĄā§‡āĻĄ āϞāĻŋāĻ™ā§āĻ• āĻšā§‡āĻ•āĻžāϰ" +msgstr "" #: src/SUMMARY.md msgid "Concurrency: Afternoon" -msgstr "āϏāĻŽāĻŦāĻ°ā§āϤ⧀āĻļā§€āϞāϤāĻž: āĻĻ⧁āĻĒ⧁āϰāĻŦ⧇āϞāĻž" +msgstr "" -#: src/SUMMARY.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/concurrency/welcome-async.md src/concurrency/async.md msgid "Async Basics" -msgstr "Async Basics" +msgstr "" -#: src/SUMMARY.md src/async/async-await.md +#: src/SUMMARY.md src/concurrency/async/async-await.md msgid "`async`/`await`" -msgstr "`async`/`await`" +msgstr "" -#: src/SUMMARY.md src/async/futures.md +#: src/SUMMARY.md src/concurrency/async.md src/concurrency/async/futures.md msgid "Futures" -msgstr "āĻ­āĻŦāĻŋāĻˇā§āĻ¯ā§Ž" +msgstr "" + +#: src/SUMMARY.md src/concurrency/async.md +#: src/concurrency/async/state-machine.md +msgid "State Machine" +msgstr "" -#: src/SUMMARY.md src/async/runtimes.md +#: src/SUMMARY.md src/concurrency/async.md src/concurrency/async/runtimes.md msgid "Runtimes" -msgstr "āϰāĻžāύāϟāĻžāχāĻŽ" +msgstr "" -#: src/SUMMARY.md src/async/runtimes/tokio.md +#: src/SUMMARY.md src/concurrency/async/runtimes/tokio.md msgid "Tokio" -msgstr "Tokio" +msgstr "" -#: src/SUMMARY.md src/exercises/concurrency/link-checker.md src/async/tasks.md -#: src/exercises/concurrency/chat-app.md +#: src/SUMMARY.md src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/async.md src/concurrency/async/tasks.md +#: src/concurrency/async-exercises/chat-app.md msgid "Tasks" -msgstr "Tasks-āĻ•āĻ°ā§āĻŽ" +msgstr "" -#: src/SUMMARY.md src/async/channels.md -msgid "Async Channels" -msgstr "āĻ…āϏāĻŽāύāĻŋāϝāĻŧāϤ āĻšā§āϝāĻžāύ⧇āϞ" +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/concurrency/welcome-async.md src/concurrency/async-control-flow.md +msgid "Channels and Control Flow" +msgstr "" -#: src/SUMMARY.md -msgid "Control Flow" -msgstr "āĻĒā§āϰāĻŦāĻžāĻš āύāĻŋāϝāĻŧāĻ¨ā§āĻ¤ā§āϰāĻŖ" +#: src/SUMMARY.md src/concurrency/async-control-flow.md +#: src/concurrency/async-control-flow/channels.md +msgid "Async Channels" +msgstr "" -#: src/SUMMARY.md src/async/control-flow/join.md +#: src/SUMMARY.md src/concurrency/async-control-flow.md +#: src/concurrency/async-control-flow/join.md msgid "Join" -msgstr "āĻœā§‹ā§œāĻž" +msgstr "" -#: src/SUMMARY.md src/async/control-flow/select.md +#: src/SUMMARY.md src/concurrency/async-control-flow.md +#: src/concurrency/async-control-flow/select.md msgid "Select" -msgstr "āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰāĻž" +msgstr "" -#: src/SUMMARY.md +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/concurrency/welcome-async.md src/concurrency/async-pitfalls.md msgid "Pitfalls" -msgstr "āĻ•ā§āώāϤāĻŋ" +msgstr "" -#: src/SUMMARY.md +#: src/SUMMARY.md src/concurrency/async-pitfalls.md msgid "Blocking the Executor" -msgstr "āĻāĻ•ā§āϏāĻŋāĻ•āĻŋāωāϟāϰ āĻŦā§āϞāĻ• āĻ•āϰāĻž" +msgstr "" -#: src/SUMMARY.md src/async/pitfalls/pin.md +#: src/SUMMARY.md src/concurrency/async-pitfalls/pin.md msgid "`Pin`" -msgstr "`Pin`" +msgstr "" -#: src/SUMMARY.md src/async/pitfalls/async-traits.md +#: src/SUMMARY.md src/concurrency/async-pitfalls.md +#: src/concurrency/async-pitfalls/async-traits.md msgid "Async Traits" -msgstr "Async Traits" +msgstr "" -#: src/SUMMARY.md src/async/pitfalls/cancellation.md +#: src/SUMMARY.md src/concurrency/async-pitfalls.md +#: src/concurrency/async-pitfalls/cancellation.md msgid "Cancellation" -msgstr "āĻŦāĻžāϤāĻŋāϞāĻ•āϰāĻŖ" +msgstr "" -#: src/SUMMARY.md src/exercises/concurrency/chat-app.md -#: src/exercises/concurrency/solutions-afternoon.md +#: src/SUMMARY.md src/concurrency/async-exercises.md +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md msgid "Broadcast Chat Application" -msgstr "āϏāĻŽā§āĻĒā§āϰāϚāĻžāϰ āĻ•āϰ⧇ āĻ•āĻĨā§‹āĻĒāĻ•āĻĨāύ āĻ•āϰāĻžāϰ āĻāĻĒā§āϞāĻŋāϕ⧇āĻļāύ" - -#: src/SUMMARY.md -msgid "Final Words" -msgstr "āĻšā§‚āĻĄāĻŧāĻžāĻ¨ā§āϤ āĻ•āĻŋāϛ⧁ āĻ•āĻĨāĻž" +msgstr "" -#: src/SUMMARY.md src/thanks.md -msgid "Thanks!" -msgstr "āϧāĻ¨ā§āϝāĻŦāĻžāĻĻ!" +#: src/SUMMARY.md src/running-the-course/course-structure.md +msgid "Idiomatic Rust" +msgstr "" -#: src/SUMMARY.md src/glossary.md -msgid "Glossary" -msgstr "āĻļāĻŦā§āĻĻāϕ⧋āώ" +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/idiomatic/welcome.md src/idiomatic/foundations-api-design.md +msgid "Foundations of API Design" +msgstr "" + +#: src/SUMMARY.md src/idiomatic/foundations-api-design.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments.md +msgid "Meaningful Doc Comments" +msgstr "" #: src/SUMMARY.md -msgid "Other Resources" -msgstr "āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻ‰ā§ŽāϏāϏāĻŽā§‚āĻš" +msgid "Who Are You Writing For?" +msgstr "" -#: src/SUMMARY.md src/credits.md -msgid "Credits" -msgstr "āĻ•ā§āϰ⧇āĻĄāĻŋāϟāϏ" +#: src/SUMMARY.md +msgid "Library vs Application docs" +msgstr "" -#: src/index.md -msgid "" -"[![Build workflow](https://img.shields.io/github/actions/workflow/status/" -"google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" -"google/comprehensive-rust/actions/workflows/build.yml?query=branch%3Amain) [!" -"[GitHub contributors](https://img.shields.io/github/contributors/google/" -"comprehensive-rust?style=flat-square)](https://github.com/google/" -"comprehensive-rust/graphs/contributors) [![GitHub stars](https://img.shields." -"io/github/stars/google/comprehensive-rust?style=flat-square)](https://github." -"com/google/comprehensive-rust/stargazers)" +#: src/SUMMARY.md +msgid "Anatomy of a Doc Comment" msgstr "" -"[![Build workflow](https://img.shields.io/github/actions/workflow/status/" -"google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" -"google/comprehensive-rust/actions/workflows/build.yml?query=branch%3Amain) [!" -"[GitHub contributors](https://img.shields.io/github/contributors/google/" -"comprehensive-rust?style=flat-square)](https://github.com/google/" -"comprehensive-rust/graphs/contributors) [![GitHub stars](https://img.shields." -"io/github/stars/google/comprehensive-rust?style=flat-square)](https://github." -"com/google/comprehensive-rust/stargazers)" -#: src/index.md -msgid "" -"This is a free Rust course developed by the Android team at Google. The " -"course covers the full spectrum of Rust, from basic syntax to advanced " -"topics like generics and error handling." +#: src/SUMMARY.md +msgid "Name Drop and Signpost" msgstr "" -"āĻāϟāĻŋ Google āĻāϰ āĻ…ā§āϝāĻžāĻ¨ā§āĻĄā§āϰāϝāĻŧ⧇āĻĄ āϟāĻŋāĻŽ āĻĻā§āĻŦāĻžāϰāĻž āϤ⧈āϰāĻŋ āĻāĻ•āϟāĻŋ āϚāĻžāϰ āĻĻāĻŋāύ⧇āϰ āϰāĻžāĻ¸ā§āϟāĻļāĻŋāĻ–āĻŦāĻžāϰ āϕ⧋āĻ°ā§āϏ āϝāĻž " -"āϰāĻžāĻ¸ā§āϟ-āĻāϰ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻ¸ā§āĻĒ⧇āĻ•āĻŸā§āϰāĻžāĻŽ, āĻŽā§ŒāϞāĻŋāĻ• āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āĻĨ⧇āϕ⧇ āĻļ⧁āϰ⧁ āĻ•āϰ⧇ āĻœā§‡āύ⧇āϰāĻŋāĻ• āĻāĻŦāĻ‚ āĻ¤ā§āϰ⧁āϟāĻŋ " -"āĻĒāϰāĻŋāϚāĻžāϞāύāĻžāϰ āĻŽāϤ⧋ āωāĻ¨ā§āύāϤ āĻŦāĻŋāώ⧟ āĻļāĻŋāĻ–āϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" -#: src/index.md -msgid "" -"The latest version of the course can be found at . If you are reading somewhere else, please check there " -"for updates." +#: src/SUMMARY.md +msgid "Avoid Redundancy" msgstr "" -"āĻāχ āϕ⧋āĻ°ā§āϏ āĻāϰ āϏāĻŦāĻšā§‡ā§Ÿā§‡ āύāϤ⧁āύ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ " -"- āĻāĻ–āĻžāύ⧇ āĻĒāĻžāĻ“ā§ŸāĻž āϝāĻžāĻŦ⧇āĨ¤ āϝāĻĻāĻŋ āĻ…āĻ¨ā§āϝ āϕ⧋āĻĨāĻžāĻ“ āĻĨ⧇āϕ⧇ āφāĻĒāύāĻŋ āĻĒ⧜āϛ⧇āύ āϤāĻžāĻšāϞ⧇ āĻāχāĻ–āĻžāύ⧇ āĻāĻ•āĻŦāĻžāϰ āĻĻ⧇āϖ⧇ " -"āĻ¨ā§‡ā§ŸāĻž āĻ­āĻžāϞ⧋āĨ¤" -#: src/index.md -msgid "The course is also available [as a PDF](comprehensive-rust.pdf)." -msgstr "āĻāχ āϕ⧋āĻ°ā§āϏāϟāĻŋ āĻĒāĻŋ.āĻĄāĻŋ.āĻāĻĢ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡āĻ“ āωāĻĒāϞāĻŦā§āϧ āφāϛ⧇ (comprehensive-rust.pdf)āĨ¤" +#: src/SUMMARY.md +msgid "Name and Signature are Not Enough" +msgstr "" -#: src/index.md -msgid "" -"The goal of the course is to teach you Rust. We assume you don't know " -"anything about Rust and hope to:" +#: src/SUMMARY.md +msgid "What and Why, not How and Where" msgstr "" -"āϕ⧋āĻ°ā§āϏ⧇āϰ āϞāĻ•ā§āĻˇā§āϝ āĻšāϞ āφāĻĒāύāĻžāϕ⧇ āϰāĻžāĻ¸ā§āϟ āĻļ⧇āĻ–āĻžāύ⧋āĨ¤ āφāĻŽāϰāĻž āϧāϰ⧇ āύāĻŋāϞāĻžāĻŽ āφāĻĒāύāĻŋ āĻ•āĻŋāϛ⧁āχ āϜāĻžāύ⧇āύ āύāĻž āϰāĻžāĻ¸ā§āϟ " -"āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āĻāĻŦāĻ‚ āφāĻļāĻž āĻ•āϰāĻŋ:" -#: src/index.md -msgid "Give you a comprehensive understanding of the Rust syntax and language." -msgstr "āφāĻĒāύāĻžāϕ⧇ āϰāĻžāĻ¸ā§āϟ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āĻāĻŦāĻ‚ āĻ­āĻžāώāĻž āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āĻāĻ•āϟāĻŋ āĻŦāĻŋāĻ¸ā§āϤāĻžāϰāĻŋāϤ āĻŦā§‹āĻāĻžāϝāĻŧ" +#: src/SUMMARY.md src/idiomatic/foundations-api-design.md +#: src/idiomatic/foundations-api-design/predictable-api.md +msgid "Predictable API" +msgstr "" -#: src/index.md -msgid "Enable you to modify existing programs and write new programs in Rust." +#: src/SUMMARY.md +msgid "Naming conventions" msgstr "" -"āφāĻĒāύāĻžāϕ⧇ āĻŦāĻŋāĻĻā§āϝāĻŽāĻžāύ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāϗ⧁āϞāĻŋ āϏāĻ‚āĻļā§‹āϧāύ āĻ•āϰāϤ⧇ āĻāĻŦāĻ‚ āϰāĻžāĻ¸ā§āϟ āĻ āύāϤ⧁āύ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āϞāĻŋāĻ–āϤ⧇ āϏāĻ•ā§āώāĻŽ āĻ•āϰ⧇āĨ¤" -#: src/index.md -msgid "Show you common Rust idioms." -msgstr "āφāĻĒāύāĻžāϕ⧇ āϏāĻžāϧāĻžāϰāĻŖ āϰāĻžāĻ¸ā§āϟ āχāĻĄāĻŋāϝāĻŧāĻŽāϏ āĻĻ⧇āĻ–āĻžāϝāĻŧāĨ¤" +#: src/SUMMARY.md +msgid "New" +msgstr "" -#: src/index.md -msgid "We call the first four course days Rust Fundamentals." -msgstr "āφāĻŽāϰāĻž āϕ⧋āĻ°ā§āϏ⧇āϰ āĻĒā§āϰāĻĨāĻŽ āϚāĻžāϰāϟāĻŋ āĻĻāĻŋāύāϕ⧇ āϰāĻžāĻ¸ā§āϟ āĻĢāĻžāĻ¨ā§āĻĄāĻžāĻŽā§‡āĻ¨ā§āϟāĻžāϞ āĻŦāϞāĻŋāĨ¤" +#: src/SUMMARY.md +msgid "Get" +msgstr "" -#: src/index.md -msgid "" -"Building on this, you're invited to dive into one or more specialized topics:" +#: src/SUMMARY.md +msgid "Push" msgstr "" -"āĻāϟāĻŋāϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇, āφāĻĒāύāĻžāϕ⧇ āĻāĻ• āĻŦāĻž āĻāĻ•āĻžāϧāĻŋāĻ• āĻŦāĻŋāĻļ⧇āώ āĻŦāĻŋāώāϝāĻŧāϗ⧁āϞāĻŋāϤ⧇ āĻĄā§āĻŦ āĻĻ⧇āĻ“ā§ŸāĻžāϰ āϜāĻ¨ā§āϝ " -"āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŋāϤāĨ¤" -#: src/index.md -msgid "" -"[Android](android.md): a half-day course on using Rust for Android platform " -"development (AOSP). This includes interoperability with C, C++, and Java." +#: src/SUMMARY.md +msgid "Is" msgstr "" -"[Android](android.md): āĻ…ā§āϝāĻžāĻ¨ā§āĻĄā§āϰāϝāĻŧ⧇āĻĄ āĻĒā§āĻ˛ā§āϝāĻžāϟāĻĢāĻ°ā§āĻŽā§‡āϰ āĻĄā§‡āϭ⧇āϞāĻĒāĻŽā§‡āĻ¨ā§āϟ (AOSP) āĻāϰ āϜāĻ¨ā§āϝ āϰāĻžāĻ¸ā§āϟ " -"āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āĻāĻ•āϟāĻŋ āĻ…āĻ°ā§āϧ-āĻĻāĻŋāύ⧇āϰ āϕ⧋āĻ°ā§āϏāĨ¤ āĻāϰ āĻŽāĻ§ā§āϝ⧇ C, C++ āĻāĻŦāĻ‚ Java āϏāĻš āφāĻ¨ā§āϤāσāĻ•āĻžāĻ°ā§āϝāϝ⧋āĻ—ā§āϝāϤāĻž " -"āĻ…āĻ¨ā§āϤāĻ°ā§āϭ⧁āĻ•ā§āϤ āϰāϝāĻŧ⧇āϛ⧇āĨ¤" -#: src/index.md -msgid "" -"[Chromium](chromium.md): a half-day course on using Rust within Chromium " -"based browsers. This includes interoperability with C++ and how to include " -"third-party crates in Chromium." +#: src/SUMMARY.md +msgid "Mut" msgstr "" -"[Chromium][chromium.md): āĻāĻ•āϟāĻŋ āφāϧāĻž āĻĻāĻŋāύ⧇āϰ āϕ⧋āĻ°ā§āϏ āϝ⧇āĻ–āĻžāύ⧇ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ Chromium āϝ⧁āĻ•ā§āϤ " -"āĻŦā§āϰāĻžāωāϏāĻžāϰ āĻ āϰāĻžāĻ¸ā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇ āĻāϟāĻž āĻļ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇āĨ¤ āĻāϤ⧇ C++ āφāĻ¨ā§āϤāσāĻ•āĻžāĻ°ā§āϝāĻ•ā§āώāĻŽāϤāĻž " -"āϏāĻš āϤ⧃āĻ¤ā§€ā§Ÿ āĻĒāĻ•ā§āώ⧇āϰ āĻ•ā§āϰ⧇āϟ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ Chromium āĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇ āĻāϟāĻžāĻ“ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇āĨ¤" -#: src/index.md -msgid "" -"[Bare-metal](bare-metal.md): a whole-day class on using Rust for bare-metal " -"(embedded) development. Both microcontrollers and application processors are " -"covered." +#: src/SUMMARY.md +msgid "With: Constructor" msgstr "" -"[āĻŦā§‡ā§ŸāĻžāϰ-āĻŽā§‡āϟāĻžāϞ](bare-metal.md): āϰāĻžāĻ¸ā§āϟ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻāĻŽāĻŦ⧇āĻĄā§‡āĻĄ āĻĄā§‡āϭ⧇āϞāĻĒāĻŽā§‡āĻ¨ā§āϟ āĻ āϞāĻžāĻ—āϤ⧇ āĻĒāĻžāϰ⧇ āĻāχ " -"āĻŦāĻŋāĻˇā§Ÿā§‡āϰ āĻ“āĻĒāϰ⧇ āĻāĻ•āϟāĻž āĻĒ⧁āϰ⧋ āĻĻāĻŋāύ⧇āϰ āĻ•ā§āϞāĻžāϏāĨ¤ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻ•āĻ¨ā§āĻŸā§āϰ⧋āϞ⧇āϰāϏ āĻāĻŦāĻ‚ āĻāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āĻĒā§āϰāϏ⧇āϏāϏāĻ°ā§āϏ āĻāχ " -"āĻĻ⧁āĻŸā§‹ āĻŦāĻŋāώ⧟āϗ⧁āϞāĻŋāϰ āϚāĻ°ā§āϚāĻž āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇ āĻāĻ–āĻžāύ⧇āĨ¤" -#: src/index.md -msgid "" -"[Concurrency](concurrency.md): a whole-day class on concurrency in Rust. We " -"cover both classical concurrency (preemptively scheduling using threads and " -"mutexes) and async/await concurrency (cooperative multitasking using " -"futures)." +#: src/SUMMARY.md +msgid "With: Copy-and-change" msgstr "" -"[āϏāĻŽāĻŦāĻ°ā§āϤ⧀ āĻ—āĻŖāύāĻž](concurrency.md): āϰāĻžāĻ¸ā§āϟ āĻ āϏāĻŽāĻŦāĻ°ā§āϤ⧀ āĻ—āĻŖāύāĻžāϰ āĻ“āĻĒāϰ⧇ āĻāĻ•āϟāĻž āĻĒ⧁āϰ⧋ āĻĻāĻŋāύ⧇āϰ āĻ•ā§āϞāĻžāϏ " -"āĨ¤ āĻāĻ–āĻžāύ⧇ āĻ•ā§āϞāĻžāϏāĻŋāĻ•āĻžāϞ āϏāĻŽāĻŦāĻ°ā§āϤ⧀ (āĻĨā§āϰ⧇āĻĄ āĻāĻŦāĻ‚ mutexes āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻ…āĻ—ā§āϰāĻ•ā§āϰ⧟āĻžāϧāĻŋāĻ•āĻžāϰ-āϏāĻ‚āĻ•ā§āϰāĻžāĻ¨ā§āϤ " -"āϏāĻŽāϝāĻŧāϏ⧂āĻšā§€ āĻŦāĻžāύāĻžāύ⧋) āĻ—āĻŖāύāĻž āĻāĻŦāĻ‚ async/await āϏāĻŽāĻŦāĻ°ā§āϤ⧀ āĻ—āĻŖāύāĻž (āĻĢāĻŋāωāϚāĻžāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϏāĻŽāĻŦāĻžāϝāĻŧ " -"āĻŽāĻžāĻ˛ā§āϟāĻŋāϟāĻžāĻ¸ā§āĻ•āĻŋāĻ‚)-āĻāχ āĻĻ⧁āχ āϧāϰāϪ⧇āϰ āύāĻŋā§Ÿā§‡ āϚāĻ°ā§āϚāĻž āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇āĨ¤" -#: src/index.md -msgid "Non-Goals" -msgstr "āϝāĻž āϞāĻ•ā§āĻˇā§āϝ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āĻĒāĻĄāĻŧ⧇ āύāĻž" +#: src/SUMMARY.md +msgid "With: Closures" +msgstr "" -#: src/index.md -msgid "" -"Rust is a large language and we won't be able to cover all of it in a few " -"days. Some non-goals of this course are:" +#: src/SUMMARY.md +msgid "With in normal use" msgstr "" -"āϰāĻžāĻ¸ā§āϟ āĻāĻ•āϟāĻŋ āĻŦ⧃āĻšā§Ž āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāĻŋāĻ‚ āĻ˛ā§āϝāĻžāĻ‚āϗ⧁āϝāĻŧ⧇āϜ āĻāĻŦāĻ‚ āφāĻŽāϰāĻž āĻ•āϝāĻŧ⧇āĻ• āĻĻāĻŋāύ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āĻāϟāĻŋāϕ⧇ āĻ•āĻ­āĻžāϰ āĻ•āϰāϤ⧇ " -"āϏāĻ•ā§āώāĻŽ āĻšāĻŦ āύāĻžāĨ¤ āĻāχ āϕ⧋āĻ°ā§āϏ⧇āϰ āĻ•āĻŋāϛ⧁ āĻ…-āϞāĻ•ā§āĻˇā§āϝ āĻšāϞāσ" -#: src/index.md -msgid "" -"Learning how to develop macros: please see [Chapter 19.5 in the Rust Book]" -"(https://doc.rust-lang.org/book/ch19-06-macros.html) and [Rust by Example]" -"(https://doc.rust-lang.org/rust-by-example/macros.html) instead." +#: src/SUMMARY.md +msgid "Try" msgstr "" -"āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻŦāĻžāύāĻžāύ⧋ āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇: āĻāϰ āϜāĻ¨ā§āϝ⧇ [āϰāĻžāĻ¸ā§āϟ āĻŦāχ āĻāϰ āĻ…āĻ§ā§āϝāĻžāϝāĻŧ ⧧⧝.ā§Ģ](https://doc." -"rust-lang.org/book/ch19-06-macros.html) āĻāĻŦāĻ‚ [āωāĻĻāĻžāĻšāϰāĻŖ āĻĻā§āĻŦāĻžāϰāĻž Rust](https://doc." -"rust-lang.org/rust-by-example/macros.html) āĻĻ⧇āϖ⧁āύāĨ¤" -#: src/index.md -msgid "Assumptions" -msgstr "\\##āϧ⧃āĻˇā§āϟāϤāĻžāϏāĻŽā§‚āĻš" +#: src/SUMMARY.md +msgid "From" +msgstr "" -#: src/index.md -msgid "" -"The course assumes that you already know how to program. Rust is a " -"statically-typed language and we will sometimes make comparisons with C and " -"C++ to better explain or contrast the Rust approach." +#: src/SUMMARY.md +msgid "Into" msgstr "" -"āϕ⧋āĻ°ā§āϏāϟāĻŋ āĻ…āύ⧁āĻŽāĻžāύ āĻ•āϰ⧇ āϝ⧇ āφāĻĒāύāĻŋ āχāϤāĻŋāĻŽāĻ§ā§āϝ⧇āχ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āĻ•āϰāϤ⧇ āϜāĻžāύ⧇āύāĨ¤ āϰāĻžāĻ¸ā§āϟ āĻāĻ•āϟāĻŋ āĻ¸ā§āĻŸā§āϝāĻžāϟāĻŋāĻ•āĻžāϞāĻŋ " -"āϟāĻžāχāĻĒāĻĄ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāĻŋāĻ‚ āĻ˛ā§āϝāĻžāĻ‚āϗ⧁āϝāĻŧ⧇āϜ āĻāĻŦāĻ‚ āφāĻŽāϰāĻž āĻ•āĻ–āύāĻ“ āĻ•āĻ–āύāĻ“ C āĻāĻŦāĻ‚ C++ āĻāϰ āϏāĻžāĻĨ⧇ āϤ⧁āϞāύāĻž āĻ•āϰāĻŦ " -"āĻ­āĻžāϞ⧋āĻ­āĻžāĻŦ āĻŦā§āϝāĻžāĻ–āĻž āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻ…āĻĨāĻŦāĻž āĻŦāĻŋāĻĒāϰ⧀āϤ āϰāĻžāĻ¸ā§āϟ āĻĒāĻĻā§āϧāϤāĻŋāĨ¤" -#: src/index.md -msgid "" -"If you know how to program in a dynamically-typed language such as Python or " -"JavaScript, then you will be able to follow along just fine too." +#: src/SUMMARY.md +msgid "Into inner" msgstr "" -"āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āϜāĻžāύ⧇āύ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻāĻ•āϟāĻŋ āĻĄāĻžāχāύāĻžāĻŽāĻŋāĻ•ā§āϝāĻžāϞāĻŋ āϟāĻžāχāĻĒāĻĄ āĻ­āĻžāώāĻžāϝāĻŧ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āĻ•āϰāϤ⧇ āĻšāϝāĻŧ āϝ⧇āĻŽāύ " -"āĻĒāĻžāχāĻĨāύ āĻŦāĻž āϜāĻžāĻ­āĻžāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟ, āϤāĻžāĻšāϞ⧇ āφāĻĒāύāĻŋ āϖ⧁āĻŦ āĻ­āĻžāϞ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāϤ⧇ āϏāĻ•ā§āώāĻŽ āĻšāĻŦ⧇āύāĨ¤" -#: src/index.md -msgid "" -"This is an example of a _speaker note_. We will use these to add additional " -"information to the slides. This could be key points which the instructor " -"should cover as well as answers to typical questions which come up in class." +#: src/SUMMARY.md +msgid "By" msgstr "" -"āĻāϟāĻŋ āĻāĻ•āϟāĻŋ _speaker note_ āĻāϰ āωāĻĻāĻžāĻšāϰāĻŖāĨ¤ āφāĻŽāϰāĻž āĻ…āϤāĻŋāϰāĻŋāĻ•ā§āϤ āϤāĻĨā§āϝ āĻ¸ā§āϞāĻžāχāĻĄā§‡ āϝ⧋āĻ— āĻ•āϰāϤ⧇ āĻāχāϗ⧁āϞ⧋ " -"āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦā§‹āĨ¤ āĻāϟāĻŋ āĻĒā§āϰāϧāĻžāύ āĻĒāϝāĻŧ⧇āĻ¨ā§āϟ āĻšāϤ⧇ āĻĒāĻžāϰ⧇ āϝāĻž āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāϕ⧇āϰ āωāϚāĻŋāϤ āĻ•āĻ­āĻžāϰ⧇āϰ āĻĒāĻžāĻļāĻžāĻĒāĻžāĻļāĻŋ " -"āĻ•ā§āϞāĻžāϏ⧇ āφāϏāĻž āϏāĻžāϧāĻžāϰāĻŖ āĻĒā§āϰāĻļā§āύ⧇āϰ āωāĻ¤ā§āϤāϰ āĻĻ⧇āĻ“āϝāĻŧāĻžāĨ¤" -#: src/running-the-course.md src/running-the-course/course-structure.md -msgid "This page is for the course instructor." -msgstr "āĻāχ āĻĒ⧃āĻˇā§āĻ āĻžāϟāĻŋ āϕ⧋āĻ°ā§āϏ āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāϕ⧇āϰ āϜāĻ¨ā§āϝāĨ¤" +#: src/SUMMARY.md +msgid "Unchecked" +msgstr "" -#: src/running-the-course.md -msgid "" -"Here is a bit of background information about how we've been running the " -"course internally at Google." +#: src/SUMMARY.md +msgid "To" msgstr "" -"āφāĻŽāϰāĻž āϕ⧀āĻ­āĻžāĻŦ⧇ āϕ⧋āĻ°ā§āϏāϟāĻŋ āϚāĻžāϞāĻžāĻšā§āĻ›āĻŋ āϏ⧇ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āĻāĻ–āĻžāύ⧇ āĻ•āĻŋāϛ⧁ āĻĒāϟāĻ­ā§‚āĻŽāĻŋāϰ āϗ⧁āĻ—āϞ⧇ āĻ…āĻ­ā§āϝāĻ¨ā§āϤāϰ⧀āĻŖāĻ­āĻžāĻŦ⧇ āϤāĻĨā§āϝ " -"āϰāϝāĻŧ⧇āϛ⧇āĨ¤" -#: src/running-the-course.md -msgid "" -"We typically run classes from 9:00 am to 4:00 pm, with a 1 hour lunch break " -"in the middle. This leaves 3 hours for the morning class and 3 hours for the " -"afternoon class. Both sessions contain multiple breaks and time for students " -"to work on exercises." +#: src/SUMMARY.md +msgid "As and Ref" msgstr "" -"āϏāĻžāϧāĻžāϰāĻŖāϤ āφāĻŽāϰāĻž āϏāĻ•āĻžāϞ ⧝.ā§Ļā§Ļ āĻĨ⧇āϕ⧇ āĻŦāĻŋāϕ⧇āϞ ā§Ē.ā§Ļā§Ļ (āĻŽāĻžāĻā§‡ ā§§ āϘāĻ¨ā§āϟāĻžāϰ āĻŦāĻŋāϰāϤāĻŋāϏāĻš) āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻ•ā§āϞāĻžāϏ āĻ•āϰ⧇ " -"āĻĨāĻžāĻ•āĻŋāĨ¤ āĻāχ āϜāĻ¨ā§āϝ⧇ āϏāĻ•āĻžāϞ⧇ ā§Š āϘāĻ¨ā§āϟāĻž āĻāĻŦāĻ‚ āĻĻ⧁āĻĒ⧁āϰ⧇ ā§Š āϘāĻ¨ā§āϟāĻž āϏāĻŽā§Ÿā§‡ āĻĨāĻžāϕ⧇ āĻ•ā§āϞāĻžāϏ āĻāϰ āϜāĻ¨ā§āϝ⧇āĨ¤ āĻĻ⧁āϟāĻŋ āĻ­āĻžāϗ⧇āχ " -"āĻļāĻŋāĻ•ā§āώāĻžāĻ°ā§āĻĨā§€ āĻĻ⧇āϰ āϜāĻ¨ā§āϝ⧇ āĻŦāĻŋāϰāϤāĻŋ āĻāĻŦāĻ‚ āĻ…āύ⧁āĻļā§€āϞāύ⧀āϰ āĻ•āĻžāĻœā§‡āϰ āϏāĻŽā§Ÿā§‡ āϝ⧁āĻ•ā§āϤ āĻĨāĻžāϕ⧇āĨ¤" -#: src/running-the-course.md -msgid "Before you run the course, you will want to:" -msgstr "āφāĻĒāύāĻŋ āϕ⧋āĻ°ā§āϏ āϚāĻžāϞāĻžāύ⧋āϰ āφāϗ⧇, āφāĻĒāύāĻŋ āϚāĻžāχāĻŦ⧇āύ:" +#: src/SUMMARY.md +msgid "Raw parts" +msgstr "" -#: src/running-the-course.md -msgid "" -"Make yourself familiar with the course material. We've included speaker " -"notes to help highlight the key points (please help us by contributing more " -"speaker notes!). When presenting, you should make sure to open the speaker " -"notes in a popup (click the link with a little arrow next to \"Speaker " -"Notes\"). This way you have a clean screen to present to the class." +#: src/SUMMARY.md +msgid "Implementing Common Traits" msgstr "" -"āϕ⧋āĻ°ā§āϏ⧇āϰ āωāĻĒāĻžāĻĻāĻžāύ⧇āϰ āϏāĻžāĻĨ⧇ āύāĻŋāĻœā§‡āϕ⧇ āĻĒāϰāĻŋāϚāĻŋāϤ āĻ•āϰ⧁āύāĨ¤ āφāĻŽāϰāĻž āĻ¸ā§āĻĒāĻŋāĻ•āĻžāϰ āύ⧋āϟ āĻ…āĻ¨ā§āϤāĻ°ā§āϭ⧁āĻ•ā§āϤ āĻ•āϰ⧇āĻ›āĻŋ āĻŽā§‚āϞ " -"āĻĒāϝāĻŧ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋ āĻšāĻžāχāϞāĻžāχāϟ āĻ•āϰāϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ (āĻ…āύ⧁āĻ—ā§āϰāĻš āĻ•āϰ⧇ āφāϰāĻ“ āĻ¸ā§āĻĒāĻŋāĻ•āĻžāϰ āύ⧋āϟ āĻ…āĻŦāĻĻāĻžāύ āϰ⧇āϖ⧇ " -"āφāĻŽāĻžāĻĻ⧇āϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧁āύ !)āĨ¤ āωāĻĒāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āĻ¸ā§āĻĒāĻŋāĻ•āĻžāϰ āύ⧋āϟ āĻĒāĻĒāφāĻĒ āĻ āϖ⧁āϞāϤ⧇ " -"āϭ⧁āϞāĻŦ⧇āύ āύāĻž (\"āĻ¸ā§āĻĒā§€āĻ•āĻžāϰ āύ⧋āϟāϏ\" āĻāϰ āĻĒāĻžāĻļ⧇ āĻāĻ•āϟāĻŋ āϛ⧋āϟ āϤ⧀āϰ āϏāĻš āϞāĻŋāĻ™ā§āϕ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ)āĨ¤ āĻāχ āĻĒāĻĨ⧇ " -"āĻ•ā§āϞāĻžāϏ⧇ āωāĻĒāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āφāĻĒāύāĻžāϰ āĻ•āĻžāϛ⧇ āĻāĻ•āϟāĻŋ āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āĻĒāĻ°ā§āĻĻāĻž āϰāϝāĻŧ⧇āϛ⧇āĨ¤" -#: src/running-the-course.md -msgid "" -"Decide on the dates. Since the course takes four days, we recommend that you " -"schedule the days over two weeks. Course participants have said that they " -"find it helpful to have a gap in the course since it helps them process all " -"the information we give them." +#: src/SUMMARY.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +msgid "Debug" msgstr "" -"āϤāĻŋāĻĨāĻŋāϰ āĻ“āĻĒāϰ⧇ āφāϗ⧇ āĻĨ⧇āϕ⧇ āϏāĻŋāĻĻā§āϧāĻžāĻ¨ā§āϤ āύāĻŋā§Ÿā§‡ āĻ¨ā§‡ā§ŸāĻž āĻ­āĻžāϞ⧋āĨ¤ āϝ⧇āĻšā§‡āϤ⧁ āĻāχ āϕ⧋āĻ°ā§āϏāϟāĻŋ ā§Ē-āĻĻāĻŋāύ āĻāϰ āϏ⧇āĻšā§‡āϤ⧁ " -"āφāĻŽāĻžāĻĻ⧇āϰ āϤāϰāĻĢ āĻĨ⧇āϕ⧇ āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻĨāĻžāĻ•āĻŦ⧇ āϝ⧇ āϤāĻŋāĻĨāĻŋāϗ⧁āϞāĻŋ āĻĻ⧁āχ āϏāĻĒā§āϤāĻž āϧāϰ⧇ āĻ›ā§œāĻŋā§Ÿā§‡ āϰāĻžāĻ–āĻŦāĻžāĨ¤ āφāϗ⧇āϰ " -"āĻ…āĻ‚āĻļāĻ—ā§āϰāĻšāĻŖāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻĨ⧇āϕ⧇ āĻāχ āĻĒāĻžāĻ“ā§ŸāĻž āϗ⧇āϛ⧇ āϝ⧇ āĻāϰāĻŽ āĻ•āϰ⧇ āĻāĻ•āĻžāϧāĻŋāĻ• āϏāĻĒā§āϤāĻž āϧāϰ⧇ " -"āϕ⧋āĻ°ā§āϏāϟāĻŋ āĻ•āϰāĻžāϞ⧇ āϤāĻžāϰāĻž āφāϰāĻ“ āĻ­āĻžāϞ⧋ āĻŦā§‹āĻā§‡āĨ¤" -#: src/running-the-course.md -msgid "" -"Find a room large enough for your in-person participants. We recommend a " -"class size of 15-25 people. That's small enough that people are comfortable " -"asking questions --- it's also small enough that one instructor will have " -"time to answer the questions. Make sure the room has _desks_ for yourself " -"and for the students: you will all need to be able to sit and work with your " -"laptops. In particular, you will be doing a lot of live-coding as an " -"instructor, so a lectern won't be very helpful for you." +#: src/SUMMARY.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "PartialEq and Eq" msgstr "" -"āφāĻĒāύāĻžāϰ āĻŦā§āϝāĻ•ā§āϤāĻŋāĻ—āϤ āĻ…āĻ‚āĻļāĻ—ā§āϰāĻšāύ⧇āϰ āϜāĻ¨ā§āϝ āϝāĻĨ⧇āĻˇā§āϟ āĻŦāĻĄāĻŧ āĻāĻ•āϟāĻŋ āϰ⧁āĻŽ āϖ⧁āρāϜ⧁āύāĨ¤ āφāĻŽāϰāĻž āϏ⧁āĻĒāĻžāϰāĻŋāĻļ āĻ•āϰāĻŋ 15-25 āϜāύ⧇āϰ " -"āϏāĻžāχāĻœā§‡āϰ āĻ•ā§āϞāĻžāϏāĨ¤ āĻāϟāĻŋ āϝāĻĨ⧇āĻˇā§āϟ āϛ⧋āϟ āϝ⧇ āĻŽāĻžāύ⧁āώ āφāϰāĻžāĻŽāĻĻāĻžāϝāĻŧāĻ• āĻ…āύ⧁āĻ­āĻŦ āĻ•āϰ⧇ āĻĒā§āϰāĻļā§āύ āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻ•āϰāϤ⧇--- " -"āĻāϟāĻŋ āϝāĻĨ⧇āĻˇā§āϟ āϛ⧋āϟ āϝ⧇ āĻāĻ•āϜāύ āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāĻ• āĻāϰ āϏāĻŽāϝāĻŧ āĻĨāĻžāĻ•āĻŦ⧇ āĻĒā§āϰāĻļā§āύ⧇āϰ āωāĻ¤ā§āϤāϰ āĻĻ⧇āĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝāĨ¤ āύāĻŋāĻļā§āϚāĻŋāϤ " -"āĻ•āϰ⧁āύ āϝ⧇ āϘāϰ⧇ āφāĻĒāύāĻžāϰ āϜāĻ¨ā§āϝ āĻāĻŦāĻ‚ āĻ›āĻžāĻ¤ā§āϰāĻĻ⧇āϰ āϜāĻ¨ā§āϝ _desks_ āφāϛ⧇ : āφāĻĒāύāĻžā§āĻĻ⧇āϰ āϏāĻ•āϞāϕ⧇ āφāĻĒāύāĻžāĻĻ⧇āϰ " -"āĻ˛ā§āϝāĻžāĻĒāϟāĻĒ⧇āϰ āϏāĻžāĻĨ⧇ āĻŦāϏ⧇ āĻ•āĻžāϜ āĻ•āϰāϤ⧇ āϏāĻ•ā§āώāĻŽ āĻšāϤ⧇ āĻšāĻŦ⧇āĨ¤ āĻŦāĻŋāĻļ⧇āώ āĻ•āϰ⧇, āφāĻĒāύāĻŋ āĻāĻ•āϜāύ āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāĻ• āĻšāĻŋāϏāĻžāĻŦ⧇ " -"āĻĒā§āϰāϚ⧁āϰ āϞāĻžāχāĻ­-āϕ⧋āĻĄāĻŋāĻ‚ āĻ•āϰāĻŦ⧇āύ, āϤāĻžāχ lecturn āφāĻĒāύāĻžāϰ āϜāĻ¨ā§āϝ āϖ⧁āĻŦ āϏāĻšāĻžāϝāĻŧāĻ• āĻšāĻŦ⧇ āύāĻžāĨ¤" -#: src/running-the-course.md -msgid "" -"On the day of your course, show up to the room a little early to set things " -"up. We recommend presenting directly using `mdbook serve` running on your " -"laptop (see the [installation instructions](https://github.com/google/" -"comprehensive-rust#building)). This ensures optimal performance with no lag " -"as you change pages. Using your laptop will also allow you to fix typos as " -"you or the course participants spot them." +#: src/SUMMARY.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "PartialOrd and Ord" msgstr "" -"āφāĻĒāύāĻžāϰ āϕ⧋āĻ°ā§āϏ⧇āϰ āĻĻāĻŋāύ, āϜāĻŋāύāĻŋāϏāϗ⧁āϞāĻŋ āϏ⧇āϟ āĻ•āϰāϤ⧇ āĻāĻ•āϟ⧁ āϤāĻžāĻĄāĻŧāĻžāϤāĻžāĻĄāĻŧāĻŋ āĻ•āϰ⧁āύ āφāĻŽāϰāĻž āφāĻĒāύāĻžāϰ āĻ˛ā§āϝāĻžāĻĒāϟāĻĒ⧇ " -"āϚāϞāĻŽāĻžāύ `mdbook serve` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϏāϰāĻžāϏāϰāĻŋ āωāĻĒāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻžāϰ āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻĻāĻŋāχ (āĻĻ⧇āϖ⧁āύ " -"\\[āχāύāĻ¸ā§āϟāϞ⧇āĻļāύ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻžāĻŦāϞ⧀\\] [3](https://github.com/google/comprehensive-" -"rust#building))āĨ¤ āφāĻĒāύāĻŋ āĻĒ⧃āĻˇā§āĻ āĻžāϗ⧁āϞāĻŋ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ āĻāϟāĻŋ āϕ⧋āύāĻ“ āĻ˛ā§āϝāĻžāĻ— āĻ›āĻžāĻĄāĻŧāĻžāχ " -"āϏāĻ°ā§āĻŦā§‹āĻ¤ā§āϤāĻŽ āĻ•āĻžāĻ°ā§āϝāĻ•ā§āώāĻŽāϤāĻž āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧇āĨ¤ āφāĻĒāύāĻžāϰ āĻ˛ā§āϝāĻžāĻĒāϟāĻĒ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϞ⧇ āφāĻĒāύāĻŋ āφāĻĒāύāĻžāϰ āĻŦāĻž āϕ⧋āĻ°ā§āϏ⧇āϰ " -"āĻŽāϤ⧋ āϟāĻžāχāĻĒ āϭ⧁āϞ āĻ āĻŋāĻ• āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇āύ āĻ…āĻ‚āĻļāĻ—ā§āϰāĻšāĻŖāĻ•āĻžāϰ⧀āϰāĻž āϤāĻžāĻĻ⧇āϰ āϖ⧁āρāĻœā§‡ āĻŦ⧇āϰ āĻ•āϰ⧇āĨ¤" -#: src/running-the-course.md -msgid "" -"Let people solve the exercises by themselves or in small groups. We " -"typically spend 30-45 minutes on exercises in the morning and in the " -"afternoon (including time to review the solutions). Make sure to ask people " -"if they're stuck or if there is anything you can help with. When you see " -"that several people have the same problem, call it out to the class and " -"offer a solution, e.g., by showing people where to find the relevant " -"information in the standard library." +#: src/SUMMARY.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md +msgid "Hash" msgstr "" -"āϤāĻžāĻĻ⧇āϰāϕ⧇ āĻāĻ•āĻž āĻāĻ•āĻž āĻŦāĻž āϛ⧋āϟ āĻĻāϞ⧇ āĻ…āύ⧁āĻļā§€āϞāύ⧇āϰ āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰāϤ⧇ āĻĻāĻŋāύāĨ¤ āφāĻŽāϰāĻž āϏāĻžāϧāĻžāϰāĻŖāϤ āϏāĻ•āĻžāϞ⧇ āĻāĻŦāĻ‚ " -"āĻŦāĻŋāϕ⧇āϞ⧇ āĻŦā§āϝāĻžāϝāĻŧāĻžāĻŽā§‡āϰ āϜāĻ¨ā§āϝ 30-45 āĻŽāĻŋāύāĻŋāϟ āĻŦā§āϝāϝāĻŧ āĻ•āϰāĻŋ (āϏāĻŽāĻžāϧāĻžāύāϗ⧁āϞāĻŋ āĻĒāĻ°ā§āϝāĻžāϞ⧋āϚāύāĻž āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āϏāĻš)āĨ¤ " -"āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ āϞ⧋āϕ⧇āĻĻ⧇āϰ āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻ•āϰ⧁āύ āϤāĻžāϰāĻž āφāϟāϕ⧇ āφāϛ⧇ āĻ•āĻŋāύāĻž āĻŦāĻž āφāĻĒāύāĻŋ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ " -"āĻāĻŽāύ āĻ•āĻŋāϛ⧁ āφāϛ⧇ āĻ•āĻŋāύāĻžāĨ¤ āϝāĻ–āύ āφāĻĒāύāĻŋ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻšā§āϛ⧇āύ āϝ⧇ āĻŦ⧇āĻļ āĻ•āϝāĻŧ⧇āĻ•āϜāύ⧇āϰ āĻāĻ•āχ āϏāĻŽāĻ¸ā§āϝāĻž āϰāϝāĻŧ⧇āϛ⧇, " -"āĻāϟāĻŋāϕ⧇ āĻ•ā§āϞāĻžāϏ⧇ āĻ•āϞ āĻ•āϰ⧁āύ āĻāĻŦāĻ‚ āĻāĻ•āϟāĻŋ āϏāĻŽāĻžāϧāĻžāύ āĻ…āĻĢāĻžāϰ āĻ•āϰ⧁āύ, āϝ⧇āĻŽāύ, āĻĒā§āϰāĻžāϏāĻ™ā§āĻ—āĻŋāĻ• āϤāĻĨā§āϝāϟāĻŋ āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ " -"āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋāϤ⧇ āϕ⧋āĻĨāĻžāϝāĻŧ āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāĻŦ⧇ āϤāĻž āϞ⧋āϕ⧇āĻĻ⧇āϰ āĻĻ⧇āĻ–āĻŋāϝāĻŧ⧇ āĻĻāĻŋāύāĨ¤" -#: src/running-the-course.md -msgid "" -"That is all, good luck running the course! We hope it will be as much fun " -"for you as it has been for us!" +#: src/SUMMARY.md src/memory-management.md src/memory-management/clone.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +msgid "Clone" msgstr "" -"āĻāχāϏāĻŦ āϝ⧇, āϕ⧋āĻ°ā§āϏāϟāĻŋ āϚāĻžāϞāĻžāύ⧋āϰ āϜāĻ¨ā§āϝ āĻļ⧁āĻ­āĻ•āĻžāĻŽāύāĻžāĨ¤ āφāĻŽāϰāĻž āφāĻļāĻž āĻ•āϰāĻŋ āĻāϟāĻž āϤāϤāϟāĻžāχ āĻŽāϜāĻžāϰ āĻšāĻŦ⧇ āφāĻĒāύāĻžāϰ " -"āϜāĻ¨ā§āϝ āϝāϤāϟāĻž āĻšāϝāĻŧ⧇āĻ›āĻŋāϞ⧋ āφāĻŽāĻžāĻĻ⧇āϰ āĻ•āĻžāϛ⧇āĨ¤" -#: src/running-the-course.md -msgid "" -"Please [provide feedback](https://github.com/google/comprehensive-rust/" -"discussions/86) afterwards so that we can keep improving the course. We " -"would love to hear what worked well for you and what can be made better. " -"Your students are also very welcome to [send us feedback](https://github.com/" -"google/comprehensive-rust/discussions/100)!" +#: src/SUMMARY.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +msgid "Copy" msgstr "" -"āĻ…āύ⧁āĻ—ā§āϰāĻš āĻ•āϰ⧇ \\[āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧁āύ\\] [1](https://github.com/google/" -"comprehensive-rust/discussions/86) āĻĒāϰ⧇ āϝāĻžāϤ⧇ āφāĻŽāϰāĻž āωāĻ¨ā§āύāϤāĻŋ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŋāĨ¤ āĻ…āĻŦāĻļā§āϝāχ " -"āφāĻĒāύāĻžāϰ āϜāĻ¨ā§āϝ āϕ⧀ āĻ­āĻžāϞ āĻ•āĻžāϜ āĻ•āϰ⧇āϛ⧇ āĻāĻŦāĻ‚ āωāĻ¤ā§āϤāĻŽ āϕ⧀ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇ āϤāĻž āφāĻŽāϰāĻž āĻļ⧁āύāϤ⧇ āϚāĻžāχāĨ¤" -"āφāĻĒāύāĻžāϰ āĻ›āĻžāĻ¤ā§āϰāĻĻ⧇āϰāĻ“ \\[āφāĻŽāĻžāĻĻ⧇āϰ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻĒāĻžāĻ āĻžāϤ⧇\\] āϖ⧁āĻŦ āĻ¸ā§āĻŦāĻžāĻ—āϤ āϜāĻžāύāĻžāχ[2](https://" -"github.com/google/comprehensive-rust/discussions/100)" -#: src/running-the-course/course-structure.md -msgid "Rust Fundamentals" -msgstr "āϰāĻžāĻ¸ā§āϟ āĻāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻœā§āĻžāĻžāύ " +#: src/SUMMARY.md +msgid "Serialize and Deserialize" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "" -"The first four days make up [Rust Fundamentals](../welcome-day-1.md). The " -"days are fast paced and we cover a lot of ground!" +#: src/SUMMARY.md src/std-traits.md +msgid "From and Into" msgstr "" -"āĻĒā§āϰāĻĨāĻŽ āϚāĻžāϰ āĻĻāĻŋāύ āϧāϰ⧇ [āϰāĻžāĻ¸ā§āϟ āĻāϰ āĻŽā§‚āϞāϏ⧂āĻ¤ā§āϰāϗ⧁āϞāĻŋ](../welcome-day-1.md) āϏ⧇āĻ–āĻžāύ āĻšāĻŦ⧇āĨ¤ āĻāχ " -"āĻ…āĻ§ā§āϝāĻžāϝāĻŧāϗ⧁āϞāĻŋ āĻĻā§āϰ⧁āϤ āĻ—āϤāĻŋāϰ āĻšāϝāĻŧ āĻāĻŦāĻ‚ āφāĻŽāϰāĻž āĻ…āύ⧇āĻ•āϟāĻž āĻāĻ•āϏāĻžāĻĨ⧇ āĻļāĻŋāĻ–āĻŦāĻžāϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻžāĻŦā§‹āĨ¤" -#: src/running-the-course/course-structure.md -msgid "Course schedule:" -msgstr "āϕ⧋āĻ°ā§āϏ āĻāϰ āϏāĻŽāϝāĻŧāϏ⧂āĻšā§€" +#: src/SUMMARY.md +msgid "TryFrom and TryInto" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "Day 1 Morning (2 hours and 10 minutes, including breaks)" -msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύ⧇āϰ āϏāĻ•āĻžāϞ (āĻŦāĻŋāϰāϤāĻŋāϏāĻš ⧍ āϘāĻ¨ā§āϟāĻž ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md +msgid "Display" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Welcome](../welcome-day-1.md) (5 minutes)" -msgstr "[āĻ¸ā§āĻŦāĻžāĻ—āϤ](../welcome-day-1.md) (ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/idiomatic/welcome.md src/idiomatic/leveraging-the-type-system.md +msgid "Leveraging the Type System" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Hello, World](../hello-world.md) (15 minutes)" -msgstr "[āĻšā§āϝāĻžāϞ⧋, āĻ“ā§ŸāĻžāĻ°ā§āĻ˛ā§āĻĄ](../hello-world.md) (ā§§ā§Ģ āĻŽāĻŋāύāĻŋāϟ )" +#: src/SUMMARY.md src/idiomatic/leveraging-the-type-system.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +msgid "Newtype Pattern" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Types and Values](../types-and-values.md) (45 minutes)" -msgstr "[āϟāĻžāχāĻĒ āĻāĻŦāĻ‚ āĻŽāĻžāύ](../types-and-values.md) (ā§Ēā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +msgid "Semantic Confusion" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Control Flow Basics](../control-flow-basics.md) (40 minutes)" -msgstr "[āύāĻŋāϝāĻŧāĻ¨ā§āĻ¤ā§āϰāĻŖ āĻĒā§āϰāĻŦāĻžāĻšāϰ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āĻœā§āĻžāĻžāύ](../control-flow-basics.md) (ā§Ēā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md +msgid "Parse, Don't Validate" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "Day 1 Afternoon (2 hours and 15 minutes, including breaks)" -msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύ⧇āϰ āĻĻ⧁āĻĒ⧁āϰ (āĻŦāĻŋāϰāϤāĻŋāϏāĻš ⧍ āϘāĻ¨ā§āϟāĻž ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +msgid "Is It Encapsulated?" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Tuples and Arrays](../tuples-and-arrays.md) (35 minutes)" -msgstr "[āϟāĻŋāωāĻĒāϞ āĻāĻŦāĻ‚ āĻ…ā§āϝāĻžāϰ⧇](../tuples-and-arrays.md) (ā§Šā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/idiomatic/leveraging-the-type-system.md +msgid "RAII" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[References](../references.md) (35 minutes)" -msgstr "[āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ](../references.md) (ā§Šā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +msgid "Drop Skipped" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[User-Defined Types](../user-defined-types.md) (50 minutes)" -msgstr "[āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āĻĻā§āĻŦāĻžāϰāĻž āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āϟāĻžāχāĻĒ](../user-defined-types.md) (ā§Ģā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/concurrency/shared-state.md +msgid "Mutex" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "Day 2 Morning (2 hours and 50 minutes, including breaks)" -msgstr "āĻĻā§āĻŦāĻŋāĻ¤ā§€ā§Ÿ āĻĻāĻŋāύ⧇āϰ āϏāĻ•āĻžāϞ (āĻŦāĻŋāϰāϤāĻŋāϏāĻš ⧍ āϘāĻ¨ā§āϟāĻž ā§Ģā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/idiomatic/leveraging-the-type-system/raii/drop_guards.md +msgid "Drop Guards" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Welcome](../welcome-day-2.md) (3 minutes)" -msgstr "[āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ](../welcome-day-2.md) (ā§Š āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +msgid "Drop Bomb" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Pattern Matching](../pattern-matching.md) (1 hour)" -msgstr "[āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āĻŽā§āϝāĻžāϚāĻŋāĻ‚](../pattern-matching.md) (ā§§ āϘāĻ¨ā§āϟāĻž)" +#: src/SUMMARY.md +msgid "Drop Bomb Forget" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Methods and Traits](../methods-and-traits.md) (45 minutes)" -msgstr "[āĻĒā§āϰāĻŖāĻžāϞ⧀ āĻāĻŦāĻ‚ āĻŸā§āϰ⧇āχāϟ](../methods-and-traits.md) (ā§Ēā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "forget and drop functions" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Generics](../generics.md) (40 minutes)" -msgstr "[āĻœā§‡āύ⧇āϰāĻŋāĻ•ā§āϏ\\](../generics.md) (ā§Ēā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +msgid "Scope Guard" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "Day 2 Afternoon (3 hours and 10 minutes, including breaks)" -msgstr "āĻĻā§āĻŦāĻŋāĻ¤ā§€ā§Ÿ āĻĻāĻŋāύ⧇āϰ āĻĻ⧁āĻĒ⧁āϰāĻŦ⧇āϞāĻž (āĻŦāĻŋāϰāϤāĻŋāϏāĻš ā§Š āϘāĻ¨ā§āϟāĻž ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +msgid "Drop Option" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Standard Library Types](../std-types.md) (1 hour and 20 minutes)" -msgstr "[āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋāϰ āϟāĻžāχāĻĒāϗ⧁āϞāĻŋ](../std-types.md) (ā§§ āϘāĻ¨ā§āϟāĻž āĻŸā§‹ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/idiomatic/leveraging-the-type-system.md +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "Extension Traits" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Standard Library Traits](../std-traits.md) (1 hour and 40 minutes)" -msgstr "[āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋāϰ āĻŸā§āϰ⧇āχāϟ](../std-traits.md) (ā§§ āϘāĻ¨ā§āϟāĻž āĻŸā§‹ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "Extending Foreign Types" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "Day 3 Morning (2 hours and 20 minutes, including breaks)" -msgstr "āϤ⧃āĻ¤ā§€ā§Ÿ āĻĻāĻŋāύ⧇āϰ āϏāĻ•āĻžāϞāĻŦ⧇āϞāĻž (āĻŦāĻŋāϰāϤāĻŋāϏāĻš ⧍ āϘāĻ¨ā§āϟāĻž ⧍ā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "Method Resolution Conflicts" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Welcome](../welcome-day-3.md) (3 minutes)" -msgstr "[āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ](../welcome-day-3.md) (ā§Š āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md +msgid "Trait Method Conflicts" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Memory Management](../memory-management.md) (1 hour)" -msgstr "[āĻŽā§‡āĻŽāϰāĻŋ āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻž](../memory-management.md) (ā§§ āϘāĻ¨ā§āϟāĻž)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "Extending Other Traits" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Smart Pointers](../smart-pointers.md) (55 minutes)" -msgstr "[āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻžāύ āχāĻ™ā§āĻ—āĻŋāϤāĻ•āĻžāϰ⧀ āĻŦāĻž āĻ¸ā§āĻŽāĻžāĻ°ā§āϟ āĻĒā§Ÿā§‡āĻ¨ā§āϟāĻžāϰ](../smart-pointers.md) (ā§Ģā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "Should I Define An Extension Trait?" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "Day 3 Afternoon (2 hours and 10 minutes, including breaks)" -msgstr "āϤ⧃āĻ¤ā§€ā§Ÿ āĻĻāĻŋāύ⧇āϰ āĻĻ⧁āĻĒ⧁āϰāĻŦ⧇āϞāĻž (āĻŦāĻŋāϰāϤāĻŋāϏāĻš ⧍ āϘāĻ¨ā§āϟāĻž ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/idiomatic/leveraging-the-type-system.md +msgid "Typestate Pattern" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Borrowing](../borrowing.md) (50 minutes)" -msgstr "[āϧāĻžāϰ āύ⧇āĻ“ā§ŸāĻž āĻŦāĻž āĻŦāĻ°ā§‹ā§ŸāĻŋāĻ‚](../borrowing.md) (ā§Ģā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +msgid "Typestate Pattern Example" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "" -"[Slices and Lifetimes](../slices-and-lifetimes.md) (1 hour and 10 minutes)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "Beyond Simple Typestate" msgstr "" -"[āϟ⧁āĻ•āϰāĻž āĻŦāĻž āĻ¸ā§āϞāĻžāχāϏ⧇āϏ āĻāĻŦāĻ‚ āĻœā§€āĻŦāύāĻ•āĻžāϞ ](../slices-and-lifetimes.md) (ā§§ āϘāĻ¨ā§āϟāĻž ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ)" -#: src/running-the-course/course-structure.md -msgid "Day 4 Morning (2 hours and 50 minutes, including breaks)" -msgstr "āϚāϤ⧁āĻ°ā§āĻĨ āĻĻāĻŋāύ⧇āϰ āϏāĻ•āĻžāϞāĻŦ⧇āϞāĻž (āĻŦāĻŋāϰāϤāĻŋāϏāĻš ⧍āϘāĻ¨ā§āϟāĻž ā§Ģā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +msgid "Typestate Pattern with Generics" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Welcome](../welcome-day-4.md) (3 minutes)" -msgstr "[āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ](../welcome-day-4.md) (ā§Š āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md +msgid "Serializer: implement Root" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Iterators](../iterators.md) (45 minutes)" -msgstr "[āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋāĻ•āĻžāϰ⧀ āĻŦāĻž āχāϟāĻžāϰ⧇āϟāĻ°ā§āϏ](../iterators.md) (ā§Ēā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md +msgid "Serializer: implement Struct" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Modules](../modules.md) (40 minutes)" -msgstr "[āĻŽāĻĄāĻŋāωāϞ](../modules.md) (ā§Ēā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md +msgid "Serializer: implement Property" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Testing](../testing.md) (1 hour)" -msgstr "[āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻž](../testing.md) (ā§§ āϘāĻ¨ā§āϟāĻž)" +#: src/SUMMARY.md +msgid "Serializer: Complete implementation" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "Day 4 Afternoon (2 hours and 10 minutes, including breaks)" -msgstr "āϚāϤ⧁āĻ°ā§āĻĨ āĻĻāĻŋāύ⧇āϰ āĻĻ⧁āĻĒ⧁āϰāĻŦ⧇āϞāĻž (āĻŦāĻŋāϰāϤāĻŋāϏāĻš ⧍ āϘāĻ¨ā§āϟāĻž ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/idiomatic/leveraging-the-type-system.md +msgid "Borrow checking invariants" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Error Handling](../error-handling.md) (55 minutes)" -msgstr "[āĻ¤ā§āϰ⧁āϟāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž](../error-handling.md) (ā§Ģā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "Lifetimes and Borrows: the Abstract Rules" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "[Unsafe Rust](../unsafe-rust.md) (1 hour and 5 minutes)" -msgstr "[āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āϰāĻžāĻ¸ā§āϟ](../unsafe-rust.md) (ā§§ āϘāĻ¨ā§āϟāĻž ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "Single-use values" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "Deep Dives" -msgstr "āĻ—āĻ­ā§€āϰ āĻĄā§āĻŦ" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "Mutually Exclusive References / \"Aliasing XOR Mutability\"" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "" -"In addition to the 4-day class on Rust Fundamentals, we cover some more " -"specialized topics:" +#: src/SUMMARY.md +msgid "PhantomData and Types" msgstr "" -"āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻŽā§‚āϞ āĻŦāĻŋāĻˇā§Ÿā§‡āϰ āĻ“āĻĒāϰ⧇ ā§Ē āĻĻāĻŋāύ⧇āϰ āĻ•ā§āϞāĻžāϏ āĻ›āĻžāĻĄāĻŧāĻžāĻ“, āĻāĻ–āĻžāύ⧇ āφāϰāĻ“ āĻ•āĻŋāϛ⧁ āĻŦāĻŋāĻļ⧇āώ āĻŦāĻŋāώāϝāĻŧ āϚāĻ°ā§āϚāĻž āĻ•āϰāĻž " -"āĻšā§Ÿā§‡āϛ⧇ āϝ⧇āĻŽāύ:" -#: src/running-the-course/course-structure.md -msgid "Rust in Android" -msgstr "āĻ…ā§āϝāĻžāĻ¨ā§āĻĄā§āϰāϝāĻŧ⧇āĻĄā§‡ āϰāĻžāĻ¸ā§āϟ" +#: src/SUMMARY.md +msgid "PhantomData and Types (implementation)" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "" -"The [Rust in Android](../android.md) deep dive is a half-day course on using " -"Rust for Android platform development. This includes interoperability with " -"C, C++, and Java." +#: src/SUMMARY.md +msgid "PhantomData: Lifetimes for External Resources" msgstr "" -"[āĻ…ā§āϝāĻžāĻ¨ā§āĻĄā§āϰāϝāĻŧ⧇āĻĄā§‡ āϰāĻžāĻ¸ā§āϟ](../android.md) āĻšāϞ āĻ…ā§āϝāĻžāĻ¨ā§āĻĄā§āϰāϝāĻŧ⧇āĻĄ āĻĒā§āĻ˛ā§āϝāĻžāϟāĻĢāĻ°ā§āĻŽ āĻĄā§‡āϭ⧇āϞāĻĒāĻŽā§‡āĻ¨ā§āϟ āĻāϰ āϜāĻ¨ā§āϝ " -"āϰāĻžāĻ¸ā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āĻāĻ•āϟāĻŋ āĻ…āĻ°ā§āϧ-āĻĻāĻŋāύ⧇āϰ āϕ⧋āĻ°ā§āϏāĨ¤ āĻāϰ āĻŽāĻ§ā§āϝ⧇ āϰāϝāĻŧ⧇āϛ⧇ C, C++, āĻāĻŦāĻ‚ Java āĻāϰ āϏāĻžāĻĨ⧇ " -"āφāĻ¨ā§āϤāσāĻ•āĻžāĻ°ā§āϝāϝ⧋āĻ—ā§āϝāϤāĻžāĨ¤" -#: src/running-the-course/course-structure.md -msgid "" -"You will need an [AOSP checkout](https://source.android.com/docs/setup/" -"download/downloading). Make a checkout of the [course repository](https://" -"github.com/google/comprehensive-rust) on the same machine and move the `src/" -"android/` directory into the root of your AOSP checkout. This will ensure " -"that the Android build system sees the `Android.bp` files in `src/android/`." +#: src/SUMMARY.md +msgid "PhantomData: OwnedFd & BorrowedFd" msgstr "" -"āφāĻĒāύāĻžāϰ āĻāĻ•āϟāĻŋ \\[AOSP āĻšā§‡āĻ•āφāωāϟ\\] āĻĒā§āϰāϝāĻŧā§‹āϜāύ āĻšāĻŦ⧇ [1](https://source.android.com/docs/" -"setup/download/downloading)āĨ¤ āĻāĻ•āϟāĻŋ āĻšā§‡āĻ•āφāωāϟ āĻ•āϰ⧁āύ \\[āϕ⧋āĻ°ā§āϏ āϰāĻŋāĻĒā§‹āϜāĻŋāϟāϰāĻŋ [2](https://" -"github.com/google/comprehensive-rust) āĻāĻ•āχ āĻŽā§‡āĻļāĻŋāύ⧇ āĻāĻŦāĻ‚ `src/android/` āĻĄāĻŋāϰ⧇āĻ•ā§āϟāϰāĻŋ " -"āϏāϰāĻžāύ āφāĻĒāύāĻžāϰ AOSP āĻšā§‡āĻ•āφāωāĻŸā§‡āϰ āĻŽā§‚āϞ āĻĄāĻŋāϰ⧇āĻ•ā§āϟāϰāĻŋāϤ⧇āĨ¤ āĻāϟāĻŋ āĻ…ā§āϝāĻžāĻ¨ā§āĻĄā§āϰāϝāĻŧ⧇āĻĄ āĻŦāĻŋāĻ˛ā§āĻĄ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ āύāĻŋāĻļā§āϚāĻŋāϤ " -"āĻ•āϰāĻŦ⧇ `src/android/`\\-āĻ `Android.bp` āĻĢāĻžāχāϞāϗ⧁āϞāĻŋ āĻĻ⧇āϖ⧁āύāĨ¤" -#: src/running-the-course/course-structure.md -msgid "" -"Ensure that `adb sync` works with your emulator or real device and pre-build " -"all Android examples using `src/android/build_all.sh`. Read the script to " -"see the commands it runs and make sure they work when you run them by hand." +#: src/SUMMARY.md src/idiomatic/leveraging-the-type-system.md +#: src/idiomatic/leveraging-the-type-system/token-types.md +msgid "Token Types" msgstr "" -"āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ āϝ⧇ `adb āϏāĻŋāĻ™ā§āĻ•` āφāĻĒāύāĻžāϰ āĻāĻŽā§āϞ⧇āϟāϰ āĻŦāĻž āĻŦāĻžāĻ¸ā§āϤāĻŦ āĻĄāĻŋāĻ­āĻžāχāϏ⧇āϰ āϏāĻžāĻĨ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇ āĻāĻŦāĻ‚ " -"Android āωāĻĻāĻžāĻšāϰāĻŖāϗ⧁āϞ⧋ āĻĒā§āϰāĻŋ-āĻŦāĻŋāĻ˛ā§āĻĄ āĻ•āϰ⧁āύ `src/android/build_all.sh` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇āĨ¤āĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟ " -"āĻĒāĻĄāĻŧ⧁āύ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻĻ⧇āĻ–āϤ⧇ āϝ⧇āϗ⧁āϞ⧋ āĻāϟāĻŋ āϚāĻžāϞāĻžāϝāĻŧ āĻāĻŦāĻ‚ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ āϝ⧇ āφāĻĒāύāĻŋ āϝāĻ–āύ āϤāĻžāĻĻ⧇āϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇āύ " -"āϤāĻ–āύ āϤāĻžāϰāĻž āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤" -#: src/running-the-course/course-structure.md -msgid "Rust in Chromium" -msgstr "āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽā§‡ āϰāĻžāĻ¸ā§āϟ" +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md +msgid "Permission Tokens" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "" -"The [Rust in Chromium](../chromium.md) deep dive is a half-day course on " -"using Rust as part of the Chromium browser. It includes using Rust in " -"Chromium's `gn` build system, bringing in third-party libraries (\"crates\") " -"and C++ interoperability." +#: src/SUMMARY.md +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md +msgid "Token Types with Data: Mutex Guards" msgstr "" -"āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽ āĻŦā§āϰāĻžāωāϏāĻžāϰ āĻāϰ āϜāĻ¨ā§āϝ⧇ āϰāĻžāĻ¸ā§āϟ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžā§Ÿ āĻāϰ āĻ“āĻĒāϰ⧇ āĻ…āĻ°ā§āϧ⧇āĻ• āĻĻāĻŋāύ⧇āϰ āϜāĻ¨ā§āϝ⧇ " -"āĻ—āĻ­ā§€āϰ āĻ­āĻžāĻŦ⧇ āϚāĻ°ā§āϚāĻž āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇ āĻāĻ–āĻžāύ⧇ - [āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽ āĻāϰ āϜāĻ¨ā§āϝ⧇ āϰāĻžāĻ¸ā§āϟ](../chromium.md)āĨ¤ " -"āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽ āĻāϰ `gn` āύāĻŋāĻ°ā§āĻŽāĻžāĻŖ āĻĒāĻĻā§āϧāϤāĻŋāϤ⧇ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇, āϤ⧃āϤ⧀āϝāĻŧ āĻĒāĻ•ā§āώ⧇āϰ " -"āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ (āϝāĻžāϕ⧇ āĻ•ā§āϰ⧇āϟ āĻŦāϞāĻž āĻšā§Ÿā§‡ Rust āĻ) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻāĻŦāĻ‚ C++ āφāĻ¨ā§āϤāσ-āĻ•āĻžāĻ°ā§āϝāĻ•ā§āώāĻŽāϤāĻž āĻāχ " -"āĻŦāĻŋāĻˇā§Ÿā§‡ āϗ⧁āϞāĻŋāϰ āĻ—āĻ­ā§€āϰ āϚāĻ°ā§āϚāĻž āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇āĨ¤" -#: src/running-the-course/course-structure.md -msgid "" -"You will need to be able to build Chromium --- a debug, component build is " -"[recommended](../chromium/setup.md) for speed but any build will work. " -"Ensure that you can run the Chromium browser that you've built." +#: src/SUMMARY.md +msgid "Branded pt 1: Variable-specific tokens" msgstr "" -"āĻāϰ āϜāĻ¨ā§āϝ⧇ āφāĻĒāύāĻžāϰ āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽ āύāĻŋāĻ°ā§āĻŽāĻžāĻŖ āĻ•āϰāĻŦāĻžāϰ āĻ•ā§āώāĻŽāϤāĻž āĻĨāĻžāϕ⧇ āĻĻāϰāĻ•āĻžāϰāĨ¤ āϝāĻĻāĻŋāĻ“ āϝ⧇āϕ⧋āύ⧋ āύāĻŋāĻ°ā§āĻŽāĻŋāϤ " -"āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāĻŦ⧇, āϤāĻŦ⧁āĻ“ āϤāĻžā§œāĻžāϤāĻžā§œāĻŋ āĻ•āĻžāϜ āĻ•āϰāĻŦāĻžāϰ āϜāĻ¨ā§āϝ⧇ āφāĻŽāϰāĻž āĻāĻ•āϟāĻŋ āĻĄāĻŋāĻŦāĻžāĻ— āĻĒāĻĻā§āϧāϤāĻŋāϤ⧇ " -"āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦāĻžāϰ [āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ](../chromium/setup.md) āĻĻ⧇āĻŦāĨ¤ āύāĻŋāĻ°ā§āĻŽāĻŋāϤ " -"āĻ•ā§āϰ⧋āĻŽāĻŋ⧟āĻŽ āϝ⧇āύ āφāĻĒāύāĻžāϰ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡ āϚāϞāϤ⧇ āĻĒāĻžāϰ⧇ āĻāϟāĻžāĻ“ āĻŽāĻžāĻĨāĻžā§Ÿ āϰāĻžāĻ–āĻž āĻĻāϰāĻ•āĻžāϰāĨ¤ " -#: src/running-the-course/course-structure.md -msgid "Bare-Metal Rust" -msgstr "Bare-Metal āϰāĻžāĻ¸ā§āϟ" +#: src/SUMMARY.md +msgid "Branded pt 2: `PhantomData` and Lifetime Subtyping" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "" -"The [Bare-Metal Rust](../bare-metal.md) deep dive is a full day class on " -"using Rust for bare-metal (embedded) development. Both microcontrollers and " -"application processors are covered." +#: src/SUMMARY.md +msgid "Branded pt 3: Implementation" msgstr "" -"[Bare-Metal āϰāĻžāĻ¸ā§āϟ](../bare-metal.md): āϰāĻžāĻ¸ā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ bare-metal (embedded) " -"āĻĄā§‡āϭ⧇āϞāĻĒāĻŽā§‡āĻ¨ā§āϟ āĻāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āĻĒ⧁āϰ⧋ āĻĻāĻŋāύ⧇āϰ āĻ•ā§āϞāĻžāϏāĨ¤ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻ•āĻ¨ā§āĻŸā§āϰ⧋āϞāĻžāϰ āĻāĻŦāĻ‚ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āĻĒā§āϰāϏ⧇āϏāϰ " -"āωāĻ­āϝāĻŧāχ āĻ•āĻ­āĻžāϰ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤" -#: src/running-the-course/course-structure.md -msgid "" -"For the microcontroller part, you will need to buy the [BBC micro:bit]" -"(https://microbit.org/) v2 development board ahead of time. Everybody will " -"need to install a number of packages as described on the [welcome page](../" -"bare-metal.md)." +#: src/SUMMARY.md +msgid "Branded pt 4: Branded types in action." msgstr "" -"āĻŽāĻžāχāĻ•ā§āϰ⧋āĻ•āĻ¨ā§āĻŸā§āϰ⧋āϞāĻžāϰ āĻ…āĻ‚āĻļ⧇āϰ āϜāĻ¨ā§āϝ, āφāĻĒāύāĻžāϕ⧇ āϏāĻŽāϝāĻŧ⧇āϰ āφāϗ⧇ āĻ•āĻŋāύāϤ⧇ āĻšāĻŦ⧇ [BBC micro:bit](https://" -"microbit.org/) v2 āωāĻ¨ā§āύāϝāĻŧāύ āĻŦā§‹āĻ°ā§āĻĄāĨ¤ āϏāĻŦāĻžāχāϕ⧇ [welcome page](../bare-metal.md) āĻ " -"āĻŦāĻ°ā§āĻŖāĻŋāϤ āĻĒā§āϝāĻžāϕ⧇āϜāϗ⧁āϞāĻŋāϰ āĻāĻ•āϟāĻŋ āϏāĻ‚āĻ–ā§āϝāĻž āχāύāĻ¸ā§āϟāϞ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤" -#: src/running-the-course/course-structure.md -msgid "Concurrency in Rust" -msgstr "Concurrency in āϰāĻžāĻ¸ā§āϟ" +#: src/SUMMARY.md src/running-the-course/course-structure.md +#: src/idiomatic/welcome.md src/idiomatic/polymorphism.md +msgid "Polymorphism" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "" -"The [Concurrency in Rust](../concurrency.md) deep dive is a full day class " -"on classical as well as `async`/`await` concurrency." +#: src/SUMMARY.md src/idiomatic/polymorphism/refresher.md +msgid "Refresher" msgstr "" -"[Concurrency in Rust](../concurrency.md) āĻĄāĻŋāĻĒ āĻĄāĻžāχāĻ­ āĻ•ā§āϞāĻžāϏāĻŋāĻ•ā§āϝāĻžāϞ⧇āϰ āωāĻĒāϰ āĻĒ⧁āϰ⧋ āĻĻāĻŋāύ⧇āϰ " -"āĻāĻ•āϟāĻŋ āĻ•ā§āϞāĻžāϏ āϏ⧇āχāϏāĻžāĻĨ⧇ `async`/`await` concurrency." -#: src/running-the-course/course-structure.md -msgid "" -"You will need a fresh crate set up and the dependencies downloaded and ready " -"to go. You can then copy/paste the examples into `src/main.rs` to experiment " -"with them:" +#: src/SUMMARY.md src/idiomatic/polymorphism/refresher/deriving-traits.md +msgid "Deriving Traits" msgstr "" -"āφāĻĒāύāĻžāϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āĻšāĻŦ⧇ āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āĻ•ā§āϰ⧇āϟ āϏ⧇āϟ āφāĻĒ āĻāĻŦāĻ‚ āύāĻŋāĻ°ā§āĻ­āϰāϤāĻž āĻĄāĻžāωāύāϞ⧋āĻĄ āĻ•āϰāĻž āĻāĻŦāĻ‚ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ " -"āĻšāĻ“āϝāĻŧāĻžāĨ¤ āϤāĻžāϰāĻĒāϰ āφāĻĒāύāĻŋ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ `src/main.rs`\\-āĻ āωāĻĻāĻžāĻšāϰāĻŖāϗ⧁āϞ⧋ āĻ•āĻĒāĻŋ/āĻĒ⧇āĻ¸ā§āϟ āĻ•āϰāϤ⧇ " -"āĻĒāĻžāϰ⧇āύ:" -#: src/running-the-course/course-structure.md -msgid "Format" -msgstr "āĻŦāĻŋāĻ¨ā§āϝāĻžāϏ" +#: src/SUMMARY.md +msgid "Default Implementations" +msgstr "" -#: src/running-the-course/course-structure.md -msgid "" -"The course is meant to be very interactive and we recommend letting the " -"questions drive the exploration of Rust!" +#: src/SUMMARY.md +msgid "Blanket Implementations" msgstr "" -"āϕ⧋āĻ°ā§āϏāϟāĻŋ āϖ⧁āĻŦ āχāĻ¨ā§āϟāĻžāϰ⧇āĻ•ā§āϟāĻŋāĻ­ āĻšāϤ⧇ āĻŦā§‹āĻāĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇ āĻāĻŦāĻ‚ āφāĻŽāϰāĻž āĻāϟāĻŋ āĻ•āϰāĻžāϰ āϏ⧁āĻĒāĻžāϰāĻŋāĻļ āĻ•āϰāĻ›āĻŋ āĻĒā§āϰāĻļā§āύāϗ⧁āϞ⧋ " -"Rust āĻāϰ āĻ…āĻ¨ā§āĻŦ⧇āώāĻŖ āϚāĻžāϞāύāĻž āĻ•āϰ⧁āĻ•!" -#: src/running-the-course/keyboard-shortcuts.md -msgid "There are several useful keyboard shortcuts in mdBook:" -msgstr "mdBook-āĻ āĻŦ⧇āĻļ āĻ•āĻŋāϛ⧁ āĻĻāϰāĻ•āĻžāϰ⧀ āϕ⧀āĻŦā§‹āĻ°ā§āĻĄ āĻļāĻ°ā§āϟāĻ•āĻžāϟ āϰāϝāĻŧ⧇āϛ⧇āσ" +#: src/SUMMARY.md +msgid "Conditional Methods" +msgstr "" -#: src/running-the-course/keyboard-shortcuts.md -msgid "Arrow-Left" -msgstr "Arrow-Left" +#: src/SUMMARY.md src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "Orphan Rule" +msgstr "" -#: src/running-the-course/keyboard-shortcuts.md -msgid ": Navigate to the previous page." -msgstr ": Navigate to the previous page." +#: src/SUMMARY.md +msgid "Statically Sized and Dynamically Sized types" +msgstr "" -#: src/running-the-course/keyboard-shortcuts.md -msgid "Arrow-Right" -msgstr "Arrow-Right" +#: src/SUMMARY.md src/idiomatic/polymorphism/refresher/monomorphization.md +msgid "Monomorphization and Binary Size" +msgstr "" -#: src/running-the-course/keyboard-shortcuts.md -msgid ": Navigate to the next page." -msgstr ": Navigate to the next page." +#: src/SUMMARY.md +msgid "From OOP to Rust" +msgstr "" -#: src/running-the-course/keyboard-shortcuts.md src/cargo/code-samples.md -msgid "Ctrl + Enter" -msgstr "Ctrl + Enter" +#: src/SUMMARY.md +msgid "Inheritance" +msgstr "" -#: src/running-the-course/keyboard-shortcuts.md -msgid ": Execute the code sample that has focus." -msgstr ": Execute the code sample that has focus." +#: src/SUMMARY.md +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "Why no Inheritance in Rust?" +msgstr "" -#: src/running-the-course/keyboard-shortcuts.md -msgid "s" -msgstr "s" +#: src/SUMMARY.md +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +msgid "Inheritance from Rust's Perspective" +msgstr "" -#: src/running-the-course/keyboard-shortcuts.md -msgid ": Activate the search bar." -msgstr ": Activate the search bar." +#: src/SUMMARY.md +msgid "\"Inheritance\" in Rust and Supertraits" +msgstr "" -#: src/running-the-course/translations.md -msgid "" -"The course has been translated into other languages by a set of wonderful " -"volunteers:" -msgstr "āϕ⧋āĻ°ā§āϏāϟāĻŋ āĻŦāĻŋāĻ¸ā§āĻŽāϝāĻŧāĻ•āϰ āĻāĻ•āϟāĻŋ āϏ⧇āϟ āĻ¸ā§āĻŦ⧇āĻšā§āĻ›āĻžāϏ⧇āĻŦāĻ• āĻĻā§āĻŦāĻžāϰāĻž āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻ­āĻžāώāĻžāϝāĻŧ āĻ…āύ⧁āĻŦāĻžāĻĻ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āσ" +#: src/SUMMARY.md src/idiomatic/polymorphism/from-oop-to-rust/composition.md +msgid "Composition over Inheritance" +msgstr "" -#: src/running-the-course/translations.md -msgid "" -"[Brazilian Portuguese](https://google.github.io/comprehensive-rust/pt-BR/) " -"by [@rastringer](https://github.com/rastringer), [@hugojacob](https://github." -"com/hugojacob), [@joaovicmendes](https://github.com/joaovicmendes), and " -"[@henrif75](https://github.com/henrif75)." +#: src/SUMMARY.md +msgid "Trait Objects and Dynamic Dispatch" msgstr "" -"[āĻŦā§āϰāĻžāϜāĻŋāϞ⧀āϝāĻŧ āĻĒāĻ°ā§āϤ⧁āĻ—ā§€āϜ](https://google.github.io/comprehensive-rust/pt-BR/) āĻ•āϰāĻž " -"āĻšā§Ÿā§‡āϛ⧇ [@rastringer](https://github.com/rastringer), [@hugojacob](https://" -"github.com/hugojacob), [@joaovicmendes](https://github.com/joaovicmendes) " -"āĻāĻŦāĻ‚ [@henrif75](https://github.com/henrif75) āĻĻā§āĻŦāĻžāϰāĻžāĨ¤" -#: src/running-the-course/translations.md -msgid "" -"[Chinese (Simplified)](https://google.github.io/comprehensive-rust/zh-CN/) " -"by [@suetfei](https://github.com/suetfei), [@wnghl](https://github.com/" -"wnghl), [@anlunx](https://github.com/anlunx), [@kongy](https://github.com/" -"kongy), [@noahdragon](https://github.com/noahdragon), [@superwhd](https://" -"github.com/superwhd), [@SketchK](https://github.com/SketchK), and [@nodmp]" -"(https://github.com/nodmp)." +#: src/SUMMARY.md +msgid "Dyn Compatibility" msgstr "" -"[āϏāϰāϞ⧀āĻ•ā§ƒāϤ āĻšā§€āύāĻž āĻ­āĻžāώāĻž](https://google.github.io/comprehensive-rust/zh-CN/) āĻ•āϰāĻž " -"āĻšā§Ÿā§‡āϛ⧇ [@suetfei](https://github.com/suetfei), [@wnghl](https://github.com/" -"wnghl), [@anlunx](https://github.com/anlunx), [@kongy](https://github.com/" -"kongy), [@noahdragon](https://github.com/noahdragon), [@superwhd](https://" -"github.com/superwhd), [@SketchK](https://github.com/SketchK), āĻāĻŦāĻ‚ [@nodmp]" -"(https://github.com/nodmp) āĻĻā§āĻŦāĻžāϰāĻžāĨ¤" -#: src/running-the-course/translations.md -msgid "" -"[Chinese (Traditional)](https://google.github.io/comprehensive-rust/zh-TW/) " -"by [@hueich](https://github.com/hueich), [@victorhsieh](https://github.com/" -"victorhsieh), [@mingyc](https://github.com/mingyc), [@kuanhungchen](https://" -"github.com/kuanhungchen), and [@johnathan79717](https://github.com/" -"johnathan79717)." +#: src/SUMMARY.md +msgid "Generics vs Trait Objects" msgstr "" -"[āϐāϤāĻŋāĻšā§āϝāĻ—āϤ āĻšā§€āύāĻž āĻ­āĻžāώāĻž](https://google.github.io/comprehensive-rust/zh-TW/) āĻ•āϰāĻž " -"āĻšā§Ÿā§‡āϛ⧇ [@hueich](https://github.com/hueich), [@victorhsieh](https://github." -"com/victorhsieh), [@mingyc](https://github.com/mingyc), [@kuanhungchen]" -"(https://github.com/kuanhungchen), āĻāĻŦāĻ‚ [@johnathan79717](https://github.com/" -"johnathan79717) āĻĻā§āĻŦāĻžāϰāĻžāĨ¤" -#: src/running-the-course/translations.md -msgid "" -"[Korean](https://google.github.io/comprehensive-rust/ko/) by [@keispace]" -"(https://github.com/keispace), [@jiyongp](https://github.com/jiyongp), " -"[@jooyunghan](https://github.com/jooyunghan), and [@namhyung](https://github." -"com/namhyung)." +#: src/SUMMARY.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md +msgid "Limits of Trait Objects" msgstr "" -"[āϕ⧋āϰāĻŋāϝāĻŧāĻžāύ](https://google.github.io/comprehensive-rust/ko/) āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇ " -"[@keispace](https://github.com/keispace), [@jiyongp](https://github.com/" -"jiyongp) āĻāĻŦāĻ‚ [@jooyunghan](https://github.com/jooyunghan) āĻĻā§āĻŦāĻžāϰāĻžāĨ¤" -#: src/running-the-course/translations.md -msgid "" -"[Spanish](https://google.github.io/comprehensive-rust/es/) by [@deavid]" -"(https://github.com/deavid)." +#: src/SUMMARY.md +msgid "Heterogeneous Collections" msgstr "" -"[āĻ¸ā§āĻĒā§āϝāĻžāύāĻŋāĻļ āĻ­āĻžāώāĻž](https://google.github.io/comprehensive-rust/es/) āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇ " -"[@deavid](https://github.com/deavid) āĻĻā§āĻŦāĻžāϰāĻžāĨ¤" -#: src/running-the-course/translations.md -msgid "" -"Use the language picker in the top-right corner to switch between languages." -msgstr "āĻ­āĻžāώāĻžāϰ āĻŽāĻ§ā§āϝ⧇ āĻ¸ā§āϝ⧁āχāϚ āĻ•āϰāϤ⧇ āωāĻĒāϰ⧇āϰ-āĻĄāĻžāύ āϕ⧋āϪ⧇ āĻ­āĻžāώāĻž āϚāϝāĻŧāύāĻ•āĻžāϰ⧀ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤" +#: src/SUMMARY.md +msgid "The `Any` Trait" +msgstr "" -#: src/running-the-course/translations.md -msgid "Incomplete Translations" -msgstr "āĻ…āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻ…āύ⧁āĻŦāĻžāĻĻ" +#: src/SUMMARY.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md +msgid "Pitfall: Reaching too quickly for `dyn Trait`" +msgstr "" -#: src/running-the-course/translations.md -msgid "" -"There is a large number of in-progress translations. We link to the most " -"recently updated translations:" +#: src/SUMMARY.md +msgid "Sealed Traits" msgstr "" -"āĻĒā§āϰāϚ⧁āϰ āϏāĻ‚āĻ–ā§āϝāĻ• āĻ…āύ⧁āĻŦāĻžāĻĻ āϚāϞāϛ⧇āĨ¤ āφāĻŽāϰāĻž āϏāĻžāĻŽā§āĻĒā§āϰāϤāĻŋāĻ• āφāĻĒāĻĄā§‡āϟ āĻšāĻ“āϝāĻŧāĻž āĻ…āύ⧁āĻŦāĻžāĻĻāϗ⧁āϞāĻŋāϰ āϏāĻžāĻĨ⧇ āϞāĻŋāĻ™ā§āĻ• āĻ•āϰāĻŋāσ" -#: src/running-the-course/translations.md -msgid "" -"[Bengali](https://google.github.io/comprehensive-rust/bn/) by [@raselmandol]" -"(https://github.com/raselmandol)." +#: src/SUMMARY.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md +msgid "Sealing with Enums" msgstr "" -"[āĻŦāĻžāĻ‚āϞāĻž](https://google.github.io/comprehensive-rust/bn/) āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇ " -"[@abhik-99](https://github.com/abhik-99) āĻāĻŦāĻ‚ [@raselmandol](https://github." -"com/raselmandol) āĻĻā§āĻŦāĻžāϰāĻžāĨ¤" -#: src/running-the-course/translations.md -msgid "" -"[French](https://google.github.io/comprehensive-rust/fr/) by [@KookaS]" -"(https://github.com/KookaS) and [@vcaen](https://github.com/vcaen)." +#: src/SUMMARY.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md +msgid "Traits for Polymorphism users can extend" msgstr "" -"[French](https://google.github.io/comprehensive-rust/fr/) by [@KookaS]" -"(https://github.com/KookaS) and [@vcaen](https://github.com/vcaen)" -#: src/running-the-course/translations.md -msgid "" -"[German](https://google.github.io/comprehensive-rust/de/) by [@Throvn]" -"(https://github.com/Throvn) and [@ronaldfw](https://github.com/ronaldfw)." +#: src/SUMMARY.md +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "Problem solving: Break Down the Problem" msgstr "" -"[German](https://google.github.io/comprehensive-rust/de/) by [@Throvn]" -"(https://github.com/Throvn) and [@ronaldfw](https://github.com/ronaldfw)." -#: src/running-the-course/translations.md -msgid "" -"[Japanese](https://google.github.io/comprehensive-rust/ja/) by [@CoinEZ-JPN]" -"(https://github.com/CoinEZ) and [@momotaro1105](https://github.com/" -"momotaro1105)." +#: src/SUMMARY.md src/unsafe-deep-dive/introduction.md +msgid "Introduction" msgstr "" -"[Japanese](https://google.github.io/comprehensive-rust/ja/) by [@CoinEZ-JPN]" -"(https://github.com/CoinEZ) and [@momotaro1105](https://github.com/" -"momotaro1105)." -#: src/running-the-course/translations.md -msgid "" -"[Italian](https://google.github.io/comprehensive-rust/it/) by " -"[@henrythebuilder](https://github.com/henrythebuilder) and [@detro](https://" -"github.com/detro)." +#: src/SUMMARY.md src/unsafe-deep-dive/introduction.md +#: src/unsafe-deep-dive/introduction/definition.md +msgid "Defining Unsafe Rust" msgstr "" -"[āχāϤāĻžāϞāĻŋāϝāĻŧāĻžāύ āĻ­āĻžāώāĻž](https://google.github.io/comprehensive-rust/it/) āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇ " -"[@henrythebuilder](https://github.com/henrythebuilder) āĻāĻŦāĻ‚ [@detro](https://" -"github.com/detro) āĻĻā§āĻŦāĻžāϰāĻžāĨ¤" -#: src/running-the-course/translations.md -msgid "" -"If you want to help with this effort, please see [our instructions](https://" -"github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md) for how to " -"get going. Translations are coordinated on the [issue tracker](https://" -"github.com/google/comprehensive-rust/issues/282)." +#: src/SUMMARY.md src/unsafe-deep-dive/introduction.md +msgid "Purpose of the unsafe keyword" msgstr "" -"āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻāχ āĻĒā§āϰāĻšā§‡āĻˇā§āϟāĻžāϝāĻŧ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰāϤ⧇ āϚāĻžāύ, āϤāĻžāĻšāϞ⧇ āϕ⧀āĻ­āĻžāĻŦ⧇ āĻļ⧁āϰ⧁ āĻ•āϰāĻŦ⧇āύ āϤāĻžāϰ āϜāĻ¨ā§āϝ " -"\\[āφāĻŽāĻžāĻĻ⧇āϰ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻžāĻŦāϞ⧀\\] āĻĻ⧇āϖ⧁āύāĨ¤ āĻ…āύ⧁āĻŦāĻžāĻĻāϗ⧁āϞāĻŋ \\[āχāĻ¸ā§āϝ⧁ āĻŸā§āĻ°ā§āϝāĻžāĻ•āĻžāϰ\\] āĻ āϏāĻŽāĻ¨ā§āĻŦāĻŋāϤ āĻšāϝāĻŧ⧇āϛ⧇āĨ¤" -#: src/cargo.md -msgid "" -"When you start reading about Rust, you will soon meet [Cargo](https://doc." -"rust-lang.org/cargo/), the standard tool used in the Rust ecosystem to build " -"and run Rust applications. Here we want to give a brief overview of what " -"Cargo is and how it fits into the wider ecosystem and how it fits into this " -"training." +#: src/SUMMARY.md src/unsafe-deep-dive/introduction.md +msgid "Two roles of the unsafe keyword" msgstr "" -"āφāĻĒāύāĻŋ āϝāĻ–āύ āϰāĻžāĻ¸ā§āϟ āϏāĻŽā§āĻŦāĻ¨ā§āϧ⧇ āĻĒāĻĄāĻŧāĻž āĻļ⧁āϰ⧁ āĻ•āϰāĻŦ⧇āύ, āφāĻĒāύāĻŋ āĻļā§€āĻ˜ā§āϰāχ [āĻ•āĻžāĻ°ā§āĻ—ā§‹](https://doc.rust-lang." -"org/cargo/) āĻāϰ āϏāĻžāĻĨ⧇ āĻĻ⧇āĻ–āĻž āĻ•āϰāĻŦ⧇āύ, āĻāĻ•āϟāĻŋ āφāĻĻāĻ°ā§āĻļ āϟ⧁āϞ āϝāĻž Rust āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āϤ⧈āϰāĻŋ āĻāĻŦāĻ‚ " -"āϚāĻžāϞāĻžāύ⧋āϰ āϜāĻ¨ā§āϝ Rust āχāϕ⧋āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧ⧇āϛ⧇āĨ¤ āĻāĻ–āĻžāύ⧇ āφāĻŽāϰāĻž āϚāĻžāχ āĻ•āĻžāĻ°ā§āĻ—ā§‹ āϕ⧀ āĻāĻŦāĻ‚ āĻāϟāĻŋ " -"āϕ⧀āĻ­āĻžāĻŦ⧇ āĻŦ⧃āĻšāĻ¤ā§āϤāϰ āχāϕ⧋āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡ āĻĢāĻŋāϟ āĻ•āϰ⧇ āϤāĻžāϰ āĻāĻ•āϟāĻŋ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤ āĻŦāĻŋāĻŦāϰāĻŖ āĻĻāĻŋāϤ⧇ āĻāĻŦāĻ‚ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻāϟāĻŋ " -"āĻāχ āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāϪ⧇āϰ āϏāĻžāĻĨ⧇ āĻ–āĻžāĻĒ āĻ–āĻžāϝāĻŧāĨ¤" -#: src/cargo.md -msgid "Installation" -msgstr "Installation" +#: src/SUMMARY.md src/unsafe-deep-dive/introduction.md +msgid "Warm Up Examples" +msgstr "" -#: src/cargo.md -msgid "**Please follow the instructions on .**" -msgstr "**. āĻ āĻĻ⧇āĻ“ā§ŸāĻž āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻžāĻŦāϞ⧀ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰ⧁āύāĨ¤**" +#: src/SUMMARY.md src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md +msgid "Using an unsafe block" +msgstr "" -#: src/cargo.md -msgid "" -"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." +#: src/SUMMARY.md src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md +msgid "Defining an unsafe function" msgstr "" -"āĻāĻ­āĻžāĻŦ⧇ āφāĻĒāύāĻŋ āĻ•āĻžāĻ°ā§āĻ—ā§‹ (`cargo`) āĻāĻŦāĻ‚ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ (`rustc`) āĻĒā§‡ā§Ÿā§‡ āϝāĻžāĻŦ⧇āύāĨ¤ āĻ•āĻžāĻ°ā§āĻ—ā§‹ " -"āύāĻŋāĻ°ā§āĻŽāĻžāĻŖāĻ•āĻžāĻ°ā§āϝ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤ āωāĻĒāϰāĻ¨ā§āϤ⧁ `rustup` āĻ“ āĻĒā§‡ā§Ÿā§‡ āϝāĻžāĻŦ⧇āύāĨ¤ āĻāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšā§Ÿā§‡ " -"āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āĻāϰ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ āĻāĻ•āχ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ āĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦāĻžāϰ āϜāĻ¨ā§āϝ⧇āĨ¤" -#: src/cargo.md -msgid "" -"After installing Rust, you should configure your editor or IDE to work with " -"Rust. Most editors do this by talking to [rust-analyzer](https://rust-" -"analyzer.github.io/), which provides auto-completion and jump-to-definition " -"functionality for [VS Code](https://code.visualstudio.com/), [Emacs](https://" -"rust-analyzer.github.io/manual.html#emacs), [Vim/Neovim](https://rust-" -"analyzer.github.io/manual.html#vimneovim), and many others. There is also a " -"different IDE available called [RustRover](https://www.jetbrains.com/rust/)." +#: src/SUMMARY.md src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md +msgid "Implementing an unsafe trait" msgstr "" -"āϰāĻžāĻ¸ā§āϟ āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻŦāĻžāϰ āĻĒāϰ⧇ āφāĻĒāύāĻžāϰ āĻāĻĄāĻŋāϟāϰ āĻŦāĻž āφāχ.āĻĄāĻŋ.āχ āϏāĻœā§āϜāĻŋāϤ āĻ•āϰāĻž āĻĻāϰāĻ•āĻžāϰāĨ¤ āĻŦ⧇āĻļāĻŋāϰāĻ­āĻžāĻ— āĻāĻĄāĻŋāϟāϰ " -"āĻāχāϜāĻ¨ā§āϝ⧇ [rust-analyzer](https://rust-analyzer.github.io/) āĻāϰ āϏāĻžāĻĨ⧇ āϝ⧋āĻ—āĻžāϝ⧋āĻ— āĻ•āϰ⧇ " -"āĻ•āϰāϤ⧇ āϏāĻ•ā§āώāĻŽāĨ¤ [rust-analyzer](https://rust-analyzer.github.io/) [VS Code]" -"(https://code.visualstudio.com/), [Emacs](https://rust-analyzer.github.io/" -"manual.html#emacs), [Vim/Neovim](https://rust-analyzer.github.io/manual." -"html#vimneovim) āĻāĻŦāĻ‚ āχāĻ¤ā§āϝāĻžāĻĻāĻŋāϰ āϜāĻ¨ā§āϝ⧇ āĻ¸ā§āĻŦāϝāĻŧāĻ‚-āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖāϤāĻž āĻāĻŦāĻ‚ āϏāϰāĻžāϏāϰāĻŋ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧ āϖ⧁āϜāĻžāϰ āĻŽāϤāύ " -"āĻ•āĻžāĻ°ā§āϝāĻ•āĻžāϰāĻŋāϤāĻž āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇āĨ¤ āφāϰ⧇āϟāĻž āφāχ.āĻĄāĻŋ.āχ-āĻ“ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇ āĻāĻ–āĻžāύ⧇ āϝāĻžāϰ āύāĻžāĻŽ " -"[RustRover](https://www.jetbrains.com/rust/)āĨ¤" -#: src/cargo.md -msgid "" -"On Debian/Ubuntu, you can also install Cargo, the Rust source and the [Rust " -"formatter](https://github.com/rust-lang/rustfmt) via `apt`. However, this " -"gets you an outdated rust version and may lead to unexpected behavior. The " -"command would be:" +#: src/SUMMARY.md src/unsafe-deep-dive/introduction/warm-up/unsafe-trait.md +msgid "Defining an unsafe trait" msgstr "" -"āĻĄā§‡āĻŦāĻŋ⧟āĻžāύ āĻŦāĻž āωāĻŦ⧁āĻ¨ā§āϟ⧁ āϤ⧇āĻ“ `apt` āĻĻā§āĻŦāĻžāϰāĻž āφāĻĒāύāĻŋ āĻ•āĻžāĻ°ā§āĻ—ā§‹, āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻ‰ā§ŽāϏ āĻāĻŦāĻ‚ [Rust formatter]" -"(https://github.com/rust-lang/rustfmt) āχāύāĻ¸ā§āϟāϞ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻāχ āĻĒāĻĻā§āϧāϤāĻŋāϤ⧇ " -"āĻ•āϰāϞ⧇ āĻĒ⧁āϰ⧋āύ⧋ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āϏāĻ‚āĻ•āϰāĻŖ āĻĒāĻžāĻŦāĻžāϰ āϏāĻŽā§āĻ­āĻŦāύāĻž āφāϛ⧇āĨ¤ āĻāϰ āĻĻāϰ⧁āύ āĻ…āĻĒā§āϰāĻ¤ā§āϝāĻžāĻļāĻŋāϤ āφāϚāϰāĻŖ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻšāϤ⧇ " -"āĻĒāĻžāϰ⧇āĨ¤ āĻāϰ āϜāĻ¨ā§āϝ⧇ āĻ•āĻŽā§āϝāĻžāĻ¨ā§āĻĄ āĻšāϞ⧋:" -#: src/cargo/rust-ecosystem.md -msgid "The Rust Ecosystem" -msgstr "The Rust āĻāϰ āχāϕ⧋āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ" +#: src/SUMMARY.md src/unsafe-deep-dive/introduction.md +msgid "Characteristics of Unsafe Rust" +msgstr "" -#: src/cargo/rust-ecosystem.md -msgid "" -"The Rust ecosystem consists of a number of tools, of which the main ones are:" -msgstr "The Rust ecosystem āĻ āĻŦ⧇āĻļ āĻ•āϝāĻŧ⧇āĻ•āϟāĻŋ āϏāϰāĻžā§āϜāĻžāĻŽ āϰāϝāĻŧ⧇āϛ⧇, āϝāĻžāϰ āĻŽāĻ§ā§āϝ⧇ āĻĒā§āϰāϧāĻžāύāϗ⧁āϞāĻŋ āĻšāϞ:" +#: src/SUMMARY.md +msgid "Dangerous" +msgstr "" -#: src/cargo/rust-ecosystem.md -msgid "" -"`rustc`: the Rust compiler which turns `.rs` files into binaries and other " -"intermediate formats." +#: src/SUMMARY.md +msgid "Sometimes necessary" msgstr "" -"`rustc`: Rust āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āϝāĻž `.rs` āĻĢāĻžāχāϞāϗ⧁āϞāĻŋāϕ⧇ āĻŦāĻžāχāύāĻžāϰāĻŋ āĻāĻŦāĻ‚ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝāϗ⧁āϞāĻŋāϤ⧇ āĻĒāϰāĻŋāĻŖāϤ āĻ•āϰ⧇ " -"āĻŽāĻ§ā§āϝāĻŦāĻ°ā§āϤ⧀ āĻŦāĻŋāĻ¨ā§āϝāĻžāϏ⧇āĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"`cargo`: the Rust dependency manager and build tool. Cargo knows how to " -"download dependencies, usually hosted on , and it will " -"pass them to `rustc` when building your project. Cargo also comes with a " -"built-in test runner which is used to execute unit tests." +#: src/SUMMARY.md +msgid "Sometimes useful" msgstr "" -"`cargo`: āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āύāĻŋāĻ°ā§āĻ­āϰāϤāĻž āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāĻ• āĻāĻŦāĻ‚ āύāĻŋāĻ°ā§āĻŽāĻžāĻŖ āϏāĻžāϧāύ⧀āĨ¤ āĻ•āĻžāĻ°ā§āĻ—ā§‹ āϜāĻžāύ⧇ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ " -"\\-āĻ āĻšā§‹āĻ¸ā§āϟ āĻ•āϰāĻž āϝ⧇ āϏāĻŦ āĻ•ā§āĻ°ā§āϝāĻžāϟāϗ⧁āϞ⧋ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§‡āϰ āϜāĻ¨ā§āϝ⧇ āĻĻāϰāĻ•āĻžāϰ āϏ⧇āϗ⧁āϞāĻŋ " -"āĻĄāĻžāωāύāϞ⧋āĻĄ āĻ•āϰāϤ⧇ āĻšāϝāĻŧ āĻāĻŦāĻ‚ āĻāϟāĻŋ āϤāĻžāĻĻ⧇āϰ āĻĒāĻžāϏ āĻ•āϰāĻŦ⧇ āφāĻĒāύāĻžāϰ āĻĒā§āϰāĻœā§‡āĻ•ā§āϟ āϤ⧈āϰāĻŋ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ `rustc` " -"āϤ⧇āĨ¤ āĻ•āĻžāĻ°ā§āĻ—ā§‹ āĻāĻ•āϟāĻŋ āĻ…āĻ¨ā§āϤāĻ°ā§āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻĒāϰāĻŋāϚāĻžāϞāĻ• āĻāϰ āϏāĻ™ā§āϗ⧇ āφāϏ⧇ āϰāĻžāύāĻžāϰ āϝāĻž āϏāĻ°ā§āĻŦāύāĻŋāĻŽā§āύ āĻĒāϰ⧀āĻ•ā§āώāĻž " -"āϚāĻžāϞāĻžāύ⧋āϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧāĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"`rustup`: the Rust toolchain installer and updater. This tool is used to " -"install and update `rustc` and `cargo` when new versions of Rust are " -"released. In addition, `rustup` can also download documentation for the " -"standard library. You can have multiple versions of Rust installed at once " -"and `rustup` will let you switch between them as needed." +#: src/SUMMARY.md src/unsafe-deep-dive/introduction.md +msgid "Responsibility shift" msgstr "" -"`rustup`: āϰāĻžāĻ¸ā§āϟ āϟ⧁āϞāĻšā§‡āχāύ āχāύāĻ¸ā§āϟāϞāĻžāϰ āĻāĻŦāĻ‚ āφāĻĒāĻĄā§‡āϟāĻžāϰāĨ¤ āĻāχ āϟ⧁āϞ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšāϝāĻŧ āϰāĻžāĻ¸ā§āϟ-āĻāϰ āύāϤ⧁āύ " -"āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ āĻĒā§āϰāĻ•āĻžāĻļāĻŋāϤ āĻšāϞ⧇ `rustc` āĻāĻŦāĻ‚ `cargo` āχāύāĻ¸ā§āϟāϞ āĻ“ āφāĻĒāĻĄā§‡āϟ āĻ•āϰāϤ⧇āĨ¤ āωāĻĒāϰāĻ¨ā§āϤ⧁, `rustup` " -"āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄā§‡ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋāϰ āϜāĻ¨ā§āϝ āĻĄāϕ⧁āĻŽā§‡āĻ¨ā§āĻŸā§‡āĻļāύāĻ“ āĻĄāĻžāωāύāϞ⧋āĻĄ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇ āφāĻĒāύāĻŋ āĻāĻ•āĻŦāĻžāϰ⧇ Rust āĻāϰ " -"āĻāĻ•āĻžāϧāĻŋāĻ• āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ āĻāĻŦāĻ‚ `āϰāĻ¸ā§āϟāφāĻĒ` āχāύāĻ¸ā§āϟāϞ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āĻ…āύ⧁āϏāĻžāϰ⧇ āφāĻĒāύāĻžāϕ⧇ āϤāĻžāĻĻ⧇āϰ āĻŽāĻ§ā§āϝ⧇ " -"āĻ¸ā§āϝ⧁āχāϚ āĻ•āϰāϤ⧇ āĻĻ⧇āĻŦ⧇āĨ¤" -#: src/cargo/rust-ecosystem.md src/types-and-values/hello-world.md -#: src/tuples-and-arrays/tuples-and-arrays.md src/references/exclusive.md -#: src/pattern-matching/destructuring.md src/memory-management/move.md -#: src/error-handling/try.md src/android/setup.md src/concurrency/threads.md -#: src/async/async-await.md -msgid "Key points:" -msgstr "āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ āĻĻāĻŋāĻ•:" +#: src/SUMMARY.md src/unsafe-deep-dive/introduction.md +msgid "Stronger development workflow required" +msgstr "" -#: src/cargo/rust-ecosystem.md -msgid "" -"Rust has a rapid release schedule with a new release coming out every six " -"weeks. New releases maintain backwards compatibility with old releases --- " -"plus they enable new functionality." +#: src/SUMMARY.md src/unsafe-deep-dive/introduction.md +msgid "Example: may_overflow" msgstr "" -"āϰāĻžāĻ¸ā§āϟ āĻĻā§āϰ⧁āϤ āĻĒā§āϰāĻ•āĻžāĻļ⧇āϰ āϏāĻŽāϝāĻŧāϏ⧂āĻšā§€ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰ⧇ āϝāĻžāϰ āĻĻāϰ⧁āύ āĻĒā§āϰāĻ¤ā§āϝ⧇āĻ• ā§Ŧ āĻŽāĻžāϏ āĻ…āĻ¨ā§āϤāϰ-āĻ…āĻ¨ā§āϤāϰ āύāϤ⧁āύ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ " -"āĻĒā§āϰāĻ•āĻžāĻļ āĻ•āϰāĻž āĻšā§Ÿā§‡āĨ¤ āύāϤ⧁āύ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖāϗ⧁āϞāĻŋ āĻĒ⧁āϰ⧋āύ⧋ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖāϗ⧁āϞāĻŋāϰ āϏāĻžāĻĨ⧇ āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝ āĻŦāϜāĻžāϝāĻŧ āϰāĻžāĻ–āĻžāϰ " -"āĻ…āϤāĻŋāϰāĻŋāĻ•ā§āϤ āύāϤ⧁āύ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āφāύ⧇āĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"There are three release channels: \"stable\", \"beta\", and \"nightly\"." +#: src/SUMMARY.md src/unsafe-deep-dive/safety-preconditions.md +msgid "Safety Preconditions" msgstr "" -"āύāϤ⧁āύ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ-āĻŽā§āĻ•ā§āϤāĻŋāϰ āϜāĻ¨ā§āϝ⧇ ā§ŠāϟāĻŋ āĻ—āϤāĻŋāĻĒāĻĨ āϰāĻžāĻ–āĻž āĻšā§Ÿā§‡āϛ⧇ - \"stable\" (āĻ¸ā§āĻŸā§āϝāĻžāĻŦāϞ - āĻ¸ā§āĻĨāĻŋāϤāĻŋāĻļā§€āϞ), " -"\"beta\" (āĻŦāĻŋāϟāĻž -āĻĒā§āϰāĻžāĻ• āĻŽā§āĻ•ā§āϤāĻŋ āύāĻŋāĻ°ā§āĻŽāĻŋāϤ) āĻāĻŦāĻ‚ \"nightly\" (āύāĻžāχāϟāϞāĻŋ - āϰāĻžāĻ¤ā§āϰāĻŋāĻ•āĻžāϞ⧀āύ)āĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"New features are being tested on \"nightly\", \"beta\" is what becomes " -"\"stable\" every six weeks." +#: src/SUMMARY.md +msgid "Common Preconditions" msgstr "" -"āύāϤ⧁āύ āĻŦ⧈āĻļāĻŋāĻˇā§āϟāϗ⧁āϞāĻŋ āύāĻžāχāϟāϞāĻŋ āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āϰāĻžāĻ¸ā§āϟ-āĻ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻž āĻšā§Ÿā§‡ āĻāĻŦāĻ‚ āĻŦāĻŋāϟāĻž āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āĻĒā§āϰāĻ¤ā§āϝ⧇āĻ• " -"ā§ŦāĻŽāĻžāϏ⧇ āĻ¸ā§āĻŸā§āϝāĻžāĻŦāϞ āϏāĻ‚āĻ•āϰāĻŖ āĻšā§Ÿā§‡ āϝāĻžā§ŸāĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"Dependencies can also be resolved from alternative [registries](https://doc." -"rust-lang.org/cargo/reference/registries.html), git, folders, and more." +#: src/SUMMARY.md src/unsafe-deep-dive/safety-preconditions/getter.md +msgid "Getter example" msgstr "" -"āĻĄāĻŋāĻĒ⧇āĻ¨ā§āĻĄā§‡āĻ¨ā§āϏāĻŋāϰ āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰāĻŦāĻžāϰ āϜāĻ¨ā§āϝ⧇ āϝ⧇āϕ⧋āύ⧋ [āĻŦ⧈āĻ•āĻ˛ā§āĻĒāĻŋāĻ• āϰ⧇āϜāĻŋāĻ¸ā§āĻŸā§āϰāĻŋ](https://doc.rust-" -"lang.org/cargo/reference/registries.html), āĻ—āĻŋāĻŸā§, āĻĢā§‹āĻ˛ā§āĻĄāĻžāϰ āχāĻ¤ā§āϝāĻžāĻĻāĻŋāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ“ āĻ•āϰāĻž " -"āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"Rust also has [editions](https://doc.rust-lang.org/edition-guide/): the " -"current edition is Rust 2021. Previous editions were Rust 2015 and Rust 2018." +#: src/SUMMARY.md +#: src/unsafe-deep-dive/safety-preconditions/semantic-preconditions.md +msgid "Semantic preconditions" msgstr "" -"āϰāĻžāĻ¸ā§āĻŸā§‡āϰ [āĻĒā§āϰāĻ•āĻžāĻļāύ](https://doc.rust-lang.org/edition-guide/) -āĻ“ āφāϛ⧇: āχāĻĻāĻžāύāĻŋāĻ‚ " -"āϰāĻžāĻ¸ā§āϟ ⧍ā§Ļ⧍⧧ āĻĒā§āϰāĻ•āĻžāĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšā§ŸāĨ¤ āĻāϰ āφāϗ⧇āϰ āĻĒā§āϰāĻ•āĻžāĻļāύāϗ⧁āϞāĻŋ āĻšāϞ⧋ āϰāĻžāĻ¸ā§āϟ ⧍ā§Ļā§§ā§Ģ āĻāĻŦāĻ‚ āϰāĻžāĻ¸ā§āϟ ⧍ā§Ļā§§āĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"The editions are allowed to make backwards incompatible changes to the " -"language." -msgstr "āĻāĻ•āϟāĻŋ āĻĒā§āϰāĻ•āĻžāĻļāύ āφāϗ⧇āϰ āĻĒā§āϰāĻ•āĻžāĻļāύ āĻāϰ āϏāĻ™ā§āϗ⧇ āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝ āĻŦāϜāĻžā§Ÿ āύāĻžāĻ“ āϰāĻžāĻ–āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" +#: src/SUMMARY.md src/unsafe-deep-dive/safety-preconditions/u8-to-bool.md +msgid "Example: u8 to bool" +msgstr "" -#: src/cargo/rust-ecosystem.md -msgid "" -"To prevent breaking code, editions are opt-in: you select the edition for " -"your crate via the `Cargo.toml` file." +#: src/SUMMARY.md +msgid "Determining preconditions" msgstr "" -"āϝāĻžāϤ⧇ āϕ⧋āĻĄ āĻ•āϰāĻŦāĻžāϰ āĻĻāϰ⧁āύ āϭ⧇āϙ⧇ āύāĻž āϝāĻžā§Ÿ āϤāĻžāχ āύāĻŋāĻœā§‡āϰ āĻĒāĻ›āĻ¨ā§āĻĻ⧇āϰ āĻŽāϤāύ āĻĒā§āϰāĻ•āĻžāĻļāύ āĻŦ⧇āρāĻšā§‡ āύ⧇āĻŦāĻžāϰ āϏ⧁āĻŦāĻŋāϧāĻž " -"`Cargo.toml` āĻĢāĻžāχāϞ āĻĻā§āĻŦāĻžāϰāĻž āĻĻ⧇āĻ“ā§ŸāĻž āĻšā§Ÿā§‡āϛ⧇āĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"To avoid splitting the ecosystem, Rust compilers can mix code written for " -"different editions." +#: src/SUMMARY.md +msgid "Example: references" msgstr "" -"āĻŦāĻžāĻ¸ā§āϤ⧁āϤāĻ¨ā§āĻ¤ā§āϰ āϝāĻžāϤ⧇ āĻŦāĻŋāĻ­āĻžāϜāĻŋāϤ āύāĻž āĻšā§Ÿ āϝāĻžā§Ÿ āϤāĻžāχ āϰāĻžāĻ¸ā§āϟ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āφāϞāĻžāĻĻāĻž-āφāϞāĻžāĻĻāĻž āĻĒā§āϰāĻ•āĻžāĻļāύ⧇āϰ āϕ⧋āĻĄ " -"āĻāĻ•āϏāĻžāĻĨ⧇ āĻŽāĻŋāϞāĻŋā§Ÿā§‡ āĻ•āĻžāϜ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"Mention that it is quite rare to ever use the compiler directly not through " -"`cargo` (most users never do)." +#: src/SUMMARY.md src/unsafe-deep-dive/safety-preconditions/defining.md +msgid "Defining your own preconditions" msgstr "" -"āϤāĻŦ⧇ āĻāϟāĻžāĻ“ āωāĻ˛ā§āϞ⧇āĻ–ā§āϝāϝ⧋āĻ—ā§āϝ āϝ⧇ āĻŦ⧇āĻļāĻŋāϰāĻ­āĻžāĻ— āϏāĻŽā§Ÿā§‡ `cargo` āύāĻž āĻ•āĻžāĻœā§‡ āϞāĻžāĻ—āĻŋā§Ÿā§‡ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āϧāϰ⧇ āĻ•āĻžāϜ " -"āĻ•āϰāĻž āϖ⧁āĻŦāχ āĻĻ⧁āĻ°ā§āϞāĻ­ (āĻŦ⧇āĻļāĻŋāϰāĻ­āĻžāĻ— āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āĻ•āĻ–āύāχ āϤāĻž āĻ•āϰ⧇ āĻĨāĻžāϕ⧇ āύāĻž)āĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"It might be worth alluding that Cargo itself is an extremely powerful and " -"comprehensive tool. It is capable of many advanced features including but " -"not limited to:" +#: src/SUMMARY.md src/unsafe-deep-dive/safety-preconditions/ascii.md +msgid "Example: ASCII Type" msgstr "" -"āĻāĻŦāĻ‚ āĻāϟāĻžāĻ“ āĻŦāϞ⧇ āϰāĻžāĻ–āĻž āĻĻāϰāĻ•āĻžāϰ āϝ⧇ āĻ•āĻžāĻ°ā§āĻ—ā§‹ āύāĻŋāĻœā§‡āĻ“ āĻ…āύ⧇āĻ• āĻ•ā§āώāĻŽāϤāĻžāĻļā§€āϞ āĻ“ āĻŦāĻŋāĻ¸ā§āϤ⧀āĻ°ā§āĻŖ āĻāĻ•āϟāĻŋ āϏāĻžāϧāύāĨ¤ āĻāϰ " -"āĻĻā§āĻŦāĻžāϰāĻž āĻāĻ•āĻžāϧāĻŋāĻ• āφāϧ⧁āύāĻŋāĻ• āĻ•āĻžāϜ āĻ•āϰāĻž āϏāĻŽā§āĻ­āĻŦ āϝ⧇āĻŽāύ:" -#: src/cargo/rust-ecosystem.md -msgid "Project/package structure" -msgstr "āĻĒā§āϰāĻœā§‡āĻ•ā§āϟ/āĻĒā§āϝāĻžāϕ⧇āϜ āĻāϰ āĻ—āĻ āύ" +#: src/SUMMARY.md src/unsafe-deep-dive/rules-of-the-game.md +msgid "Rules of the game" +msgstr "" -#: src/cargo/rust-ecosystem.md -msgid "[workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html)" +#: src/SUMMARY.md src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md +msgid "Rust is sound" msgstr "" -"[āĻ•āĻ°ā§āĻŽāĻ•ā§āώ⧇āĻ¤ā§āϰ āĻŦāĻž āĻ“ā§ŸāĻžāĻ°ā§āĻ•āĻ¸ā§āĻĒ⧇āϏ⧇āϏ](https://doc.rust-lang.org/cargo/reference/" -"workspaces.html)" -#: src/cargo/rust-ecosystem.md -msgid "Dev Dependencies and Runtime Dependency management/caching" -msgstr "āĻĄā§‡āĻ­ āĻāĻŦāĻ‚ āϰāĻžāύāϟāĻŋāĻŽā§‡āϰ āύāĻŋāĻ°ā§āĻ­āϰāϤāĻž āĻĒāϰāĻŋāϚāĻžāϞāύāĻž āĻāĻŦāĻ‚ āĻ•ā§āϝāĻžāĻļāĻŋāĻ‚" +#: src/SUMMARY.md +msgid "Copying memory" +msgstr "" -#: src/cargo/rust-ecosystem.md -msgid "" -"[build scripting](https://doc.rust-lang.org/cargo/reference/build-scripts." -"html)" +#: src/SUMMARY.md src/unsafe-deep-dive/introduction/responsibility-shift.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +msgid "Safe Rust" msgstr "" -"[āύāĻŋāĻ°ā§āĻŽāĻžāϪ⧇āϰ āϞāĻŋāĻĒāĻŋāϰāϚāύāĻž](https://doc.rust-lang.org/cargo/reference/build-scripts." -"html)" -#: src/cargo/rust-ecosystem.md -msgid "" -"[global installation](https://doc.rust-lang.org/cargo/commands/cargo-install." -"html)" +#: src/SUMMARY.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md +msgid "Encapsulated Unsafe Rust" msgstr "" -"[āϏāĻžāĻ°ā§āĻŦāϜāύ⧀āύ āĻ¸ā§āĻĨāĻžāĻĒāύāĻž](https://doc.rust-lang.org/cargo/commands/cargo-install." -"html)" -#: src/cargo/rust-ecosystem.md -msgid "" -"It is also extensible with sub command plugins as well (such as [cargo " -"clippy](https://github.com/rust-lang/rust-clippy))." +#: src/SUMMARY.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "Exposed Unsafe Rust" msgstr "" -"[cargo clippy](https://github.com/rust-lang/rust-clippy)-āϰ āĻŽāϤāύ āύāĻžāύāĻžāύ āωāĻĒ-āφāĻĻ⧇āĻļ " -"āĻĒā§āϞāĻžāĻ—āĻŋāύ āĻ•āĻžāĻœā§‡ āϞāĻžāĻ—āĻŋā§Ÿā§‡āĻ“ āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āϰāĻž āϝāĻžā§ŸāĨ¤" -#: src/cargo/rust-ecosystem.md -msgid "" -"Read more from the [official Cargo Book](https://doc.rust-lang.org/cargo/)" +#: src/SUMMARY.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "Documented safety preconditions" msgstr "" -"[āĻ…āĻĢāĻŋāϏāĻŋ⧟āĻžāϞ āĻ•āĻžāĻ°ā§āĻ—ā§‹ āĻŦāχ](https://doc.rust-lang.org/cargo/) āϤ⧇ āĻāχ āĻŦā§āϝāĻžāĻĒāĻžāϰ⧇ āφāϰāĻ“ āĻĒ⧜āϤ⧇ " -"āĻĒāĻžāϰāĻŦ⧇āύāĨ¤" -#: src/cargo/code-samples.md -msgid "Code Samples in This Training" -msgstr "āĻāχ āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāϪ⧇ āϕ⧋āĻĄ āύāĻŽā§āύāĻž" +#: src/SUMMARY.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/crying-wolf.md +msgid "Crying Wolf" +msgstr "" -#: src/cargo/code-samples.md -msgid "" -"For this training, we will mostly explore the Rust language through examples " -"which can be executed through your browser. This makes the setup much easier " -"and ensures a consistent experience for everyone." +#: src/SUMMARY.md +msgid "3 shapes of sound Rust" msgstr "" -"āĻāχ āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāϪ⧇āϰ āϜāĻ¨ā§āϝ, āφāĻŽāϰāĻž āĻŦ⧇āĻļāĻŋāϰāĻ­āĻžāĻ— āĻāĻŽāύ āωāĻĻāĻžāĻšāϰāϪ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āϰāĻžāĻ¸ā§āϟ āĻ­āĻžāώāĻž āĻ…āĻ¨ā§āĻŦ⧇āώāĻŖ āĻ•āϰāĻŦ āϝāĻž " -"āφāĻĒāύāĻžāϰ āĻŦā§āϰāĻžāωāϜāĻžāϰ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻ•āĻžāĻ°ā§āϝāĻ•āϰ āϚāϞāϤ⧇ āĻĒāĻžāϰāĻŦ⧇āĨ¤ āĻāϟāĻŋ āϏ⧇āϟāφāĻĒāϟāĻŋāϕ⧇ āφāϰāĻ“ āϏāĻšāϜ āĻ•āϰ⧇ āϤ⧋āϞ⧇ āĻāĻŦāĻ‚ " -"āĻĒā§āϰāĻ¤ā§āϝ⧇āϕ⧇āϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āϧāĻžāϰāĻžāĻŦāĻžāĻšāĻŋāĻ• āĻ…āĻ­āĻŋāĻœā§āĻžāϤāĻž āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧇āĨ¤" -#: src/cargo/code-samples.md -msgid "" -"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 work with dependencies and for that you need Cargo." +#: src/SUMMARY.md src/unsafe-deep-dive/rules-of-the-game/soundness-proof.md +msgid "Soundness Proof" msgstr "" -"āĻ•āĻžāĻ°ā§āĻ—ā§‹ āχāύāĻ¸ā§āϟāϞ āĻ•āϰ⧇ āύ⧇āĻ“ā§ŸāĻž āĻ­āĻžāϞ⧋: āĻāϟāĻŋ āφāĻĒāύāĻžāϰ āϜāĻ¨ā§āϝ āĻ…āύ⧁āĻļā§€āϞāύ⧀ āϏāĻšāϜ āĻ•āϰ⧇ āϤ⧁āϞāĻŦ⧇āĨ¤ āĻļ⧇āώ⧇āϰ āĻĻāĻŋāύ⧇ " -"āφāĻŽāϰāĻž āĻāĻ•āϟāĻŋ āĻ…āύ⧁āĻļā§€āϞāύ⧀ āĻ•āϰāĻŦ āϝāĻž āφāĻĒāύāĻžāϕ⧇ āĻĻ⧇āĻ–āĻžāĻŦ⧇ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻĄāĻŋāĻĒ⧇āĻ¨ā§āĻĄā§‡āĻ¨ā§āϏāĻŋāϰ āϏāĻžāĻĨ⧇ āĻ•āĻžāϜ āĻ•āϰāϤ⧇ āĻšāϝāĻŧ " -"āĻāĻŦāĻ‚ āĻāϰ āϜāĻ¨ā§āϝ āφāĻĒāύāĻžāϰ āĻ•āĻžāĻ°ā§āĻ—ā§‹ āĻĨāĻžāĻ•āĻž āĻĻāϰāĻ•āĻžāϰāĨ¤" -#: src/cargo/code-samples.md -msgid "The code blocks in this course are fully interactive:" -msgstr "āĻāχ āϕ⧋āĻ°ā§āϏ⧇āϰ āϕ⧋āĻĄ āĻŦā§āϞāĻ•āϗ⧁āϞāĻŋ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āχāĻ¨ā§āϟāĻžāϰ⧇āĻ•ā§āϟāĻŋāĻ­:" +#: src/SUMMARY.md +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/soundness.md +msgid "Soundness" +msgstr "" -#: src/cargo/code-samples.md src/cargo/running-locally.md -msgid "\"Edit me!\"" -msgstr "\"āφāĻŽāĻžāϕ⧇ āĻŦāĻĻāϞ⧇ āĻĻ⧇āĻ–ā§‹ āϤ⧋ āĻĻ⧇āĻ–āĻŋ!\"" +#: src/SUMMARY.md +msgid "Corollary" +msgstr "" -#: src/cargo/code-samples.md -msgid "You can use " -msgstr "āϝāĻ–āύ āĻŸā§‡āĻ•ā§āϏāϟ āĻŦāĻ•ā§āϏ āĻ āĻĢā§‹āĻ•āĻžāϏ āĻĨāĻžāϕ⧇ āϤāĻ–āύ āϕ⧋āĻĄāϟāĻŋ āĻāĻ•ā§āϏāĻŋāĻ•āĻŋāωāϟ āĻ•āϰāϤ⧇ āφāĻĒāύāĻŋ " +#: src/SUMMARY.md +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/unsoundness.md +msgid "Unsoundness" +msgstr "" -#: src/cargo/code-samples.md -msgid " to execute the code when focus is in the text box." -msgstr " āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤" +#: src/SUMMARY.md src/unsafe-deep-dive/memory-lifecycle.md +msgid "Memory Lifecycle" +msgstr "" -#: src/cargo/code-samples.md -msgid "" -"Most code samples are editable like shown above. A few code samples are not " -"editable for various reasons:" +#: src/SUMMARY.md +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +#: src/unsafe-deep-dive/initialization.md +msgid "Initialization" msgstr "" -"āĻŦ⧇āĻļāĻŋāϰāĻ­āĻžāĻ— āϕ⧋āĻĄ āύāĻŽā§āύāĻž āωāĻĒāϰ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻŽāϤ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻžāϝ⧋āĻ—ā§āϝāĨ¤ āĻ•āϝāĻŧ⧇āĻ•āϟāĻŋ āϕ⧋āĻĄ āύāĻŽā§āύāĻž āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻ•āĻžāϰāϪ⧇ " -"āϏāĻŽā§āĻĒāĻžāĻĻāύāĻžāϝ⧋āĻ—ā§āϝ āύāϝāĻŧ:" -#: src/cargo/code-samples.md -msgid "" -"The embedded playgrounds cannot execute unit tests. Copy-paste the code and " -"open it in the real Playground to demonstrate unit tests." +#: src/SUMMARY.md src/unsafe-deep-dive/initialization/maybeuninit.md +msgid "MaybeUninit" msgstr "" -"āĻ…āύ⧁āĻŦāĻŋāĻĻā§āϧ āĻĒā§āϞ⧇āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄāϟāĻŋ āĻāĻ•āĻ• āĻĒāϰ⧀āĻ•ā§āώāĻž āϚāĻžāϞāĻžāϤ⧇ āĻĒāĻžāϰāĻŦ⧇ āύāĻžāĨ¤ āĻāĻ•āĻ• āĻĒāϰ⧀āĻ•ā§āώāĻžāϗ⧁āϞāĻŋ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ⧇āϰ āϜāĻ¨ā§āϝ " -"āϕ⧋āĻĄāϟāĻŋ āĻ•āĻĒāĻŋ-āĻĒ⧇āĻ¸ā§āϟ āĻ•āϰ⧁āύ āφāϏāϞ āĻĒā§āϞ⧇āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄā§‡āĨ¤" -#: src/cargo/code-samples.md -msgid "" -"The embedded playgrounds lose their state the moment you navigate away from " -"the page! This is the reason that the students should solve the exercises " -"using a local Rust installation or via the Playground." +#: src/SUMMARY.md +msgid "Arrays of uninit" msgstr "" -"āĻ…āύ⧁āĻŦāĻŋāĻĻā§āϧ āĻĒā§āϞ⧇āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄāϗ⧁āϞāĻŋāϰ āĻ…āĻŦāĻ¸ā§āĻĨāĻž āĻ•ā§āώāĻŖāĻ¸ā§āĻĨāĻžā§Ÿā§€ - āĻ…āĻ¨ā§āϝ āĻ“ā§Ÿā§‡āĻŦāĻĒ⧇āϜ āĻ āϗ⧇āϞ⧇ āĻāϗ⧁āϞāĻŋ āφāĻŦāĻžāϰ āĻĒ⧁āϰ⧋āύ⧋ " -"āĻ…āĻŦāĻ¸ā§āĻĨāĻžā§Ÿ āĻĢāĻŋāϰ⧇ āϝāĻžāĻŦ⧇! āĻāχ āĻ•āĻžāϰāϪ⧇āχ āĻ›āĻžāĻ¤ā§āϰāĻĻ⧇āϰ āύāĻŋāĻœā§‡āϰ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡ āϰāĻžāĻ¸ā§āϟ āχāύāĻ¸ā§āϟāϞ⧇āĻļāύ āĻ•āϰ⧇ āφāϏāϞ " -"āĻĒā§āϞ⧇āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄā§‡āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻ…āύ⧁āĻļā§€āϞāύāϗ⧁āϞāĻŋ āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰāĻž āωāϚāĻŋāϤāĨ¤" -#: src/cargo/running-locally.md -msgid "Running Code Locally with Cargo" -msgstr "Cargo āĻāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻ¸ā§āĻĨāĻžāύ⧀āϝāĻŧāĻ­āĻžāĻŦ⧇ āϕ⧋āĻĄ āϚāĻžāϞāĻžāύ⧋" +#: src/SUMMARY.md +#: src/unsafe-deep-dive/initialization/maybeuninit/zeroed-method.md +msgid "MaybeUninit::zeroed()" +msgstr "" -#: src/cargo/running-locally.md -msgid "" -"If you want to experiment with the code on your own system, then you will " -"need to first install Rust. Do this by following the [instructions in the " -"Rust Book](https://doc.rust-lang.org/book/ch01-01-installation.html). This " -"should give you a working `rustc` and `cargo`. At the time of writing, the " -"latest stable Rust release has these version numbers:" +#: src/SUMMARY.md +msgid "ptr::write vs assignment" msgstr "" -"āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āφāĻĒāύāĻžāϰ āύāĻŋāĻœā§‡āϰ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡ āϕ⧋āĻĄāϟāĻŋ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāϤ⧇ āϚāĻžāύ āϤāĻŦ⧇ āφāĻĒāύāĻžāϕ⧇ āĻĒā§āϰāĻĨāĻŽā§‡ āϰāĻžāĻ¸ā§āϟ " -"āχāύāĻ¸ā§āϟāϞ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤ [āϰāĻžāĻ¸ā§āϟ āĻŦāχāϝāĻŧ⧇āϰ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻžāĻŦāϞ⧀](https://doc.rust-lang.org/book/" -"ch01-01-installation.html) āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰ⧇ āĻāϟāĻŋ āĻ•āϰ⧁āύāĨ¤ āĻāϰāχ āĻ­āĻžāĻŦ⧇ āφāĻĒāύāĻŋ āĻ•āĻžāĻœā§‡ āϞāĻžāĻ—āĻžāύ⧋āϰ āĻŽāϤāύ " -"`rustc` āĻāĻŦāĻ‚ `cargo` āĻĒā§‡ā§Ÿā§‡ āϝāĻžāĻŦ⧇āύāĨ¤ āĻāχ āĻŦāχāϟāĻŋ āϞāĻŋāĻ–āĻŦāĻžāϰ āϏāĻŽā§Ÿā§‡, āϏāĻ°ā§āĻŦāĻļ⧇āώ āĻ¸ā§āĻĨāĻŋāϤāĻŋāĻļā§€āϞ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ " -"āĻŽā§āĻ•ā§āϤāĻŋāϰ āĻāχ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ āϏāĻ‚āĻ–ā§āϝāĻž āϰāϝāĻŧ⧇āϛ⧇:" -#: src/cargo/running-locally.md -msgid "" -"You can use any later version too since Rust maintains backwards " -"compatibility." +#: src/SUMMARY.md +msgid "How to initialize memory" msgstr "" -"āφāĻĒāύāĻŋ āĻĒāϰāĻŦāĻ°ā§āϤ⧀ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖāĻ“ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ āϝ⧇āĻšā§‡āϤ⧁ āϰāĻžāĻ¸ā§āϟ āϐāϤāĻŋāĻšāĻžāϏāĻŋāĻ• āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝ āĻŦāϜāĻžāϝāĻŧ āϰāĻžāϖ⧇āĨ¤" -#: src/cargo/running-locally.md -msgid "" -"With this in place, follow these steps to build a Rust binary from one of " -"the examples in this training:" +#: src/SUMMARY.md +msgid "Partial initialization" msgstr "" -"āĻāϟāĻŋāϰ āϏāĻžāĻĨ⧇, āĻāχ āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāϪ⧇āϰ āωāĻĻāĻžāĻšāϰāĻŖāϗ⧁āϞāĻŋāϰ āĻŽāĻ§ā§āϝ⧇ āĻāĻ•āϟāĻŋ āĻĨ⧇āϕ⧇ āĻāĻ•āϟāĻŋ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻŦāĻžāχāύāĻžāϰāĻŋ āϤ⧈āϰāĻŋ " -"āĻ•āϰāϤ⧇ āĻāχ āĻĒāĻĻāĻ•ā§āώ⧇āĻĒāϗ⧁āϞāĻŋ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰ⧁āύ:" -#: src/cargo/running-locally.md -msgid "Click the \"Copy to clipboard\" button on the example you want to copy." +#: src/SUMMARY.md src/unsafe-deep-dive/pinning.md +msgid "Pinning" msgstr "" -"āφāĻĒāύāĻŋ \"Copy to clipboard\" āĻŦāĻžāϟāύ āĻĻāĻžāĻŦāĻŋā§Ÿā§‡ āϝ⧇āχ āωāĻĻāĻžāĻšāϰāĻŖāϟāĻŋ āϚāĻžāύ āϏ⧇āϟāĻŋ āĻ•āĻĒāĻŋ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤" -#: src/cargo/running-locally.md -msgid "" -"Use `cargo new exercise` to create a new `exercise/` directory for your code:" +#: src/SUMMARY.md src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/what-pinning-is.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "What pinning is" msgstr "" -"āφāĻĒāύāĻžāϰ āϕ⧋āĻĄā§‡āϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āύāϤ⧁āύ `exercise/` āĻĄāĻŋāϰ⧇āĻ•ā§āϟāϰāĻŋ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ ``cargo new " -"exercise` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ:" -#: src/cargo/running-locally.md -msgid "" -"Navigate into `exercise/` and use `cargo run` to build and run your binary:" +#: src/SUMMARY.md +msgid "What a move is" msgstr "" -"`exercise/` -āĻĄāĻŋāϰ⧇āĻ•ā§āϟāϰāĻŋāϤ⧇ āĻ—āĻŋā§Ÿā§‡ āφāĻĒāύāĻžāϰ āĻŦāĻžāχāύāĻžāϰāĻŋ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻ“ āϏ⧇āϟāĻž āϚāĻžāϞāĻžāϤ⧇ `cargo " -"run` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ:" -#: src/cargo/running-locally.md -msgid "" -"Replace the boiler-plate code in `src/main.rs` with your own code. For " -"example, using the example on the previous page, make `src/main.rs` look like" +#: src/SUMMARY.md +msgid "Definition of Pin" msgstr "" -"`src/main.rs`-āĻāϰ āĻĨ⧇āϕ⧇ āĻŦāϝāĻŧāϞāĻžāϰāĻĒā§āϞ⧇āϟ āϕ⧋āĻĄ āϏāϰāĻŋā§Ÿā§‡ āύāĻŋāĻœā§‡āϰ āϕ⧋āĻĄ āĻĻāĻŋā§Ÿā§‡ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύāĨ¤ āϝ⧇āĻŽāύ " -"āφāϗ⧇āϰ āĻĒ⧃āĻˇā§āĻ āĻžāϰ āωāĻĻāĻžāĻšāϰāĻŖ āĻ•āĻžāĻœā§‡ āϞāĻžāĻ—āĻŋā§Ÿā§‡ `src/main.rs`-āϟāĻŋāϕ⧇ āĻāĻŽāύāĻŋ āĻŦāĻžāύāĻŋā§Ÿā§‡ āĻĢ⧇āϞ⧁āύ" -#: src/cargo/running-locally.md -msgid "Use `cargo run` to build and run your updated binary:" -msgstr "`cargo run` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āύāĻŋāĻœā§‡āϰ āĻŦāĻŋāύāĻžāϰ⧀āϟāĻŋāϕ⧇ āĻŦāĻžāύāĻžāύ āĻāĻŦāĻ‚ āφāĻĒāĻĄā§‡āϟ āĻ•āϰ⧁āύ:" +#: src/SUMMARY.md +msgid "Why it's difficult" +msgstr "" -#: src/cargo/running-locally.md -msgid "" -"Use `cargo check` to quickly check your project for errors, use `cargo " -"build` to compile it without running it. You will find the output in `target/" -"debug/` for a normal debug build. Use `cargo build --release` to produce an " -"optimized release build in `target/release/`." +#: src/SUMMARY.md +msgid "`Unpin` trait" msgstr "" -"āφāĻĒāύāĻžāϰ āĻĒā§āϰāĻœā§‡āĻ•ā§āϟāĻŋāϰ āĻĻā§āϰ⧁āϤ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰ⧇ āĻ¤ā§āϰ⧁āϟāĻŋāϰ āĻŦ⧇āϰ āĻ•āϰāĻŦāĻžāϰ āϜāĻ¨ā§āϝ `cargo check` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ, " -"āĻāϟāĻŋāϕ⧇ āύāĻž āϚāĻžāϞāĻŋāϝāĻŧ⧇ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻ•āϰāϤ⧇ `cargo build` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤ āĻāĻ•āϟāĻŋ āϏāĻžāϧāĻžāϰāĻŖ āĻĄāĻŋāĻŦāĻžāĻ— " -"āĻŦāĻŋāĻ˛ā§āĻĄā§‡āϰ āϜāĻ¨ā§āϝ āφāĻĒāύāĻŋ āφāωāϟāĻĒ⧁āϟāĻŋ `target/debug/` āĻĄāĻŋāϰ⧇āĻ•ā§āϟāϰāĻŋāϤ⧇ āĻĒāĻžāĻŦ⧇āύāĨ¤ `target/release/`-āĻ " -"āĻāĻ•āϟāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜāĻĄ āϰāĻŋāϞāĻŋāϜ āĻŦāĻŋāĻ˛ā§āĻĄ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ `cargo build --release` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤" -#: src/cargo/running-locally.md -msgid "" -"You can add dependencies for your project by editing `Cargo.toml`. When you " -"run `cargo` commands, it will automatically download and compile missing " -"dependencies for you." +#: src/SUMMARY.md +msgid "`PhantomPinned`" msgstr "" -"`Cargo.toml` āĻŦāĻĻāϞ⧇ āφāĻĒāύāĻŋ āύāĻŋāĻœā§‡āϰ āĻĒā§āϰāĻœā§‡āĻ•ā§āĻŸā§‡ āφāϰāĻ“ āύāϤ⧁āύ āĻĄāĻŋāĻĒ⧇āĻ¨ā§āĻĄā§‡āĻ¨ā§āϏāĻŋ āϝ⧋āĻ— āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤\n" -"āφāĻĒāύāĻŋ āϝāĻ–āύ `cargo` āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āϚāĻžāϞāĻžāύ, āϤāĻ–āύ āĻāϟāĻŋ āύāĻŋāĻœā§‡-āύāĻŋāĻœā§‡āχ āφāĻĒāύāĻžāϰ āϜāĻ¨ā§āϝ āĻ…āύ⧁āĻĒāĻ¸ā§āĻĨāĻŋāϤ " -"āĻĄāĻŋāĻĒ⧇āĻ¨ā§āĻĄā§‡āĻ¨ā§āϏāĻŋāϗ⧁āϞāĻŋ āĻĄāĻžāωāύāϞ⧋āĻĄ āĻāĻŦāĻ‚ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻ•āϰāĻŦ⧇āĨ¤" -#: src/cargo/running-locally.md -msgid "" -"Try to encourage the class participants to install Cargo and use a local " -"editor. It will make their life easier since they will have a normal " -"development environment." +#: src/SUMMARY.md src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "Self-Referential Buffer Example" msgstr "" -"āĻ•ā§āϞāĻžāϏ āĻ…āĻ‚āĻļāĻ—ā§āϰāĻšāĻŖāĻ•āĻžāϰ⧀āĻĻ⧇āϰ Cargo āχāύāĻ¸ā§āϟāϞ āĻ•āϰāϤ⧇ āĻāĻŦāĻ‚ āĻāĻ•āϟāĻŋ āϞ⧋āĻ•āĻžāϞ āĻāĻĄāĻŋāϟāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ " -"āĻ‰ā§ŽāϏāĻžāĻšāĻŋāϤ āĻ•āϰāĻžāϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰ⧁āύāĨ¤ āĻāϟāĻŋ āϤāĻžāĻĻ⧇āϰ āĻœā§€āĻŦāύāϕ⧇ āϏāĻšāϜ āĻ•āϰ⧇ āϤ⧁āϞāĻŦ⧇ āϝ⧇āĻšā§‡āϤ⧁ āϤāĻžāĻĻ⧇āϰ āĻāĻ•āϟāĻŋ " -"āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• āĻĄā§‡āϭ⧇āϞāĻĒāĻŽā§‡āĻ¨ā§āϟ āĻāύāĻ­āĻžāχāϰāύāĻŽā§‡āĻ¨ā§āϟ āĻĨāĻžāĻ•āĻŦ⧇āĨ¤" -#: src/welcome-day-1.md -msgid "Welcome to Day 1" -msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύ⧇ āφāĻĒāύāĻžāϕ⧇ āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ" +#: src/SUMMARY.md +msgid "C++ implementation" +msgstr "" -#: src/welcome-day-1.md -msgid "" -"This is the first day of Rust Fundamentals. We will cover a lot of ground " -"today:" -msgstr "āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻŽā§‚āϞāĻŦāĻŋāώ⧟ āϚāĻ°ā§āϚāĻžāϰ āĻāϟāĻŋ āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύāĨ¤ āφāĻŽāϰāĻž āφāϜāϕ⧇ āĻ…āύ⧇āĻ•āĻ•āĻŋāϛ⧁ āĻŦ⧁āĻāĻŦāĻžāϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻŦā§‹āĨ¤" +#: src/SUMMARY.md src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md +msgid "Modeled in Rust" +msgstr "" -#: src/welcome-day-1.md -msgid "" -"Basic Rust syntax: variables, scalar and compound types, enums, structs, " -"references, functions, and methods." +#: src/SUMMARY.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +msgid "With a raw pointer" msgstr "" -"āϰāĻžāϤ āĻāϰ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āĻļāĻŦā§āĻĻāĻŦāĻŋāĻ¨ā§āϝāĻžāϏ: āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ, āĻ¸ā§āϕ⧇āϞāĻžāϰ āĻāĻŦāĻ‚ āϝ⧌āĻ—āĻŋāĻ• āĻĒā§āϰāĻ•āĻžāϰ, āχāύāĻžāĻŽ, āĻ¸ā§āĻŸā§āϰāĻžāĻ•ā§āϟ, " -"āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ, āĻĢāĻžāĻ‚āĻļāύ, āĻāĻŦāĻ‚ āĻĒāĻĻā§āϧāϤāĻŋāĨ¤" -#: src/welcome-day-1.md -msgid "Types and type inference." -msgstr "āϟāĻžāχāĻĒ āĻāĻŦāĻ‚ āϟāĻžāχāĻĒ⧇āϰ āĻ…āύ⧁āĻŽāĻžāύ āĻ•āϰāĻž" +#: src/SUMMARY.md +msgid "With an integer offset" +msgstr "" -#: src/welcome-day-1.md -msgid "Control flow constructs: loops, conditionals, and so on." -msgstr "āύāĻŋāϝāĻŧāĻ¨ā§āĻ¤ā§āϰāĻŖ āĻĒā§āϰāĻŦāĻžāĻš āĻ—āĻ āύ: āϞ⧁āĻĒ, āĻļāĻ°ā§āϤāϏāĻžāĻĒ⧇āĻ•ā§āώāĻ—āĻ āύ āĻāĻŦāĻ‚ āφāϰāĻ“ āĻ…āύ⧇āĻ• āĻ•āĻŋāϛ⧁āĨ¤" +#: src/SUMMARY.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-pin.md +msgid "With `Pin`" +msgstr "" -#: src/welcome-day-1.md -msgid "User-defined types: structs and enums." -msgstr "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀-āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āϟāĻžāχāĻĒ: āĻˇā§āĻŸā§āϰāĻžāĻ•ā§āϟ āĻ“ āχāύāĻžāĻŽ" +#: src/SUMMARY.md +msgid "`Pin` and `Drop`" +msgstr "" -#: src/welcome-day-1.md -msgid "Pattern matching: destructuring enums, structs, and arrays." -msgstr "āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āĻŽā§āϝāĻžāϚāĻŋāĻ‚: āχāύāĻžāĻŽ, āĻˇā§āĻŸā§āϰāĻžāĻ•ā§āϟ āĻāĻŦāĻ‚ āĻ…ā§āϝāĻžāϰ⧇ āĻĄāĻŋāĻ¸ā§āĻŸā§āϰāĻžāĻ•ā§āϟāϚāĻžāϰ āĻ•āϰāĻžāĨ¤" +#: src/SUMMARY.md +msgid "Worked Example" +msgstr "" -#: src/welcome-day-1.md src/welcome-day-2.md src/welcome-day-3.md -#: src/welcome-day-4.md -msgid "Schedule" -msgstr "āϏāĻŽāϝāĻŧāϏ⧂āĻšā§€" +#: src/SUMMARY.md src/unsafe-deep-dive/ffi.md +msgid "FFI" +msgstr "" -#: src/welcome-day-1.md src/welcome-day-1-afternoon.md src/welcome-day-2.md -#: src/welcome-day-2-afternoon.md src/welcome-day-3.md -#: src/welcome-day-3-afternoon.md src/welcome-day-4.md -#: src/welcome-day-4-afternoon.md -msgid "In this session:" -msgstr "āĻāχ āĻ…āϧāĻŋāĻŦ⧇āĻļāύ⧇:" +#: src/SUMMARY.md src/unsafe-deep-dive/ffi/language-interop.md +msgid "Language Interop" +msgstr "" -#: src/welcome-day-1.md -msgid "[Welcome](./welcome-day-1.md) (5 minutes)" -msgstr "[āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ](./welcome-day-1.md) (ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" - -#: src/welcome-day-1.md -msgid "[Hello, World](./hello-world.md) (15 minutes)" -msgstr "[āĻšā§āϝāĻžāϞ⧋,āĻ“ā§ŸāĻžāĻ°ā§āĻ˛ā§āĻĄ](./hello-world.md) (ā§§ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +msgid "Strategies" +msgstr "" -#: src/welcome-day-1.md -msgid "[Types and Values](./types-and-values.md) (45 minutes)" -msgstr "[āϟāĻžāχāĻĒ āĻāĻŦāĻ‚ āϤāĻžāĻĻ⧇āϰ āĻŽāĻžāύ](./types-and-values.md) (ā§Ēā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/unsafe-deep-dive/ffi/type-safety.md +msgid "Consideration: Type Safety" +msgstr "" -#: src/welcome-day-1.md -msgid "[Control Flow Basics](./control-flow-basics.md) (40 minutes)" -msgstr "[āϏāĻŽā§āĻĒāĻžāĻĻāύ āĻĒā§āϰāĻŦāĻžāĻš āύāĻŋāϝāĻŧāĻ¨ā§āĻ¤ā§āϰāĻŖ āĻāϰ āĻŽā§āϞāĻœā§āĻžāĻžāύ](./control-flow-basics.md) (ā§Ēā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/unsafe-deep-dive/ffi/language-differences.md +msgid "Language differences" +msgstr "" -#: src/welcome-day-1.md src/welcome-day-3-afternoon.md -#: src/welcome-day-4-afternoon.md -msgid "" -"Including 10 minute breaks, this session should take about 2 hours and 10 " -"minutes" -msgstr "ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ āĻŦāĻŋāϰāϤāĻŋāϏāĻš āĻāχ āĻ…āϧāĻŋāĻŦ⧇āĻļāύāϟāĻŋ ⧍ āϘāĻ¨ā§āϟāĻž ā§§ā§Ļ āĻŽāĻŋāύāĻŋāĻŸā§‡āϰ" +#: src/SUMMARY.md +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "Different representations" +msgstr "" -#: src/welcome-day-1.md -msgid "Please remind the students that:" -msgstr "āĻļāĻŋāĻ•ā§āώāĻžāĻ°ā§āĻĨā§€āĻĻ⧇āϰ āĻāϟāĻŋ āĻŽāύ⧇ āĻ•āϰāĻŋāϝāĻŧ⧇ āĻĻāĻŋāύ āϝ⧇āσ" +#: src/SUMMARY.md src/unsafe-deep-dive/ffi/language-differences/semantics.md +msgid "Different semantics" +msgstr "" -#: src/welcome-day-1.md -msgid "" -"They should ask questions when they get them, don't save them to the end." +#: src/SUMMARY.md src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Rust ↔ C" msgstr "" -"āϤāĻžāĻĻ⧇āϰ āĻĒā§āϰāĻļā§āύ āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻ•āϰāĻž āωāϚāĻŋāϤ āϝāĻ–āύ āϤāĻžāϰāĻž āϏ⧇āϗ⧁āϞāĻŋ āĻĒāĻžāĻŦ⧇, āĻļ⧇āώ āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻŦāĻžāρāϚāĻŋā§Ÿā§‡ āϰ⧇āϖ⧇ āϞāĻžāĻ­ " -"āύ⧇āχāĨ¤" -#: src/welcome-day-1.md -msgid "" -"The class is meant to be interactive and discussions are very much " -"encouraged!" +#: src/SUMMARY.md src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "C++ ↔ C" msgstr "" -"āĻāχ āĻ•ā§āϞāĻžāϏāϟāĻŋ āĻŽāĻŋāĻĨāĻˇā§āĻ•ā§āϰāĻŋ⧟ āĻšāĻ“ā§ŸāĻž āĻĻāϰāĻ•āĻžāϰ āĻāĻŦāĻ‚ āϤāĻžāϰ āϜāĻ¨ā§āϝ⧇ āĻŦāĻŋāώāϝāĻŧ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āϤāĻ°ā§āĻ•-āĻŦāĻŋāϤāĻ°ā§āĻ• āĻ•āϰāϤ⧇ āωāĻ¤ā§āϏāĻžāĻš " -"āĻĻ⧇āĻ“āϝāĻŧāĻž āωāϚāĻŋāϤāĨ¤" -#: src/welcome-day-1.md -msgid "" -"As an instructor, you should try to keep the discussions relevant, i.e., " -"keep the discussions related to how Rust does things vs some other language. " -"It can be hard to find the right balance, but err on the side of allowing " -"discussions since they engage people much more than one-way communication." +#: src/SUMMARY.md src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Rust ↔ C++" msgstr "" -"āĻāĻ•āϜāύ āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāĻ• āĻšāĻŋāϏāĻžāĻŦ⧇, āφāĻĒāύāĻžāϰ āφāϞ⧋āϚāύāĻžāϗ⧁āϞāĻŋāϕ⧇ āĻĒā§āϰāĻžāϏāĻ™ā§āĻ—āĻŋāĻ• āϰāĻžāĻ–āĻžāϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻž āωāϚāĻŋāϤ, āĻ…āĻ°ā§āĻĨāĻžā§Ž, " -"āĻ…āĻ¨ā§āϝ āϕ⧋āύ āĻ­āĻžāώāĻž āĻŦāύāĻžāĻŽ āϰāĻžāĻ¸ā§āϟ āϕ⧀āĻ­āĻžāĻŦ⧇ āϜāĻŋāύāĻŋāϏāϗ⧁āϞāĻŋ āĻ•āϰ⧇ āϤāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āφāϞ⧋āϚāύāĻžāϗ⧁āϞāĻŋ āϰāĻžāϖ⧁āύāĨ¤ " -"āϏāĻ āĻŋāĻ• āĻ­āĻžāϰāϏāĻžāĻŽā§āϝ āϖ⧁āρāĻœā§‡ āĻĒāĻžāĻ“āϝāĻŧāĻž āĻ•āĻ āĻŋāύ āĻšāϤ⧇ āĻĒāĻžāϰ⧇, āϤāĻŦ⧇ āφāϞ⧋āϚāύāĻžāϰ āĻ…āύ⧁āĻŽāϤāĻŋ āĻĻ⧇āĻ“āϝāĻŧāĻžāϰ āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇ āϭ⧁āϞ āĻšāϤ⧇ " -"āĻĒāĻžāϰ⧇ āĻ•āĻžāϰāĻŖ āϤāĻžāϰāĻž āĻāĻ•āĻŽā§āĻ–ā§€ āϝ⧋āĻ—āĻžāϝ⧋āϗ⧇āϰ āĻšā§‡āϝāĻŧ⧇ āĻ…āύ⧇āĻ• āĻŦ⧇āĻļāĻŋ āϞ⧋āĻ•āϕ⧇ āϜāĻĄāĻŧāĻŋāϤ āĻ•āϰ⧇āĨ¤" -#: src/welcome-day-1.md -msgid "" -"The questions will likely mean that we talk about things ahead of the slides." -msgstr "āϝāĻĻāĻŋ āϕ⧋āύ⧋ āĻĒā§āϰāĻļā§āύ āφāϏ⧇ āϤāĻžāĻšāϞ⧇ āϏ⧇āϟāĻž āϏāĻŽā§āĻ­āĻŦāϤ āϏāĻžāĻŽāύ⧇āϰ āĻ¸ā§āϞāĻžāχāĻĄ āĻāϰ āĻŦāĻŋāώ⧟āϗ⧁āϞāĻŋ āύāĻŋā§Ÿā§‡āχ āφāϏāĻŦ⧇āĨ¤" +#: src/SUMMARY.md +msgid "`abs(3)`" +msgstr "" -#: src/welcome-day-1.md -msgid "" -"This is perfectly okay! Repetition is an important part of learning. " -"Remember that the slides are just a support and you are free to skip them as " -"you like." +#: src/SUMMARY.md +msgid "`rand(3)`" msgstr "" -"āĻāϟāĻž āϭ⧁āϞ āĻŦā§āϝāĻžāĻĒāĻžāϰ āύ⧟! āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ āĻļ⧇āĻ–āĻžāϰ āĻāĻ•āϟāĻŋ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ āĻ…āĻ‚āĻļāĨ¤ āĻŽāύ⧇ āϰāĻžāĻ–āĻŦ⧇āύ āϝ⧇ āĻ¸ā§āϞāĻžāχāĻĄāϗ⧁āϞāĻŋ " -"āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āĻāĻ•āϟāĻŋ āϏāĻŽāĻ°ā§āĻĨāύ āĻāĻŦāĻ‚ āφāĻĒāύāĻŋ āφāĻĒāύāĻžāϰ āĻĒāĻ›āĻ¨ā§āĻĻ āĻŽāϤ⧋ āϏ⧇āϗ⧁āϞāĻŋ āĻāĻĄāĻŧāĻŋāϝāĻŧ⧇ āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤" -#: src/welcome-day-1.md -msgid "" -"The idea for the first day is to show the \"basic\" things in Rust that " -"should have immediate parallels in other languages. The more advanced parts " -"of Rust come on the subsequent days." +#: src/SUMMARY.md +msgid "Exercise:C library" msgstr "" -"āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύ⧇āϰ āϧāĻžāϰāĻŖāĻžāϟāĻŋ āĻšāϞ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ \"āĻŽā§ŒāϞāĻŋāĻ•\" āϜāĻŋāύāĻŋāϏāϗ⧁āϞāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āϝāĻž āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻ­āĻžāώāĻžāϝāĻŧ " -"āĻ…āĻŦāĻŋāϞāĻŽā§āĻŦ⧇ āϏāĻŽāĻžāĻ¨ā§āϤāϰāĻžāϞ āĻšāĻ“āϝāĻŧāĻž āωāϚāĻŋāϤāĨ¤ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āφāϰ⧋ āωāĻ¨ā§āύāϤ āĻ…āĻ‚āĻļ āĻĒāϰāĻŦāĻ°ā§āϤ⧀ āĻĻāĻŋāύ⧇ āφāϞ⧋āϚāύāĻž āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤" -#: src/welcome-day-1.md -msgid "" -"If you're teaching this in a classroom, this is a good place to go over the " -"schedule. Note that there is an exercise at the end of each segment, " -"followed by a break. Plan to cover the exercise solution after the break. " -"The times listed here are a suggestion in order to keep the course on " -"schedule. Feel free to be flexible and adjust as necessary!" +#: src/SUMMARY.md +msgid "Exercise: C++ library" msgstr "" -"āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻļā§āϰ⧇āĻŖā§€āĻ•āĻ•ā§āώ⧇ āĻļ⧇āĻ–āĻžāύ āϤāĻžāĻšāϞ⧇ āĻāϟāĻŋ āϏāĻŽāϝāĻŧāϏ⧂āĻšā§€āϤ⧇ āϝāĻžāĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āĻ­āĻžāϞ " -"āϜāĻžāϝāĻŧāĻ—āĻžāĨ¤ āĻŽāύ⧇ āϰāĻžāĻ–āĻŦ⧇āύ āϝ⧇ āĻĒā§āϰāϤāĻŋāϟāĻŋ āϏ⧇āĻ—āĻŽā§‡āĻ¨ā§āĻŸā§‡āϰ āĻļ⧇āώ⧇ āĻāĻ•āϟāĻŋ āĻ…āύ⧁āĻļā§€āϞāύ āϰāϝāĻŧ⧇āϛ⧇, āϤāĻžāϰāĻĒāϰ⧇ āĻāĻ•āϟāĻŋ " -"āĻŦāĻŋāϰāϤāĻŋāĻ“ āϰāϝāĻŧ⧇āϛ⧇āĨ¤ āĻŦāĻŋāϰāϤāĻŋāϰ āĻĒāϰ⧇ āĻ…āύ⧁āĻļā§€āϞāύ⧀āϰ āϏāĻŽāĻžāϧāĻžāύāϚāĻ°ā§āϚāĻž āĻ•āϰāĻž āĻ­āĻžāϞ⧋āĨ¤ āϕ⧋āĻ°ā§āϏāϟāĻŋ āϏāĻŽāϝāĻŧāϏ⧂āĻšā§€āϤ⧇ āϰāĻžāĻ–āĻžāϰ " -"āϜāĻ¨ā§āϝ āĻāĻ–āĻžāύ⧇ āϤāĻžāϞāĻŋāĻ•āĻžāϭ⧁āĻ•ā§āϤ āϏāĻŽāϝāĻŧāϗ⧁āϞāĻŋ āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻĻ⧇āĻ“ā§ŸāĻž āĻšā§Ÿā§‡āϛ⧇āĨ¤ āĻŦāĻŋāύāĻž āĻĻā§āĻŦāĻŋāϧāĻžāϝāĻŧ āĻāĻŦāĻ‚ " -"āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ āĻšāĻŋāϏāĻžāĻŦ⧇ āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝ āĻ•āϰ⧁āύ āĻ­āĻžāϞ⧋ āĻ•āϰ⧇ āĻĒā§‹ā§œāĻžāύ⧋āϰ āϜāĻ¨ā§āϝ⧇!" -#: src/hello-world.md src/types-and-values.md src/control-flow-basics.md -#: src/tuples-and-arrays.md src/references.md src/user-defined-types.md -#: src/pattern-matching.md src/methods-and-traits.md src/generics.md -#: src/std-types.md src/std-traits.md src/memory-management.md -#: src/smart-pointers.md src/borrowing.md src/slices-and-lifetimes.md -#: src/iterators.md src/modules.md src/testing.md src/error-handling.md -#: src/unsafe-rust.md -msgid "In this segment:" -msgstr "āĻāχ āĻ…āĻ‚āĻļ⧇:" +#: src/SUMMARY.md +msgid "Final Words" +msgstr "" -#: src/hello-world.md -msgid "[What is Rust?](./hello-world/what-is-rust.md) (10 minutes)" -msgstr "[āϰāĻžāĻ¸ā§āϟ āĻ•āĻŋ?](./hello-world/what-is-rust.md) (ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md src/thanks.md +msgid "Thanks!" +msgstr "" -#: src/hello-world.md -msgid "[Benefits of Rust](./hello-world/benefits.md) (3 minutes)" -msgstr "[āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āϏ⧁āĻŦāĻŋāϧ⧇](./hello-world/benefits.md) (ā§Š āĻŽāĻŋāύāĻŋāϟ)" +#. Please keep { #glossary } untranslated. +#: src/SUMMARY.md src/glossary.md +msgid "Glossary" +msgstr "" -#: src/hello-world.md -msgid "[Playground](./hello-world/playground.md) (2 minutes)" -msgstr "[āĻĒā§āϞ⧇āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄ](./hello-world/playground.md) (⧍ āĻŽāĻŋāύāĻŋāϟ)" +#: src/SUMMARY.md +msgid "Other Resources" +msgstr "" -#: src/hello-world.md -msgid "This segment should take about 15 minutes" -msgstr "āĻāχ āĻ…āĻ‚āĻļāϟāĻŋ āĻļ⧇āώ āĻ•āϰāϤ⧇ āĻĒā§āϰāĻžā§Ÿ ā§§ā§Ģ āĻŽāĻŋāύāĻŋāϟ āϞāĻžāĻ—āĻŦ⧇" +#: src/SUMMARY.md src/credits.md +msgid "Credits" +msgstr "" -#: src/hello-world/what-is-rust.md +#: src/index.md msgid "" -"Rust is a new programming language which had its [1.0 release in 2015]" -"(https://blog.rust-lang.org/2015/05/15/Rust-1.0.html):" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/" +"google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" +"google/comprehensive-rust/actions/workflows/build.yml?query=branch%3Amain) [!" +"[GitHub contributors](https://img.shields.io/github/contributors/google/" +"comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors) [![GitHub stars](https://img.shields." +"io/github/stars/google/comprehensive-rust?style=flat-square)](https://github." +"com/google/comprehensive-rust/stargazers)" msgstr "" -"Rust āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāĻŋāĻ‚ āĻ­āĻžāώāĻž āϝ⧇āϟāĻžāϰ āĻ›āĻŋāϞ⧋ [1.0 āĻĒā§āϰāĻ•āĻžāĻļ 2015 āϤ⧇](https://blog." -"rust-lang.org/2015/05/15/Rust-1.0.html):" - -#: src/hello-world/what-is-rust.md -msgid "Rust is a statically compiled language in a similar role as C++" -msgstr " āϏāĻŋ++ āĻāϰ āĻŽāϤāύ, āϰāĻžāĻ¸ā§āϟāĻ“ 'āĻāĻ•āϟāĻŋ āĻ¸ā§āĻĨāĻŋāϤāĻŋāĻļā§€āϞāĻ­āĻžāĻŦ⧇ āϏāĻ‚āĻ•āϞāĻŋāϤ āĻ­āĻžāώāĻž" - -#: src/hello-world/what-is-rust.md -msgid "`rustc` uses LLVM as its backend." -msgstr "`rustc` āĻāϞ.āĻāϞ.āĻ­āĻŋ.āĻāĻŽ āύ⧇āĻĒāĻĨā§āϝ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇" -#: src/hello-world/what-is-rust.md +#: src/index.md msgid "" -"Rust supports many [platforms and architectures](https://doc.rust-lang.org/" -"nightly/rustc/platform-support.html):" +"This is a free Rust course developed by the Android team at Google. The " +"course covers the full spectrum of Rust, from basic syntax to advanced " +"topics like generics and error handling." msgstr "" -"āϰāĻžāĻ¸ā§āϟ āĻ…āύ⧇āĻ•āϗ⧁āϞāĻŋ [āĻĒā§āĻ˛ā§āϝāĻžāϟāĻĢāĻ°ā§āĻŽ āĻāĻŦāĻ‚ āφāĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āϚāĻžāϰ](https://doc.rust-lang.org/nightly/" -"rustc/platform-support.html) āϏāĻŽāĻ°ā§āĻĨāύ āĻ•āϰ⧇ āϝ⧇āĻŽāύ:" - -#: src/hello-world/what-is-rust.md -msgid "x86, ARM, WebAssembly, ..." -msgstr "x86, ARM, WebAssembly, ..." -#: src/hello-world/what-is-rust.md -msgid "Linux, Mac, Windows, ..." -msgstr "Linux, Mac, Windows, ..." +#: src/index.md +msgid "" +"The latest version of the course can be found at . If you are reading somewhere else, please check there " +"for updates." +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "Rust is used for a wide range of devices:" -msgstr "āϰāĻžāĻ¸ā§āϟ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻĄāĻŋāĻ­āĻžāχāϏ⧇āϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧ:" +#: src/index.md +msgid "" +"The course is available in other languages. Select your preferred language " +"in the top right corner of the page or check the [Translations](running-the-" +"course/translations.md) page for a list of all available translations." +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "firmware and boot loaders," -msgstr "āĻĢāĻžāĻ°ā§āĻŽāĻ“ā§Ÿā§āϝāĻžāϰ āĻāĻŦāĻ‚ āĻŦ⧁āϟ āĻ˛ā§‹ā§ŸāĻžāĻĄāĻ°ā§āϏ," +#: src/index.md +msgid "The course is also available [as a PDF](comprehensive-rust.pdf)." +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "smart displays," -msgstr "āĻ¸ā§āĻŽāĻžāĻ°ā§āϟ āĻĄāĻŋāϏāĻĒā§āϞ⧇," +#: src/index.md +msgid "" +"The goal of the course is to teach you Rust. We assume you don't know " +"anything about Rust and hope to:" +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "mobile phones," -msgstr "āĻŽā§‹āĻŦāĻžāχāϞ āĻĢā§‹āύ," +#: src/index.md +msgid "Give you a comprehensive understanding of the Rust syntax and language." +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "desktops," -msgstr "āĻĄā§‡āĻ¸ā§āĻ•āϟāĻĒ," +#: src/index.md +msgid "Enable you to modify existing programs and write new programs in Rust." +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "servers." -msgstr "āϏāĻžāĻ°ā§āĻ­āĻžāϰāĨ¤" +#: src/index.md +msgid "Show you common Rust idioms." +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "Rust fits in the same area as C++:" -msgstr "Rust āĻ āĻŋāĻ• C++ āĻāϰ āĻŽāϤ⧋ āϏāĻŦāϜāĻžāϝāĻŧāĻ—āĻžāϝāĻŧ āĻ–āĻžāĻĒ āĻ–āĻžāϝāĻŧ:" +#: src/index.md +msgid "We call the first four course days Rust Fundamentals." +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "High flexibility." -msgstr "āωāĻšā§āϚāĻ¸ā§āϤāϰ⧇āϰ āύāĻŽāύ⧀āϝāĻŧāϤāĻžāĨ¤" +#: src/index.md +msgid "" +"Building on this, you're invited to dive into one or more specialized topics:" +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "High level of control." -msgstr "āύāĻŋāϝāĻŧāĻ¨ā§āĻ¤ā§āϰāϪ⧇āϰ āωāĻšā§āϚ āĻ¸ā§āϤāϰāĨ¤" +#: src/index.md +msgid "" +"[Android](android.md): a half-day course on using Rust for Android platform " +"development (AOSP). This includes interoperability with C, C++, and Java." +msgstr "" -#: src/hello-world/what-is-rust.md +#: src/index.md msgid "" -"Can be scaled down to very constrained devices such as microcontrollers." -msgstr "āĻŽāĻžāχāĻ•ā§āϰ⧋āĻ•āĻ¨ā§āĻŸā§āϰ⧋āϞāĻžāϰ⧇āϰ āĻŽāϤ⧋ āϖ⧁āĻŦ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧ āĻĄāĻŋāĻ­āĻžāχāϏ⧇ āϛ⧋āϟ āĻ•āϰ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" +"[Chromium](chromium.md): a half-day course on using Rust in Chromium-based " +"browsers. This includes interoperability with C++ and how to include third-" +"party crates in Chromium." +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "Has no runtime or garbage collection." -msgstr "āϕ⧋āύ āϰāĻžāύāϟāĻžāχāĻŽ āĻŦāĻž āφāĻŦāĻ°ā§āϜāύāĻž āϏāĻ‚āĻ—ā§āϰāĻšāĻĒā§āϰāĻŖāĻžāϞ⧀ āύ⧇āχāĨ¤" +#: src/index.md +msgid "" +"[Bare-metal](bare-metal.md): a whole-day class on using Rust for bare-metal " +"(embedded) development. Both microcontrollers and application processors are " +"covered." +msgstr "" -#: src/hello-world/what-is-rust.md -msgid "Focuses on reliability and safety without sacrificing performance." +#: src/index.md +msgid "" +"[Concurrency](concurrency/welcome.md): a whole-day class on concurrency in " +"Rust. We cover both classical concurrency (preemptively scheduling using " +"threads and mutexes) and async/await concurrency (cooperative multitasking " +"using futures)." msgstr "" -"āĻ•āĻ°ā§āĻŽāĻ•ā§āώāĻŽāϤāĻžā§Ÿā§‡ āϕ⧋āύ⧋āϰāĻ•āĻŽ āĻŦāϞāĻŋāĻĻāĻžāύ āύāĻž āĻĻāĻŋā§Ÿā§‡ āύāĻŋāĻ°ā§āĻ­āϰāϝ⧋āĻ—ā§āϝāϤāĻž āĻāĻŦāĻ‚ āύāĻŋāϰāĻžāĻĒāĻ¤ā§āϤāĻž āωāĻĒāϰ āĻĢā§‹āĻ•āĻžāϏ āĻ•āϰ⧇āĨ¤" -#: src/hello-world/benefits.md -msgid "Some unique selling points of Rust:" -msgstr "RustāĻāϰ āĻ•āĻŋāϛ⧁ āĻ…āύāĻ¨ā§āϝ āĻŦāĻŋāĻ•ā§āϰāϝāĻŧ āĻĒāϝāĻŧ⧇āĻ¨ā§āϟ:" +#: src/index.md +msgid "Non-Goals" +msgstr "" -#: src/hello-world/benefits.md +#: src/index.md msgid "" -"_Compile time memory safety_ - whole classes of memory bugs are prevented at " -"compile time" +"Rust is a large language and we won't be able to cover all of it in a few " +"days. Some non-goals of this course are:" msgstr "" -"_āϏāĻ‚āĻ•āϞāύ āϏāĻŽāϝāĻŧ āĻŽā§‡āĻŽāϰāĻŋ āύāĻŋāϰāĻžāĻĒāĻ¤ā§āϤāĻž_ - āĻ•āĻŽā§āĻĒāĻžāχāϞ⧇āϰ āϏāĻŽāϝāĻŧ āĻŽā§‡āĻŽāϰāĻŋ āĻŦāĻžāĻ—āϗ⧁āϞāĻŋāϰ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻ­āĻžāĻŦ⧇ āĻĒā§āϰāϤāĻŋāϰ⧋āϧ " -"āĻ•āϰāĻž āĻšāϝāĻŧ" - -#: src/hello-world/benefits.md -msgid "No uninitialized variables." -msgstr "āϕ⧋āύ⧋ āϏ⧂āϚāύāĻžāĻ•ā§ƒāϤ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āĻĨāĻžāϕ⧇ āύāĻžāĨ¤" -#: src/hello-world/benefits.md -msgid "No double-frees." -msgstr "āϕ⧋āύ⧋ āϰāĻ•āĻŽ āĻĄāĻžāĻŦāϞ-āĻĢā§āϰ⧇āϏ āĻšā§Ÿā§‡ āύāĻžāĨ¤" +#: src/index.md +msgid "" +"Learning how to develop macros: please see [the Rust Book](https://doc.rust-" +"lang.org/book/) and [Rust by Example](https://doc.rust-lang.org/rust-by-" +"example/macros.html) instead." +msgstr "" -#: src/hello-world/benefits.md -msgid "No use-after-free." -msgstr "āĻŽā§āĻ•ā§āϤāĻŋāϰ āĻĒāϰ⧇ āϕ⧋āύ⧋ āϰāĻ•āĻŽ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦāĻžāϰ āϜāĻžā§ŸāĻ—āĻž āύ⧇āχāĨ¤" +#: src/index.md +msgid "Assumptions" +msgstr "" -#: src/hello-world/benefits.md -msgid "No `NULL` pointers." -msgstr "āϕ⧋āύ⧋ `NULL` āĻĒā§Ÿā§‡āĻ¨ā§āϟāĻžāϰ āύ⧇āχāĨ¤" +#: src/index.md +msgid "" +"The course assumes that you already know how to program. Rust is a " +"statically-typed language and we will sometimes make comparisons with C and " +"C++ to better explain or contrast the Rust approach." +msgstr "" -#: src/hello-world/benefits.md -msgid "No forgotten locked mutexes." -msgstr "āϭ⧁āϞ āĻ•āϰ⧇ āϭ⧁āϞ⧇āϝāĻžāĻ“ āϕ⧋āύ⧋ āϞāĻ• āĻ•āϰāĻž āĻŽāĻŋāωāĻŸā§‡āĻ•ā§āϏ āĻĨāĻžāϕ⧇ āϏāĻŽā§āĻ­āĻžāĻŦāύāĻž āύ⧇āχāĨ¤" +#: src/index.md +msgid "" +"If you know how to program in a dynamically-typed language such as Python or " +"JavaScript, then you will be able to follow along just fine too." +msgstr "" -#: src/hello-world/benefits.md -msgid "No data races between threads." -msgstr "āĻĨā§āϰ⧇āĻĄā§‡āϰ āĻŽāĻžāĻā§‡ āϕ⧋āύ⧋ āϰāĻ•āĻŽā§‡āϰ āĻĄāĻžāϟāĻž āύāĻŋā§Ÿā§‡āχ āϰ⧇āϏ āĻĒāϰāĻŋāĻ¸ā§āĻĨāĻŋāϤāĻŋ āύ⧇āχāĨ¤" +#: src/index.md +msgid "" +"This is an example of a _speaker note_. We will use these to add additional " +"information to the slides. This could be key points which the instructor " +"should cover as well as answers to typical questions which come up in class." +msgstr "" -#: src/hello-world/benefits.md -msgid "No iterator invalidation." -msgstr "āχāϟāĻžāϰ⧇āϟāϰ⧇āϰ āĻ…āĻŦ⧈āϧāĻ•āϰāĻŖ āĻ•āϰāĻž āϝāĻžā§ŸāύāĻžāĨ¤" +#: src/running-the-course.md src/running-the-course/course-structure.md +msgid "This page is for the course instructor." +msgstr "" -#: src/hello-world/benefits.md +#: src/running-the-course.md msgid "" -"_No undefined runtime behavior_ - what a Rust statement does is never left " -"unspecified" +"Here is a bit of background information about how we've been running the " +"course internally at Google." msgstr "" -"_āϕ⧋āύ āĻ…āύāĻŋāĻ°ā§āϧāĻžāϰāĻŋāϤ āϰāĻžāύāϟāĻžāχāĻŽ āφāϚāϰāĻŖ āύ⧟_- āĻāĻ•āϟāĻŋ āϰāĻžāĻ¸ā§āϟ āĻŦāĻŋāĻŦ⧃āϤāĻŋ āϝāĻž āĻ•āϰ⧇ āϤāĻž āĻ•āĻ–āύāχ āĻ…āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ " -"āĻĨāĻžāϕ⧇ āύāĻž" -#: src/hello-world/benefits.md -msgid "Array access is bounds checked." -msgstr "āĻ…ā§āϝāĻžāϰ⧇ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āϏ⧀āĻŽāĻžāύāĻž āĻšā§‡āĻ• āĻ•āϰāĻž āĻšāϝāĻŧ." +#: src/running-the-course.md +msgid "" +"We typically run classes from 9:00 am to 4:00 pm, with a 1 hour lunch break " +"in the middle. This leaves 3 hours for the morning class and 3 hours for the " +"afternoon class. Both sessions contain multiple breaks and time for students " +"to work on exercises." +msgstr "" -#: src/hello-world/benefits.md -msgid "Integer overflow is defined (panic or wrap-around)." -msgstr "āĻĒā§‚āĻ°ā§āĻŖāϏāĻ‚āĻ–ā§āϝāĻž āĻ“āĻ­āĻžāϰāĻĢā§āϞ⧋ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤" +#: src/running-the-course.md +msgid "Before you run the course, you will want to:" +msgstr "" -#: src/hello-world/benefits.md +#: src/running-the-course.md msgid "" -"_Modern language features_ - as expressive and ergonomic as higher-level " -"languages" +"Make yourself familiar with the course material. We've included speaker " +"notes to help highlight the key points (please help us by contributing more " +"speaker notes!). When presenting, you should make sure to open the speaker " +"notes in a popup (click the link with a little arrow next to \"Speaker " +"Notes\"). This way you have a clean screen to present to the class." +msgstr "" + +#: src/running-the-course.md +msgid "" +"Decide on the dates. Since the course takes four days, we recommend that you " +"schedule the days over two weeks. Course participants have said that they " +"find it helpful to have a gap in the course since it helps them process all " +"the information we give them." +msgstr "" + +#: src/running-the-course.md +msgid "" +"Find a room large enough for your in-person participants. We recommend a " +"class size of 15-25 people. That's small enough that people are comfortable " +"asking questions --- it's also small enough that one instructor will have " +"time to answer the questions. Make sure the room has _desks_ for yourself " +"and for the students: you will all need to be able to sit and work with your " +"laptops. In particular, you will be doing significant live-coding as an " +"instructor, so a lectern won't be very helpful for you." +msgstr "" + +#: src/running-the-course.md +msgid "" +"On the day of your course, show up to the room a little early to set things " +"up. We recommend presenting directly using `mdbook serve` running on your " +"laptop (see the [installation instructions](https://github.com/google/" +"comprehensive-rust#building)). This ensures optimal performance with no lag " +"as you change pages. Using your laptop will also allow you to fix typos as " +"you or the course participants spot them." +msgstr "" + +#: src/running-the-course.md +msgid "" +"Let people solve the exercises by themselves or in small groups. We " +"typically spend 30-45 minutes on exercises in the morning and in the " +"afternoon (including time to review the solutions). Make sure to ask people " +"if they're stuck or if there is anything you can help with. When you see " +"that several people have the same problem, call it out to the class and " +"offer a solution, e.g., by showing people where to find the relevant " +"information in the standard library." +msgstr "" + +#: src/running-the-course.md +msgid "" +"That is all, good luck running the course! We hope it will be as much fun " +"for you as it has been for us!" +msgstr "" + +#: src/running-the-course.md +msgid "" +"Please [provide feedback](https://github.com/google/comprehensive-rust/" +"discussions/86) afterwards so that we can keep improving the course. We " +"would love to hear what worked well for you and what can be made better. " +"Your students are also very welcome to [send us feedback](https://github.com/" +"google/comprehensive-rust/discussions/100)!" +msgstr "" + +#: src/running-the-course.md +msgid "Instructor Preparation" +msgstr "" + +#: src/running-the-course.md +msgid "" +"**Go through all the material:** Before teaching the course, make sure you " +"have gone through all the slides and exercises yourself. This will help you " +"anticipate questions and potential difficulties." +msgstr "" + +#: src/running-the-course.md +msgid "" +"**Prepare for live coding:** The course involves significant live coding. " +"Practice the examples and exercises beforehand to ensure you can type them " +"out smoothly during the class. Have the solutions ready in case you get " +"stuck." +msgstr "" + +#: src/running-the-course.md +msgid "" +"**Familiarize yourself with `mdbook`:** The course is presented using " +"`mdbook`. Knowing how to navigate, search, and use its features will make " +"the presentation smoother." +msgstr "" + +#: src/running-the-course.md +msgid "" +"**Slice size helper:** Press Ctrl + Alt + B " +"to toggle a visual guide showing the amount of space available when " +"presenting. Expect any content outside of the red box to be hidden " +"initially. Use this as a guide when editing slides. You can also [enable it " +"via this link](?show-red-box=true)." +msgstr "" + +#: src/running-the-course.md +msgid "Creating a Good Learning Environment" +msgstr "" + +#: src/running-the-course.md +msgid "" +"**Encourage questions:** Reiterate that there are no \"stupid\" questions. A " +"welcoming atmosphere for questions is crucial for learning." +msgstr "" + +#: src/running-the-course.md +msgid "" +"**Manage time effectively:** Keep an eye on the schedule, but be flexible. " +"It's more important that students understand the concepts than sticking " +"rigidly to the timeline." +msgstr "" + +#: src/running-the-course.md +msgid "" +"**Facilitate group work:** During exercises, encourage students to work " +"together. This can help them learn from each other and feel less stuck." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Rust Fundamentals" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"The first four days make up [Rust Fundamentals](../welcome-day-1.md). The " +"days are fast-paced and we cover a broad range of topics!" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Course schedule:" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Day 1 Morning (2 hours and 10 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-1.md +#: src/welcome-day-1-afternoon.md src/welcome-day-2.md +#: src/welcome-day-2-afternoon.md src/welcome-day-3.md +#: src/welcome-day-3-afternoon.md src/welcome-day-4.md +#: src/welcome-day-4-afternoon.md src/concurrency/welcome.md +#: src/concurrency/welcome-async.md src/idiomatic/welcome.md +msgid "Segment" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-1.md +#: src/hello-world.md src/types-and-values.md src/control-flow-basics.md +#: src/welcome-day-1-afternoon.md src/tuples-and-arrays.md src/references.md +#: src/user-defined-types.md src/welcome-day-2.md src/pattern-matching.md +#: src/methods-and-traits.md src/generics.md src/welcome-day-2-afternoon.md +#: src/closures.md src/std-types.md src/std-traits.md src/welcome-day-3.md +#: src/memory-management.md src/smart-pointers.md +#: src/welcome-day-3-afternoon.md src/borrowing.md src/lifetimes.md +#: src/welcome-day-4.md src/iterators.md src/modules.md src/testing.md +#: src/welcome-day-4-afternoon.md src/error-handling.md src/unsafe-rust.md +#: src/concurrency/welcome.md src/concurrency/threads.md +#: src/concurrency/channels.md src/concurrency/send-sync.md +#: src/concurrency/shared-state.md src/concurrency/sync-exercises.md +#: src/concurrency/welcome-async.md src/concurrency/async.md +#: src/concurrency/async-control-flow.md src/concurrency/async-pitfalls.md +#: src/concurrency/async-exercises.md src/idiomatic/welcome.md +#: src/idiomatic/foundations-api-design.md +#: src/idiomatic/leveraging-the-type-system.md +#: src/unsafe-deep-dive/introduction.md src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "Duration" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-1.md +#: src/types-and-values.md src/control-flow-basics.md src/tuples-and-arrays.md +#: src/references.md src/user-defined-types.md src/pattern-matching.md +#: src/generics.md src/closures.md src/std-types.md src/std-traits.md +#: src/memory-management.md src/smart-pointers.md src/lifetimes.md +#: src/iterators.md src/modules.md src/testing.md src/error-handling.md +#: src/unsafe-rust.md src/concurrency/shared-state.md +#: src/concurrency/async-control-flow.md src/concurrency/async-pitfalls.md +#: src/idiomatic/leveraging-the-type-system.md +#: src/unsafe-deep-dive/introduction.md src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "5 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-1.md +#: src/types-and-values.md src/control-flow-basics.md src/tuples-and-arrays.md +#: src/user-defined-types.md src/pattern-matching.md src/methods-and-traits.md +#: src/modules.md src/unsafe-rust.md src/concurrency/welcome.md +#: src/concurrency/threads.md src/concurrency/shared-state.md +#: src/unsafe-deep-dive/introduction.md src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "15 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-1.md +#: src/borrowing.md src/concurrency/welcome-async.md +msgid "40 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-1.md +#: src/welcome-day-2.md src/welcome-day-4.md +msgid "45 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Day 1 Afternoon (2 hours and 45 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-1-afternoon.md +msgid "35 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-1-afternoon.md +#: src/welcome-day-3.md src/welcome-day-4.md src/welcome-day-4-afternoon.md +#: src/concurrency/welcome-async.md +msgid "55 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-1-afternoon.md +#: src/welcome-day-2-afternoon.md src/welcome-day-3.md +msgid "1 hour" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Day 2 Morning (2 hours and 50 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md src/hello-world.md +#: src/types-and-values.md src/control-flow-basics.md src/tuples-and-arrays.md +#: src/references.md src/welcome-day-2.md src/methods-and-traits.md +#: src/closures.md src/std-types.md src/welcome-day-3.md src/borrowing.md +#: src/lifetimes.md src/welcome-day-4.md src/iterators.md src/modules.md +#: src/testing.md src/error-handling.md src/unsafe-deep-dive/introduction.md +msgid "3 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-2.md +#: src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "50 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Day 2 Afternoon (2 hours and 50 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-2-afternoon.md +#: src/std-traits.md src/smart-pointers.md src/lifetimes.md src/iterators.md +#: src/testing.md src/unsafe-rust.md src/concurrency/welcome.md +#: src/concurrency/sync-exercises.md src/concurrency/async-exercises.md +msgid "30 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Day 3 Morning (2 hours and 20 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Day 3 Afternoon (2 hours and 30 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-3-afternoon.md +#: src/welcome-day-4-afternoon.md +msgid "1 hour and 15 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/welcome-day-3-afternoon.md +#: src/idiomatic/leveraging-the-type-system.md +msgid "1 hour and 5 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Day 4 Morning (2 hours and 50 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Day 4 Afternoon (2 hours and 20 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Deep Dives" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"In addition to the 4-day class on Rust Fundamentals, we cover some more " +"specialized topics:" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Rust in Android" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"The [Rust in Android](../android.md) deep dive is a half-day course on using " +"Rust for Android platform development. This includes interoperability with " +"C, C++, and Java." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"You will need an [AOSP checkout](https://source.android.com/docs/setup/" +"download/downloading). Make a checkout of the [course repository](https://" +"github.com/google/comprehensive-rust) on the same machine and move the `src/" +"android/` directory into the root of your AOSP checkout. This will ensure " +"that the Android build system sees the `Android.bp` files in `src/android/`." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"Ensure that `adb sync` works with your emulator or real device and pre-build " +"all Android examples using `src/android/build_all.sh`. Read the script to " +"see the commands it runs and make sure they work when you run them by hand." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Rust in Chromium" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"The [Rust in Chromium](../chromium.md) deep dive is a half-day course on " +"using Rust as part of the Chromium browser. It includes using Rust in " +"Chromium's `gn` build system, bringing in third-party libraries (\"crates\") " +"and C++ interoperability." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"You will need to be able to build Chromium --- a debug, component build is " +"[recommended](../chromium/setup.md) for speed but any build will work. " +"Ensure that you can run the Chromium browser that you've built." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Bare-Metal Rust" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"The [Bare-Metal Rust](../bare-metal.md) deep dive is a full day class on " +"using Rust for bare-metal (embedded) development. Both microcontrollers and " +"application processors are covered." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"For the microcontroller part, you will need to buy the [BBC micro:bit]" +"(https://microbit.org/) v2 development board ahead of time. Everybody will " +"need to install a number of packages as described on the [welcome page](../" +"bare-metal.md)." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Concurrency in Rust" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"The [Concurrency in Rust](../concurrency/welcome.md) deep dive is a full day " +"class on classical as well as `async`/`await` concurrency." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"You will need a fresh crate set up and the dependencies downloaded and ready " +"to go. You can then copy/paste the examples into `src/main.rs` to experiment " +"with them:" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Morning (3 hours and 20 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md src/references.md +#: src/std-types.md src/memory-management.md src/error-handling.md +#: src/concurrency/welcome.md src/concurrency/sync-exercises.md +#: src/concurrency/welcome-async.md src/concurrency/async-pitfalls.md +#: src/concurrency/async-exercises.md +#: src/idiomatic/leveraging-the-type-system.md +msgid "20 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/concurrency/welcome.md +msgid "Send and Sync" +msgstr "" + +#: src/running-the-course/course-structure.md src/concurrency/welcome.md +#: src/concurrency/welcome-async.md +msgid "1 hour and 10 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Afternoon (3 hours and 30 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"The [Idiomatic Rust](../idiomatic/welcome.md) deep dive is a 2-day class on " +"Rust idioms and patterns." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"You should be familiar with the material in [Rust Fundamentals](../welcome-" +"day-1.md) before starting this course." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Morning (14 hours and 25 minutes, including breaks)" +msgstr "" + +#: src/running-the-course/course-structure.md src/idiomatic/welcome.md +msgid "3 hours and 30 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/idiomatic/welcome.md +msgid "7 hours and 30 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md src/idiomatic/welcome.md +msgid "3 hours and 5 minutes" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Unsafe (Work in Progress)" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"The [Unsafe](../unsafe-deep-dive/welcome.md) deep dive is a two-day class on " +"the _unsafe_ Rust language. It covers the fundamentals of Rust's safety " +"guarantees, the motivation for `unsafe`, review process for `unsafe` code, " +"FFI basics, and building data structures that the borrow checker would " +"normally reject." +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "not found - {{%course outline Unsafe}}" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "Format" +msgstr "" + +#: src/running-the-course/course-structure.md +msgid "" +"The course is meant to be very interactive and we recommend letting the " +"questions drive the exploration of Rust!" +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md +msgid "There are several useful keyboard shortcuts in mdBook:" +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md +msgid "Arrow-Left: Navigate to the previous page." +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md +msgid "Arrow-Right: Navigate to the next page." +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md +msgid "" +"Ctrl + Enter: Execute the code sample that has focus." +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md +msgid "s: Activate the search bar." +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md +msgid "" +"Mention that these shortcuts are standard for `mdbook` and can be useful " +"when navigating any `mdbook`\\-generated site." +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md +msgid "You can demonstrate each shortcut live to the students." +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md +msgid "" +"The s key for search is particularly useful for quickly finding " +"topics that have been discussed earlier." +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md +msgid "" +"Ctrl + Enter will be super important for you since " +"you'll do a lot of live coding." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"The course has been translated into other languages by a set of wonderful " +"volunteers:" +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Brazilian Portuguese](https://google.github.io/comprehensive-rust/pt-BR/) " +"by [@rastringer](https://github.com/rastringer), [@hugojacob](https://github." +"com/hugojacob), [@joaovicmendes](https://github.com/joaovicmendes), and " +"[@henrif75](https://github.com/henrif75)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Chinese (Simplified)](https://google.github.io/comprehensive-rust/zh-CN/) " +"by [@suetfei](https://github.com/suetfei), [@wnghl](https://github.com/" +"wnghl), [@anlunx](https://github.com/anlunx), [@kongy](https://github.com/" +"kongy), [@noahdragon](https://github.com/noahdragon), [@superwhd](https://" +"github.com/superwhd), @SketchK, and [@nodmp](https://github.com/nodmp)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Chinese (Traditional)](https://google.github.io/comprehensive-rust/zh-TW/) " +"by [@hueich](https://github.com/hueich), [@victorhsieh](https://github.com/" +"victorhsieh), [@mingyc](https://github.com/mingyc), [@kuanhungchen](https://" +"github.com/kuanhungchen), and [@johnathan79717](https://github.com/" +"johnathan79717)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Farsi](https://google.github.io/comprehensive-rust/fa/) by [@DannyRavi]" +"(https://github.com/DannyRavi), [@javad-jafari](https://github.com/javad-" +"jafari), [@Alix1383](https://github.com/alix1383), [@moaminsharifi](https://" +"github.com/moaminsharifi) , [@hamidrezakp](https://github.com/hamidrezakp) " +"and [@mehrad77](https://github.com/mehrad77)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Japanese](https://google.github.io/comprehensive-rust/ja/) by [@CoinEZ-JPN]" +"(https://github.com/CoinEZ), [@momotaro1105](https://github.com/" +"momotaro1105), [@HidenoriKobayashi](https://github.com/HidenoriKobayashi) " +"and [@kantasv](https://github.com/kantasv)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Korean](https://google.github.io/comprehensive-rust/ko/) by [@keispace]" +"(https://github.com/keispace), [@jiyongp](https://github.com/jiyongp), " +"[@jooyunghan](https://github.com/jooyunghan), and [@namhyung](https://github." +"com/namhyung)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Spanish](https://google.github.io/comprehensive-rust/es/) by [@deavid]" +"(https://github.com/deavid)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Ukrainian](https://google.github.io/comprehensive-rust/uk/) by [@git-user-" +"cpp](https://github.com/git-user-cpp), [@yaremam](https://github.com/" +"yaremam) and [@reta](https://github.com/reta)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"Use the language picker in the top-right corner to switch between languages." +msgstr "" + +#: src/running-the-course/translations.md +msgid "Incomplete Translations" +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"There is a large number of in-progress translations. We link to the most " +"recently updated translations:" +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Arabic](https://google.github.io/comprehensive-rust/ar/) by [@younies]" +"(https://github.com/younies)" +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Bengali](https://google.github.io/comprehensive-rust/bn/) by [@raselmandol]" +"(https://github.com/raselmandol)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[French](https://google.github.io/comprehensive-rust/fr/) by [@KookaS]" +"(https://github.com/KookaS), [@vcaen](https://github.com/vcaen) and " +"[@AdrienBaudemont](https://github.com/AdrienBaudemont)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[German](https://google.github.io/comprehensive-rust/de/) by [@Throvn]" +"(https://github.com/Throvn) and [@ronaldfw](https://github.com/ronaldfw)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"[Italian](https://google.github.io/comprehensive-rust/it/) by " +"[@henrythebuilder](https://github.com/henrythebuilder) and [@detro](https://" +"github.com/detro)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"The full list of translations with their current status is also available " +"either [as of their last update](https://google.github.io/comprehensive-rust/" +"translation-report.html) or [synced to the latest version of the course]" +"(https://google.github.io/comprehensive-rust/synced-translation-report.html)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"If you want to help with this effort, please see [our instructions](https://" +"github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md) for how to " +"get going. Translations are coordinated on the [issue tracker](https://" +"github.com/google/comprehensive-rust/issues/282)." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"This is a good opportunity to thank the volunteers who have contributed to " +"the translations." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"If there are students in the class who speak any of the listed languages, " +"you can encourage them to check out the translated versions and even " +"contribute if they find any issues." +msgstr "" + +#: src/running-the-course/translations.md +msgid "" +"Highlight that the project is open source and contributions are welcome, not " +"just for translations but for the course content itself." +msgstr "" + +#: src/cargo.md +msgid "" +"When you start reading about Rust, you will soon meet [Cargo](https://doc." +"rust-lang.org/cargo/), the standard tool used in the Rust ecosystem to build " +"and run Rust applications. Here we want to give a brief overview of what " +"Cargo is and how it fits into the wider ecosystem and how it fits into this " +"training." +msgstr "" + +#: src/cargo.md +msgid "Installation" +msgstr "" + +#: src/cargo.md +msgid "**Please follow the instructions on .**" +msgstr "" + +#: src/cargo.md +msgid "" +"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 different compiler versions." +msgstr "" + +#: src/cargo.md +msgid "" +"After installing Rust, you should configure your editor or IDE to work with " +"Rust. Most editors do this by talking to [rust-analyzer](https://rust-" +"analyzer.github.io/), which provides auto-completion and jump-to-definition " +"functionality for [VS Code](https://code.visualstudio.com/), [Emacs](https://" +"rust-analyzer.github.io/manual.html#emacs), [Vim/Neovim](https://rust-" +"analyzer.github.io/manual.html#vimneovim), and many others. There is also a " +"different IDE available called [RustRover](https://www.jetbrains.com/rust/)." +msgstr "" + +#: src/cargo.md +msgid "On Debian/Ubuntu, you can install `rustup` via `apt`:" +msgstr "" + +#: src/cargo.md +msgid "" +"On macOS, you can use [Homebrew](https://brew.sh/) to install Rust, but this " +"may provide an outdated version. Therefore, it is recommended to install " +"Rust from the official site." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "The Rust Ecosystem" +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"The Rust ecosystem consists of a number of tools, of which the main ones are:" +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"`rustc`: the Rust compiler that turns `.rs` files into binaries and other " +"intermediate formats." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"`cargo`: the Rust dependency manager and build tool. Cargo knows how to " +"download dependencies, usually hosted on , and it will " +"pass them to `rustc` when building your project. Cargo also comes with a " +"built-in test runner which is used to execute unit tests." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"`rustup`: the Rust toolchain installer and updater. This tool is used to " +"install and update `rustc` and `cargo` when new versions of Rust are " +"released. In addition, `rustup` can also download documentation for the " +"standard library. You can have multiple versions of Rust installed at once " +"and `rustup` will let you switch between them as needed." +msgstr "" + +#: src/cargo/rust-ecosystem.md src/types-and-values/hello-world.md +#: src/references/exclusive.md src/memory-management/move.md +#: src/error-handling/try.md src/unsafe-rust/unsafe-functions/calling.md +#: src/android/setup.md src/concurrency/async/async-await.md +msgid "Key points:" +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"Rust has a rapid release schedule with a new release coming out every six " +"weeks. New releases maintain backwards compatibility with old releases --- " +"plus they enable new functionality." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"There are three release channels: \"stable\", \"beta\", and \"nightly\"." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"New features are being tested on \"nightly\", \"beta\" is what becomes " +"\"stable\" every six weeks." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"Dependencies can also be resolved from alternative [registries](https://doc." +"rust-lang.org/cargo/reference/registries.html), git, folders, and more." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"Rust also has [editions](https://doc.rust-lang.org/edition-guide/): the " +"current edition is Rust 2024. Previous editions were Rust 2015, Rust 2018 " +"and Rust 2021." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"The editions are allowed to make backwards incompatible changes to the " +"language." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"To prevent breaking code, editions are opt-in: you select the edition for " +"your crate via the `Cargo.toml` file." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"To avoid splitting the ecosystem, Rust compilers can mix code written for " +"different editions." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"Mention that it is quite rare to ever use the compiler directly not through " +"`cargo` (most users never do)." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"It might be worth alluding that Cargo itself is an extremely powerful and " +"comprehensive tool. It is capable of many advanced features including but " +"not limited to:" +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "Project/package structure" +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "[workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html)" +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "Dev Dependencies and Runtime Dependency management/caching" +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"[build scripting](https://doc.rust-lang.org/cargo/reference/build-scripts." +"html)" +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"[global installation](https://doc.rust-lang.org/cargo/commands/cargo-install." +"html)" +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"It is also extensible with sub command plugins as well (such as [cargo " +"clippy](https://github.com/rust-lang/rust-clippy))." +msgstr "" + +#: src/cargo/rust-ecosystem.md +msgid "" +"Read more from the [official Cargo Book](https://doc.rust-lang.org/cargo/)" +msgstr "" + +#: src/cargo/code-samples.md +msgid "Code Samples in This Training" +msgstr "" + +#: src/cargo/code-samples.md +msgid "" +"For this training, we will mostly explore the Rust language through examples " +"which can be executed through your browser. This makes the setup much easier " +"and ensures a consistent experience for everyone." +msgstr "" + +#: src/cargo/code-samples.md +msgid "" +"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 that shows you " +"how to work with dependencies and for that you need Cargo." +msgstr "" + +#: src/cargo/code-samples.md +msgid "The code blocks in this course are fully interactive:" +msgstr "" + +#: src/cargo/code-samples.md src/cargo/running-locally.md +#: src/pattern-matching/destructuring-structs.md +#: src/pattern-matching/destructuring-enums.md src/generics/trait-bounds.md +#: src/generics/impl-trait.md src/modules/filesystem.md +#: src/modules/visibility.md src/modules/paths.md src/testing/unit-tests.md +#: src/error-handling/panics.md src/error-handling/result.md +#: src/android/build-rules/binary.md src/android/build-rules/library.md +#: src/android/logging.md src/android/interoperability/with-c.md +#: src/android/interoperability/with-c/bindgen.md +#: src/android/interoperability/java.md src/concurrency/channels/unbounded.md +#: src/concurrency/channels/bounded.md +msgid "// Copyright 2022 Google LLC\n" +msgstr "" + +#: src/cargo/code-samples.md src/cargo/running-locally.md +#: src/types-and-values/hello-world.md src/types-and-values/variables.md +#: src/types-and-values/arithmetic.md src/types-and-values/inference.md +#: src/types-and-values/exercise.md src/types-and-values/solution.md +#: src/control-flow-basics/blocks-and-scopes.md src/control-flow-basics/if.md +#: src/control-flow-basics/match.md src/control-flow-basics/loops.md +#: src/control-flow-basics/loops/for.md src/control-flow-basics/loops/loop.md +#: src/control-flow-basics/break-continue.md +#: src/control-flow-basics/break-continue/labels.md +#: src/control-flow-basics/macros.md src/control-flow-basics/exercise.md +#: src/control-flow-basics/solution.md src/tuples-and-arrays/arrays.md +#: src/tuples-and-arrays/iteration.md src/tuples-and-arrays/destructuring.md +#: src/tuples-and-arrays/exercise.md src/tuples-and-arrays/solution.md +#: src/references/shared.md src/references/strings.md +#: src/references/dangling.md src/references/exercise.md +#: src/references/solution.md src/user-defined-types/named-structs.md +#: src/user-defined-types/tuple-structs.md src/user-defined-types/enums.md +#: src/user-defined-types/aliases.md src/user-defined-types/static.md +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +#: src/pattern-matching/infallible.md src/pattern-matching/match.md +#: src/pattern-matching/destructuring-structs.md +#: src/pattern-matching/destructuring-enums.md +#: src/pattern-matching/let-control-flow/if-let.md +#: src/pattern-matching/let-control-flow/while-let.md +#: src/pattern-matching/let-control-flow/let-else.md +#: src/pattern-matching/exercise.md src/pattern-matching/solution.md +#: src/methods-and-traits/methods.md src/methods-and-traits/traits.md +#: src/methods-and-traits/traits/implementing.md +#: src/methods-and-traits/traits/supertraits.md +#: src/methods-and-traits/traits/associated-types.md +#: src/methods-and-traits/deriving.md src/methods-and-traits/exercise.md +#: src/methods-and-traits/solution.md src/generics/generic-functions.md +#: src/generics/trait-bounds.md src/generics/generic-data.md +#: src/generics/generic-traits.md src/generics/impl-trait.md +#: src/generics/dyn-trait.md src/generics/exercise.md src/generics/solution.md +#: src/closures/syntax.md src/closures/capturing.md src/closures/traits.md +#: src/closures/exercise.md src/closures/solution.md src/std-types/docs.md +#: src/std-types/option.md src/std-types/result.md src/std-types/string.md +#: src/std-types/vec.md src/std-types/hashmap.md src/std-types/exercise.md +#: src/std-types/solution.md src/std-traits/comparisons.md +#: src/std-traits/operators.md src/std-traits/from-and-into.md +#: src/std-traits/casting.md src/std-traits/read-and-write.md +#: src/std-traits/default.md src/std-traits/exercise.md +#: src/std-traits/solution.md src/memory-management/review.md +#: src/memory-management/move.md src/memory-management/clone.md +#: src/memory-management/drop.md src/memory-management/exercise.md +#: src/memory-management/solution.md src/smart-pointers/box.md +#: src/smart-pointers/rc.md src/smart-pointers/trait-objects.md +#: src/smart-pointers/exercise.md src/smart-pointers/solution.md +#: src/borrowing/examples.md src/borrowing/interior-mutability/cell.md +#: src/borrowing/interior-mutability/refcell.md src/borrowing/exercise.md +#: src/borrowing/solution.md src/lifetimes/simple-borrows.md +#: src/lifetimes/returning-borrows.md src/lifetimes/multiple-borrows.md +#: src/lifetimes/borrow-both.md src/lifetimes/borrow-one.md +#: src/lifetimes/lifetime-elision.md src/lifetimes/struct-lifetimes.md +#: src/lifetimes/exercise.md src/lifetimes/solution.md +#: src/iterators/motivation.md src/iterators/iterator.md +#: src/iterators/helpers.md src/iterators/collect.md +#: src/iterators/intoiterator.md src/iterators/exercise.md +#: src/iterators/solution.md src/modules/modules.md src/modules/filesystem.md +#: src/modules/visibility.md src/modules/encapsulation.md src/modules/paths.md +#: src/modules/exercise.md src/modules/solution.md src/testing/unit-tests.md +#: src/testing/other.md src/testing/lints.md src/testing/exercise.md +#: src/testing/solution.md src/error-handling/panics.md +#: src/error-handling/result.md src/error-handling/try.md +#: src/error-handling/try-conversions.md src/error-handling/error.md +#: src/error-handling/thiserror.md src/error-handling/anyhow.md +#: src/error-handling/exercise.md src/error-handling/solution.md +#: src/unsafe-rust/dereferencing.md src/unsafe-rust/mutable-static.md +#: src/unsafe-rust/unions.md src/unsafe-rust/unsafe-functions/rust.md +#: src/unsafe-rust/unsafe-functions/extern-c.md +#: src/unsafe-rust/unsafe-functions/calling.md src/unsafe-rust/unsafe-traits.md +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +#: src/android/build-rules/binary.md src/android/build-rules/library.md +#: src/android/aidl/example-service/service-bindings.md +#: src/android/aidl/example-service/service.md +#: src/android/aidl/example-service/server.md +#: src/android/aidl/example-service/client.md +#: src/android/aidl/example-service/changing-definition.md +#: src/android/aidl/example-service/changing-implementation.md +#: src/android/aidl/types/objects.md src/android/aidl/types/parcelables.md +#: src/android/aidl/types/file-descriptor.md src/android/testing.md +#: src/android/testing/googletest.md src/android/testing/mocking.md +#: src/android/logging.md src/android/interoperability/with-c.md +#: src/android/interoperability/with-c/bindgen.md +#: src/android/interoperability/with-c/rust-library.md +#: src/android/interoperability/cpp/bridge.md +#: src/android/interoperability/cpp/rust-bridge.md +#: src/android/interoperability/cpp/generated-cpp.md +#: src/android/interoperability/cpp/cpp-bridge.md +#: src/android/interoperability/cpp/shared-types.md +#: src/android/interoperability/cpp/shared-enums.md +#: src/android/interoperability/cpp/rust-result.md +#: src/android/interoperability/cpp/cpp-exception.md +#: src/android/interoperability/java.md src/exercises/chromium/build-rules.md +#: src/chromium/testing.md src/chromium/testing/rust-gtest-interop.md +#: src/chromium/testing/chromium-import-macro.md +#: src/chromium/interoperability-with-cpp/example-bindings.md +#: src/chromium/interoperability-with-cpp/error-handling-qr.md +#: src/chromium/interoperability-with-cpp/error-handling-png.md +#: src/bare-metal/alloc.md src/bare-metal/microcontrollers/mmio.md +#: src/bare-metal/microcontrollers/pacs.md +#: src/bare-metal/microcontrollers/hals.md +#: src/bare-metal/microcontrollers/type-state.md +#: src/exercises/bare-metal/solutions-morning.md +#: src/bare-metal/aps/inline-assembly.md src/bare-metal/aps/mmio.md +#: src/bare-metal/aps/uart.md src/bare-metal/aps/uart/traits.md +#: src/bare-metal/aps/uart/using.md src/bare-metal/aps/better-uart/bitflags.md +#: src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md src/bare-metal/aps/safemmio/using.md +#: src/bare-metal/aps/logging.md src/bare-metal/aps/logging/using.md +#: src/bare-metal/aps/aarch64-rt.md +#: src/bare-metal/useful-crates/aarch64-paging.md +#: src/exercises/bare-metal/solutions-afternoon.md +#: src/concurrency/threads/plain.md src/concurrency/threads/scoped.md +#: src/concurrency/channels/senders-receivers.md +#: src/concurrency/channels/unbounded.md src/concurrency/channels/bounded.md +#: src/concurrency/shared-state/arc.md src/concurrency/shared-state/mutex.md +#: src/concurrency/shared-state/example.md +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/sync-exercises/solutions.md +#: src/concurrency/async/async-await.md src/concurrency/async/futures.md +#: src/concurrency/async/state-machine.md +#: src/concurrency/async/runtimes/tokio.md src/concurrency/async/tasks.md +#: src/concurrency/async-control-flow/channels.md +#: src/concurrency/async-control-flow/join.md +#: src/concurrency/async-control-flow/select.md +#: src/concurrency/async-pitfalls/blocking-executor.md +#: src/concurrency/async-pitfalls/pin.md +#: src/concurrency/async-pitfalls/async-traits.md +#: src/concurrency/async-pitfalls/cancellation.md +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +#: src/idiomatic/foundations-api-design/predictable-api.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/new.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/get.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/push.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/is.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/mut.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md +#: src/idiomatic/leveraging-the-type-system/raii.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +#: src/idiomatic/leveraging-the-type-system/token-types.md +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +#: src/idiomatic/polymorphism.md src/idiomatic/polymorphism/refresher.md +#: src/idiomatic/polymorphism/refresher/traits.md +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +#: src/idiomatic/polymorphism/refresher/deriving-traits.md +#: src/idiomatic/polymorphism/refresher/default-impls.md +#: src/idiomatic/polymorphism/refresher/supertraits.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md +#: src/idiomatic/polymorphism/refresher/conditional-methods.md +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +#: src/idiomatic/polymorphism/refresher/sized.md +#: src/idiomatic/polymorphism/refresher/monomorphization.md +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/composition.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-trait.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-useful.md +#: src/unsafe-deep-dive/introduction/may_overflow.md +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +#: src/unsafe-deep-dive/safety-preconditions/getter.md +#: src/unsafe-deep-dive/safety-preconditions/determining.md +#: src/unsafe-deep-dive/safety-preconditions/references.md +#: src/unsafe-deep-dive/safety-preconditions/ascii.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/crying-wolf.md +#: src/unsafe-deep-dive/initialization/maybeuninit.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md +#: src/unsafe-deep-dive/initialization/maybeuninit/zeroed-method.md +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +#: src/unsafe-deep-dive/initialization/partial-initialization.md +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +#: src/unsafe-deep-dive/pinning/definition-of-pin.md +#: src/unsafe-deep-dive/pinning/phantompinned.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-offset.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-pin.md +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md +#: src/unsafe-deep-dive/ffi/abs.md src/unsafe-deep-dive/ffi/rand.md +#: src/unsafe-deep-dive/ffi/c-library-example.md +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "// SPDX-License-Identifier: Apache-2.0\n" +msgstr "" + +#: src/cargo/code-samples.md src/cargo/running-locally.md +msgid "\"Edit me!\"" +msgstr "" + +#: src/cargo/code-samples.md +msgid "" +"You can use Ctrl + Enter to execute the code when " +"focus is in the text box." +msgstr "" + +#: src/cargo/code-samples.md +msgid "" +"Most code samples are editable like shown above. A few code samples are not " +"editable for various reasons:" +msgstr "" + +#: src/cargo/code-samples.md +msgid "" +"The embedded playgrounds cannot execute unit tests. Copy-paste the code and " +"open it in the real Playground to demonstrate unit tests." +msgstr "" + +#: src/cargo/code-samples.md +msgid "" +"The embedded playgrounds lose their state the moment you navigate away from " +"the page! This is the reason that the students should solve the exercises " +"using a local Rust installation or via the Playground." +msgstr "" + +#: src/cargo/running-locally.md +msgid "Running Code Locally with Cargo" +msgstr "" + +#: src/cargo/running-locally.md +msgid "" +"If you want to experiment with the code on your own system, then you will " +"need to first install Rust. Do this by following the [instructions in the " +"Rust Book](https://doc.rust-lang.org/book/ch01-01-installation.html). This " +"should give you a working `rustc` and `cargo`. At the time of writing, the " +"latest stable Rust release has these version numbers:" +msgstr "" + +#: src/cargo/running-locally.md +msgid "" +"You can use any later version too since Rust maintains backwards " +"compatibility." +msgstr "" + +#: src/cargo/running-locally.md +msgid "" +"With this in place, follow these steps to build a Rust binary from one of " +"the examples in this training:" +msgstr "" + +#: src/cargo/running-locally.md +msgid "Click the \"Copy to clipboard\" button on the example you want to copy." +msgstr "" + +#: src/cargo/running-locally.md +msgid "" +"Use `cargo new exercise` to create a new `exercise/` directory for your code:" +msgstr "" + +#: src/cargo/running-locally.md +msgid "" +"Navigate into `exercise/` and use `cargo run` to build and run your binary:" +msgstr "" + +#: src/cargo/running-locally.md +msgid "" +"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" +msgstr "" + +#: src/cargo/running-locally.md +msgid "Use `cargo run` to build and run your updated binary:" +msgstr "" + +#: src/cargo/running-locally.md +msgid "" +"Use `cargo check` to quickly check your project for errors, use `cargo " +"build` to compile it without running it. You will find the output in `target/" +"debug/` for a normal debug build. Use `cargo build --release` to produce an " +"optimized release build in `target/release/`." +msgstr "" + +#: src/cargo/running-locally.md +msgid "" +"You can add dependencies for your project by editing `Cargo.toml`. When you " +"run `cargo` commands, it will automatically download and compile missing " +"dependencies for you." +msgstr "" + +#: src/cargo/running-locally.md +msgid "" +"Try to encourage the class participants to install Cargo and use a local " +"editor. It will make their life easier since they will have a normal " +"development environment." +msgstr "" + +#: src/welcome-day-1.md +msgid "Welcome to Day 1" +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"This is the first day of Rust Fundamentals. We will cover a broad range of " +"topics today:" +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"Basic Rust syntax: variables, scalar and compound types, enums, structs, " +"references, functions, and methods." +msgstr "" + +#: src/welcome-day-1.md +msgid "Types and type inference." +msgstr "" + +#: src/welcome-day-1.md +msgid "Control flow constructs: loops, conditionals, and so on." +msgstr "" + +#: src/welcome-day-1.md +msgid "User-defined types: structs and enums." +msgstr "" + +#: src/welcome-day-1.md src/welcome-day-2.md src/welcome-day-3.md +#: src/welcome-day-4.md src/concurrency/welcome.md +#: src/concurrency/welcome-async.md src/idiomatic/welcome.md +msgid "Schedule" +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"Including 10 minute breaks, this session should take about 2 hours and 10 " +"minutes. It contains:" +msgstr "" + +#: src/welcome-day-1.md +msgid "Please remind the students that:" +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"They should ask questions when they get them, don't save them to the end." +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"The class is meant to be interactive and discussions are very much " +"encouraged!" +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"As an instructor, you should try to keep the discussions relevant, i.e., " +"keep the discussions related to how Rust does things vs. some other " +"language. It can be hard to find the right balance, but err on the side of " +"allowing discussions since they engage people much more than one-way " +"communication." +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"The questions will likely mean that we talk about things ahead of the slides." +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"This is perfectly okay! Repetition is an important part of learning. " +"Remember that the slides are just a support and you are free to skip them as " +"you like." +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"The idea for the first day is to show the \"basic\" things in Rust that " +"should have immediate parallels in other languages. The more advanced parts " +"of Rust come on the subsequent days." +msgstr "" + +#: src/welcome-day-1.md +msgid "" +"If you're teaching this in a classroom, this is a good place to go over the " +"schedule. Note that there is an exercise at the end of each segment, " +"followed by a break. Plan to cover the exercise solution after the break. " +"The times listed here are a suggestion in order to keep the course on " +"schedule. Feel free to be flexible and adjust as necessary!" +msgstr "" + +#: src/hello-world.md src/concurrency/send-sync.md +msgid "This segment should take about 15 minutes. It contains:" +msgstr "" + +#: src/hello-world.md src/types-and-values.md src/control-flow-basics.md +#: src/tuples-and-arrays.md src/references.md src/user-defined-types.md +#: src/pattern-matching.md src/methods-and-traits.md src/generics.md +#: src/closures.md src/std-types.md src/std-traits.md src/memory-management.md +#: src/smart-pointers.md src/borrowing.md src/lifetimes.md src/iterators.md +#: src/modules.md src/testing.md src/error-handling.md src/unsafe-rust.md +#: src/concurrency/threads.md src/concurrency/channels.md +#: src/concurrency/send-sync.md src/concurrency/shared-state.md +#: src/concurrency/sync-exercises.md src/concurrency/async.md +#: src/concurrency/async-control-flow.md src/concurrency/async-pitfalls.md +#: src/concurrency/async-exercises.md src/idiomatic/foundations-api-design.md +#: src/idiomatic/leveraging-the-type-system.md +#: src/unsafe-deep-dive/introduction.md src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "Slide" +msgstr "" + +#: src/hello-world.md src/references.md src/user-defined-types.md +#: src/pattern-matching.md src/methods-and-traits.md src/generics.md +#: src/closures.md src/std-types.md src/memory-management.md +#: src/smart-pointers.md src/borrowing.md src/modules.md src/unsafe-rust.md +#: src/concurrency/channels.md src/concurrency/send-sync.md +#: src/concurrency/shared-state.md src/concurrency/async.md +#: src/concurrency/async-control-flow.md src/concurrency/async-pitfalls.md +#: src/unsafe-deep-dive/introduction.md +msgid "10 minutes" +msgstr "" + +#: src/hello-world.md src/control-flow-basics.md src/user-defined-types.md +#: src/memory-management.md src/concurrency/channels.md +#: src/concurrency/send-sync.md src/idiomatic/foundations-api-design.md +msgid "2 minutes" +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "" +"Rust is a new programming language that had its [1.0 release in 2015]" +"(https://blog.rust-lang.org/2015/05/15/Rust-1.0.html):" +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "Rust is a statically compiled language in a similar role as C++" +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "`rustc` uses LLVM as its backend." +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "" +"Rust supports many [platforms and architectures](https://doc.rust-lang.org/" +"nightly/rustc/platform-support.html):" +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "x86, ARM, WebAssembly, ..." +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "Linux, Mac, Windows, ..." +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "Rust is used for a wide range of devices:" +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "firmware and boot loaders," +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "smart displays," +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "mobile phones," +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "desktops," +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "servers." +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "Rust fits in the same area as C++:" +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "High flexibility." +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "High level of control." +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "" +"Can be scaled down to very constrained devices such as microcontrollers." +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "Has no runtime or garbage collection." +msgstr "" + +#: src/hello-world/what-is-rust.md +msgid "Focuses on reliability and safety without sacrificing performance." +msgstr "" + +#: src/hello-world/benefits.md +msgid "Some unique selling points of Rust:" +msgstr "" + +#: src/hello-world/benefits.md +msgid "" +"_Compile time memory safety_ - whole classes of memory bugs are prevented at " +"compile time" +msgstr "" + +#: src/hello-world/benefits.md +msgid "No uninitialized variables." +msgstr "" + +#: src/hello-world/benefits.md +msgid "No double-frees." +msgstr "" + +#: src/hello-world/benefits.md +msgid "No use-after-free." +msgstr "" + +#: src/hello-world/benefits.md +msgid "No `NULL` pointers." +msgstr "" + +#: src/hello-world/benefits.md +msgid "No forgotten locked mutexes." +msgstr "" + +#: src/hello-world/benefits.md +msgid "No data races between threads." +msgstr "" + +#: src/hello-world/benefits.md +msgid "No iterator invalidation." +msgstr "" + +#: src/hello-world/benefits.md +msgid "" +"_No undefined runtime behavior_ - what a Rust statement does is never left " +"unspecified" +msgstr "" + +#: src/hello-world/benefits.md +msgid "Array access is bounds checked." +msgstr "" + +#: src/hello-world/benefits.md +msgid "Integer overflow is defined (panic or wrap-around)." +msgstr "" + +#: src/hello-world/benefits.md +msgid "" +"_Modern language features_ - as expressive and ergonomic as higher-level " +"languages" +msgstr "" + +#: src/hello-world/benefits.md +msgid "Enums and pattern matching." msgstr "" -"_āφāϧ⧁āύāĻŋāĻ• āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāĻŋāĻ‚ āĻ­āĻžāώāĻžāϰ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ_- āωāĻšā§āϚ-āĻ¸ā§āϤāϰ⧇āϰ āĻ­āĻžāώāĻžāϰ āĻŽāϤ⧋āχ āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāĻĒā§‚āĻ°ā§āĻŖ āĻāĻŦāĻ‚ " -"āĻāϰāĻ—āύ⧋āĻŽāĻŋāĻ•" - -#: src/hello-world/benefits.md -msgid "Enums and pattern matching." -msgstr "āχāύāĻžāĻŽ āĻāĻŦāĻ‚ āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āĻŽā§āϝāĻžāϚāĻŋāĻ‚āĨ¤" #: src/hello-world/benefits.md msgid "Generics." -msgstr "āĻœā§‡āύ⧇āϰāĻŋāĻ•ā§āϏāĨ¤" +msgstr "" + +#: src/hello-world/benefits.md +msgid "No overhead FFI." +msgstr "" + +#: src/hello-world/benefits.md +msgid "Zero-cost abstractions." +msgstr "" + +#: src/hello-world/benefits.md +msgid "Great compiler errors." +msgstr "" + +#: src/hello-world/benefits.md +msgid "Built-in dependency manager." +msgstr "" + +#: src/hello-world/benefits.md +msgid "Built-in support for testing." +msgstr "" + +#: src/hello-world/benefits.md +msgid "Excellent Language Server Protocol support." +msgstr "" + +#: src/hello-world/benefits.md +msgid "" +"Do not spend much time here. All of these points will be covered in more " +"depth later." +msgstr "" + +#: src/hello-world/benefits.md +msgid "" +"Make sure to ask the class which languages they have experience with. " +"Depending on the answer you can highlight different features of Rust:" +msgstr "" + +#: src/hello-world/benefits.md +msgid "" +"Experience with C or C++: Rust eliminates a whole class of _runtime errors_ " +"via the borrow checker. You get performance like in C and C++, but you don't " +"have the memory unsafety issues. In addition, you get a modern language with " +"constructs like pattern matching and built-in dependency management." +msgstr "" + +#: src/hello-world/benefits.md +msgid "" +"Experience with Java, Go, Python, JavaScript...: You get the same memory " +"safety as in those languages, plus a similar high-level language feeling. In " +"addition you get fast and predictable performance like C and C++ (no garbage " +"collector) as well as access to low-level hardware (should you need it)." +msgstr "" + +#: src/hello-world/playground.md +msgid "" +"The [Rust Playground](https://play.rust-lang.org/) provides an easy way to " +"run short Rust programs, and is the basis for the examples and exercises in " +"this course. Try running the \"hello-world\" program it starts with. It " +"comes with a few handy features:" +msgstr "" + +#: src/hello-world/playground.md +msgid "" +"Under \"Tools\", use the `rustfmt` option to format your code in the " +"\"standard\" way." +msgstr "" + +#: src/hello-world/playground.md +msgid "" +"Rust has two main \"profiles\" for generating code: Debug (extra runtime " +"checks, less optimization) and Release (fewer runtime checks, lots of " +"optimization). These are accessible under \"Debug\" at the top." +msgstr "" + +#: src/hello-world/playground.md +msgid "" +"If you're interested, use \"ASM\" under \"...\" to see the generated " +"assembly code." +msgstr "" + +#: src/hello-world/playground.md +msgid "" +"As students head into the break, encourage them to open up the playground " +"and experiment a little. Encourage them to keep the tab open and try things " +"out during the rest of the course. This is particularly helpful for advanced " +"students who want to know more about Rust's optimizations or generated " +"assembly." +msgstr "" + +#: src/types-and-values.md src/concurrency/async.md +msgid "This segment should take about 40 minutes. It contains:" +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "" +"Let us jump into the simplest possible Rust program, a classic Hello World " +"program:" +msgstr "" + +#: src/types-and-values/hello-world.md src/control-flow-basics/if.md +#: src/control-flow-basics/match.md src/control-flow-basics/loops/for.md +#: src/control-flow-basics/loops/loop.md +#: src/control-flow-basics/break-continue/labels.md +#: src/tuples-and-arrays/arrays.md src/references/strings.md +#: src/references/dangling.md src/user-defined-types/static.md +#: src/pattern-matching/match.md src/methods-and-traits/traits/implementing.md +#: src/methods-and-traits/traits/supertraits.md +#: src/methods-and-traits/traits/associated-types.md +#: src/generics/generic-traits.md src/generics/dyn-trait.md +#: src/smart-pointers/trait-objects.md src/borrowing/examples.md +#: src/lifetimes/lifetime-elision.md src/lifetimes/struct-lifetimes.md +#: src/lifetimes/exercise.md src/lifetimes/solution.md +#: src/iterators/motivation.md src/iterators/helpers.md +#: src/iterators/collect.md src/modules/encapsulation.md +#: src/error-handling/thiserror.md src/error-handling/anyhow.md +#: src/android/aidl/example-service/service-bindings.md +#: src/android/aidl/example-service/service.md +#: src/android/aidl/example-service/server.md +#: src/android/aidl/example-service/client.md +#: src/android/aidl/example-service/changing-definition.md +#: src/android/aidl/example-service/changing-implementation.md +#: src/android/aidl/types/objects.md src/android/aidl/types/parcelables.md +#: src/android/aidl/types/file-descriptor.md src/android/testing.md +#: src/android/testing/googletest.md src/android/testing/mocking.md +#: src/concurrency/threads/plain.md src/concurrency/threads/scoped.md +#: src/concurrency/channels/senders-receivers.md +#: src/concurrency/shared-state/arc.md src/concurrency/shared-state/mutex.md +#: src/concurrency/shared-state/example.md +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/sync-exercises/solutions.md +#: src/concurrency/async/async-await.md src/concurrency/async/futures.md +#: src/concurrency/async/runtimes/tokio.md src/concurrency/async/tasks.md +#: src/concurrency/async-control-flow/channels.md +#: src/concurrency/async-control-flow/join.md +#: src/concurrency/async-control-flow/select.md +#: src/concurrency/async-pitfalls/blocking-executor.md +#: src/concurrency/async-pitfalls/pin.md +#: src/concurrency/async-pitfalls/async-traits.md +#: src/concurrency/async-pitfalls/cancellation.md +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md +msgid "// Copyright 2024 Google LLC\n" +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "\"Hello 🌍!\"" +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "What you see:" +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "Functions are introduced with `fn`." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "The `main` function is the entry point of the program." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "Blocks are delimited by curly braces like in C and C++." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "Statements end with `;`." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "`println` is a macro, indicated by the `!` in the invocation." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "Rust strings are UTF-8 encoded and can contain any Unicode character." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "" +"This slide tries to make the students comfortable with Rust code. They will " +"see a ton of it over the next four days so we start small with something " +"familiar." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "" +"Rust is very much like other languages in the C/C++/Java tradition. It is " +"imperative and it doesn't try to reinvent things unless absolutely necessary." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "Rust is modern with full support for Unicode." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "" +"Rust uses macros for situations where you want to have a variable number of " +"arguments (no function [overloading](../control-flow-basics/functions.md))." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "" +"`println!` is a macro because it needs to handle an arbitrary number of " +"arguments based on the format string, which can't be done with a regular " +"function. Otherwise it can be treated like a regular function." +msgstr "" + +#: src/types-and-values/hello-world.md +msgid "" +"Rust is multi-paradigm. For example, it has powerful [object-oriented " +"programming features](https://doc.rust-lang.org/book/ch17-00-oop.html), and, " +"while it is not a functional language, it includes a range of [functional " +"concepts](https://doc.rust-lang.org/book/ch13-00-functional-features.html)." +msgstr "" + +#: src/types-and-values/variables.md +msgid "" +"Rust provides type safety via static typing. Variable bindings are made with " +"`let`:" +msgstr "" + +#: src/types-and-values/variables.md src/types-and-values/arithmetic.md +#: src/types-and-values/inference.md src/types-and-values/exercise.md +#: src/types-and-values/solution.md +#: src/control-flow-basics/blocks-and-scopes.md +#: src/control-flow-basics/loops.md src/control-flow-basics/break-continue.md +#: src/control-flow-basics/macros.md src/control-flow-basics/exercise.md +#: src/control-flow-basics/solution.md src/tuples-and-arrays/iteration.md +#: src/tuples-and-arrays/destructuring.md src/tuples-and-arrays/exercise.md +#: src/tuples-and-arrays/solution.md src/references/shared.md +#: src/references/exercise.md src/references/solution.md +#: src/user-defined-types/named-structs.md +#: src/user-defined-types/tuple-structs.md src/user-defined-types/enums.md +#: src/user-defined-types/aliases.md src/user-defined-types/exercise.md +#: src/user-defined-types/solution.md src/pattern-matching/exercise.md +#: src/pattern-matching/solution.md src/methods-and-traits/methods.md +#: src/methods-and-traits/traits.md src/methods-and-traits/deriving.md +#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md +#: src/generics/generic-functions.md src/generics/generic-data.md +#: src/generics/exercise.md src/generics/solution.md src/std-types/docs.md +#: src/std-types/option.md src/std-types/result.md src/std-types/string.md +#: src/std-types/vec.md src/std-types/hashmap.md src/std-types/exercise.md +#: src/std-types/solution.md src/std-traits/comparisons.md +#: src/std-traits/operators.md src/std-traits/from-and-into.md +#: src/std-traits/casting.md src/std-traits/read-and-write.md +#: src/std-traits/default.md src/std-traits/exercise.md +#: src/std-traits/solution.md src/memory-management/review.md +#: src/memory-management/move.md src/memory-management/clone.md +#: src/memory-management/drop.md src/memory-management/exercise.md +#: src/memory-management/solution.md src/smart-pointers/box.md +#: src/smart-pointers/rc.md src/smart-pointers/exercise.md +#: src/smart-pointers/solution.md src/borrowing/exercise.md +#: src/borrowing/solution.md src/iterators/iterator.md +#: src/iterators/intoiterator.md src/iterators/exercise.md +#: src/iterators/solution.md src/modules/modules.md src/modules/exercise.md +#: src/modules/solution.md src/testing/other.md src/testing/lints.md +#: src/testing/exercise.md src/testing/solution.md src/error-handling/try.md +#: src/error-handling/try-conversions.md src/error-handling/error.md +#: src/error-handling/exercise.md src/error-handling/solution.md +#: src/unsafe-rust/dereferencing.md src/unsafe-rust/mutable-static.md +#: src/unsafe-rust/unions.md src/unsafe-rust/unsafe-traits.md +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +#: src/android/interoperability/cpp/bridge.md +#: src/android/interoperability/cpp/rust-bridge.md +#: src/android/interoperability/cpp/generated-cpp.md +#: src/android/interoperability/cpp/cpp-bridge.md +#: src/android/interoperability/cpp/shared-types.md +#: src/android/interoperability/cpp/shared-enums.md +#: src/android/interoperability/cpp/rust-result.md +#: src/android/interoperability/cpp/cpp-exception.md +#: src/exercises/chromium/build-rules.md src/chromium/testing.md +#: src/chromium/testing/rust-gtest-interop.md +#: src/chromium/testing/chromium-import-macro.md +#: src/chromium/interoperability-with-cpp/example-bindings.md +#: src/chromium/interoperability-with-cpp/error-handling-qr.md +#: src/chromium/interoperability-with-cpp/error-handling-png.md +#: src/bare-metal/alloc.md src/bare-metal/microcontrollers/mmio.md +#: src/bare-metal/microcontrollers/pacs.md +#: src/bare-metal/microcontrollers/hals.md +#: src/bare-metal/microcontrollers/type-state.md +#: src/exercises/bare-metal/solutions-morning.md +#: src/bare-metal/aps/inline-assembly.md src/bare-metal/aps/mmio.md +#: src/bare-metal/aps/uart.md src/bare-metal/aps/uart/traits.md +#: src/bare-metal/aps/better-uart/bitflags.md +#: src/bare-metal/aps/better-uart/driver.md src/bare-metal/aps/logging.md +#: src/bare-metal/aps/logging/using.md +#: src/bare-metal/useful-crates/aarch64-paging.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "// Copyright 2023 Google LLC\n" +msgstr "" + +#: src/types-and-values/variables.md +msgid "\"x: {x}\"" +msgstr "" + +#: src/types-and-values/variables.md +msgid "" +"// x = 20;\n" +" // println!(\"x: {x}\");\n" +msgstr "" + +#: src/types-and-values/variables.md +msgid "" +"Uncomment the `x = 20` to demonstrate that variables are immutable by " +"default. Add the `mut` keyword to allow changes." +msgstr "" + +#: src/types-and-values/variables.md +msgid "" +"Warnings are enabled for this slide, such as for unused variables or " +"unnecessary `mut`. These are omitted in most slides to avoid distracting " +"warnings. Try removing the mutation but leaving the `mut` keyword in place." +msgstr "" + +#: src/types-and-values/variables.md +msgid "" +"The `i32` here is the type of the variable. This must be known at compile " +"time, but type inference (covered later) allows the programmer to omit it in " +"many cases." +msgstr "" + +#: src/types-and-values/values.md +msgid "" +"Here are some basic built-in types, and the syntax for literal values of " +"each type." +msgstr "" + +#: src/types-and-values/values.md src/unsafe-rust/exercise.md +msgid "Types" +msgstr "" + +#: src/types-and-values/values.md +msgid "Literals" +msgstr "" + +#: src/types-and-values/values.md +msgid "Signed integers" +msgstr "" + +#: src/types-and-values/values.md +msgid "`i8`, `i16`, `i32`, `i64`, `i128`, `isize`" +msgstr "" + +#: src/types-and-values/values.md +msgid "`-10`, `0`, `1_000`, `123_i64`" +msgstr "" + +#: src/types-and-values/values.md +msgid "Unsigned integers" +msgstr "" + +#: src/types-and-values/values.md +msgid "`u8`, `u16`, `u32`, `u64`, `u128`, `usize`" +msgstr "" + +#: src/types-and-values/values.md +msgid "`0`, `123`, `10_u16`" +msgstr "" + +#: src/types-and-values/values.md +msgid "Floating point numbers" +msgstr "" + +#: src/types-and-values/values.md +msgid "`f32`, `f64`" +msgstr "" + +#: src/types-and-values/values.md +msgid "`3.14`, `-10.0e20`, `2_f32`" +msgstr "" + +#: src/types-and-values/values.md +msgid "Unicode scalar values" +msgstr "" + +#: src/types-and-values/values.md src/android/aidl/types/primitives.md +msgid "`char`" +msgstr "" + +#: src/types-and-values/values.md +msgid "`'a'`, `'Îą'`, `'∞'`" +msgstr "" + +#: src/types-and-values/values.md +msgid "Booleans" +msgstr "" + +#: src/types-and-values/values.md src/android/aidl/types/primitives.md +msgid "`bool`" +msgstr "" + +#: src/types-and-values/values.md +msgid "`true`, `false`" +msgstr "" + +#: src/types-and-values/values.md +msgid "The types have widths as follows:" +msgstr "" + +#: src/types-and-values/values.md +msgid "`iN`, `uN`, and `fN` are _N_ bits wide," +msgstr "" + +#: src/types-and-values/values.md +msgid "`isize` and `usize` are the width of a pointer," +msgstr "" + +#: src/types-and-values/values.md +msgid "`char` is 32 bits wide," +msgstr "" + +#: src/types-and-values/values.md +msgid "`bool` is 8 bits wide." +msgstr "" + +#: src/types-and-values/values.md +msgid "There are a few syntaxes that are not shown above:" +msgstr "" + +#: src/types-and-values/values.md +msgid "" +"All underscores in numbers can be left out, they are for legibility only. So " +"`1_000` can be written as `1000` (or `10_00`), and `123_i64` can be written " +"as `123i64`." +msgstr "" + +#: src/types-and-values/arithmetic.md +msgid "\"result: {}\"" +msgstr "" + +#: src/types-and-values/arithmetic.md +msgid "" +"This is the first time we've seen a function other than `main`, but the " +"meaning should be clear: it takes three integers, and returns an integer. " +"Functions will be covered in more detail later." +msgstr "" + +#: src/types-and-values/arithmetic.md +msgid "Arithmetic is very similar to other languages, with similar precedence." +msgstr "" + +#: src/types-and-values/arithmetic.md +msgid "" +"What about integer overflow? In C and C++ overflow of _signed_ integers is " +"actually undefined, and might do unknown things at runtime. In Rust, it's " +"defined." +msgstr "" + +#: src/types-and-values/arithmetic.md +msgid "" +"Change the `i32`'s to `i16` to see an integer overflow, which panics " +"(checked) in a debug build and wraps in a release build. There are other " +"options, such as overflowing, saturating, and carrying. These are accessed " +"with method syntax, e.g., `(a * b).saturating_add(b * c).saturating_add(c * " +"a)`." +msgstr "" + +#: src/types-and-values/arithmetic.md +msgid "" +"In fact, the compiler will detect overflow of constant expressions, which is " +"why the example requires a separate function." +msgstr "" + +#: src/types-and-values/inference.md +msgid "Rust will look at how the variable is _used_ to determine the type:" +msgstr "" + +#: src/types-and-values/inference.md +msgid "" +"This slide demonstrates how the Rust compiler infers types based on " +"constraints given by variable declarations and usages." +msgstr "" + +#: src/types-and-values/inference.md +msgid "" +"It is very important to emphasize that variables declared like this are not " +"of some sort of dynamic \"any type\" that can hold any data. The machine " +"code generated by such declaration is identical to the explicit declaration " +"of a type. The compiler does the job for us and helps us write more concise " +"code." +msgstr "" + +#: src/types-and-values/inference.md +msgid "" +"When nothing constrains the type of an integer literal, Rust defaults to " +"`i32`. This sometimes appears as `{integer}` in error messages. Similarly, " +"floating-point literals default to `f64`." +msgstr "" + +#: src/types-and-values/inference.md +msgid "// ERROR: no implementation for `{float} == {integer}`\n" +msgstr "" + +#: src/types-and-values/exercise.md +msgid "" +"The Fibonacci sequence begins with `[0, 1]`. For `n > 1`, the next number is " +"the sum of the previous two." +msgstr "" + +#: src/types-and-values/exercise.md +msgid "" +"Write a function `fib(n)` that calculates the nth Fibonacci number. When " +"will this function panic?" +msgstr "" + +#: src/types-and-values/exercise.md +msgid "// The base case.\n" +msgstr "" + +#: src/types-and-values/exercise.md src/control-flow-basics/exercise.md +msgid "\"Implement this\"" +msgstr "" + +#: src/types-and-values/exercise.md +msgid "// The recursive case.\n" +msgstr "" + +#: src/types-and-values/exercise.md src/types-and-values/solution.md +msgid "\"fib({n}) = {}\"" +msgstr "" + +#: src/types-and-values/exercise.md +msgid "This exercise is a classic introduction to recursion." +msgstr "" + +#: src/types-and-values/exercise.md +msgid "" +"Encourage students to think about the base cases and the recursive step." +msgstr "" + +#: src/types-and-values/exercise.md +msgid "" +"The question \"When will this function panic?\" is a hint to think about " +"integer overflow. The Fibonacci sequence grows quickly!" +msgstr "" + +#: src/types-and-values/exercise.md +msgid "" +"Students might come up with an iterative solution as well, which is a great " +"opportunity to discuss the trade-offs between recursion and iteration (e.g., " +"performance, stack overflow for deep recursion)." +msgstr "" + +#: src/types-and-values/solution.md +msgid "" +"We use the `return` syntax here to return values from the function. Later in " +"the course, we will see that the last expression in a block is automatically " +"returned, allowing us to omit the `return` keyword for a more concise style." +msgstr "" + +#: src/types-and-values/solution.md +msgid "" +"The `if` condition `n < 2` does not need parentheses, which is standard Rust " +"style." +msgstr "" + +#: src/types-and-values/solution.md +msgid "Panic" +msgstr "" + +#: src/types-and-values/solution.md +msgid "" +"The exercise asks when this function will panic. The Fibonacci sequence " +"grows very rapidly. With `u32`, the calculated values will overflow the 32-" +"bit integer limit (4,294,967,295) when `n` reaches 48." +msgstr "" + +#: src/types-and-values/solution.md +msgid "" +"In Rust, integer arithmetic checks for overflow in _debug mode_ (which is " +"the default when using `cargo run`). If an overflow occurs, the program will " +"panic (crash with an error message). In _release mode_ (`cargo run --" +"release`), overflow checks are disabled by default, and the number will wrap " +"around (modular arithmetic), producing incorrect results." +msgstr "" + +#: src/types-and-values/solution.md +msgid "Walk through the solution step-by-step." +msgstr "" + +#: src/types-and-values/solution.md +msgid "Explain the recursive calls and how they lead to the final result." +msgstr "" + +#: src/types-and-values/solution.md +msgid "" +"Discuss the integer overflow issue. With `u32`, the function will panic for " +"`n` around 47. You can demonstrate this by changing the input to `main`." +msgstr "" + +#: src/types-and-values/solution.md +msgid "" +"Show an iterative solution as an alternative and compare its performance and " +"memory usage with the recursive one. An iterative solution will be much more " +"efficient." +msgstr "" + +#: src/types-and-values/solution.md src/control-flow-basics/match.md +#: src/references/dangling.md src/user-defined-types/named-structs.md +#: src/user-defined-types/enums.md src/user-defined-types/static.md +#: src/pattern-matching/infallible.md +#: src/pattern-matching/destructuring-structs.md +#: src/pattern-matching/let-control-flow/let-else.md src/closures/syntax.md +#: src/memory-management/review.md src/memory-management/move.md +#: src/memory-management/copy-types.md src/borrowing/shared.md +#: src/borrowing/borrowck.md src/borrowing/interior-mutability/refcell.md +#: src/lifetimes/borrow-one.md src/iterators/motivation.md +#: src/iterators/iterator.md src/iterators/helpers.md src/iterators/collect.md +#: src/modules/encapsulation.md src/error-handling/result.md +#: src/error-handling/anyhow.md src/concurrency/async/state-machine.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +#: src/idiomatic/leveraging-the-type-system/raii.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "More to Explore" +msgstr "" + +#: src/types-and-values/solution.md +msgid "" +"For a more advanced discussion, you can introduce memoization or dynamic " +"programming to optimize the recursive Fibonacci calculation, although this " +"is beyond the scope of the current topic." +msgstr "" + +#: src/control-flow-basics.md src/methods-and-traits.md src/modules.md +#: src/testing.md +msgid "This segment should take about 45 minutes. It contains:" +msgstr "" + +#: src/control-flow-basics.md +msgid "if Expressions" +msgstr "" + +#: src/control-flow-basics.md src/pattern-matching.md src/concurrency/async.md +#: src/concurrency/async-control-flow.md +msgid "4 minutes" +msgstr "" + +#: src/control-flow-basics.md +msgid "match Expressions" +msgstr "" + +#: src/control-flow-basics.md +msgid "break and continue" +msgstr "" + +#: src/control-flow-basics.md +msgid "We will now cover the many kinds of flow control found in Rust." +msgstr "" + +#: src/control-flow-basics.md +msgid "" +"Most of this will be very familiar to what you have seen in other " +"programming languages." +msgstr "" + +#: src/control-flow-basics/blocks-and-scopes.md +msgid "" +"A block in Rust contains a sequence of expressions, enclosed by braces `{}`." +msgstr "" + +#: src/control-flow-basics/blocks-and-scopes.md +msgid "" +"The final expression of a block determines the value and type of the whole " +"block." +msgstr "" + +#: src/control-flow-basics/blocks-and-scopes.md +msgid "// dbg!(y);\n" +msgstr "" + +#: src/control-flow-basics/blocks-and-scopes.md +msgid "" +"If the last expression ends with `;`, then the resulting value and type is " +"`()`." +msgstr "" + +#: src/control-flow-basics/blocks-and-scopes.md +msgid "A variable's scope is limited to the enclosing block." +msgstr "" + +#: src/control-flow-basics/blocks-and-scopes.md +msgid "" +"You can explain that dbg! is a Rust macro that prints and returns the value " +"of a given expression for quick and dirty debugging." +msgstr "" + +#: src/control-flow-basics/blocks-and-scopes.md +msgid "" +"You can show how the value of the block changes by changing the last line in " +"the block. For instance, adding/removing a semicolon or using a `return`." +msgstr "" + +#: src/control-flow-basics/blocks-and-scopes.md +msgid "" +"Demonstrate that attempting to access `y` outside of its scope won't compile." +msgstr "" + +#: src/control-flow-basics/blocks-and-scopes.md +msgid "" +"Values are effectively \"deallocated\" when they go out of their scope, even " +"if their data on the stack is still there." +msgstr "" + +#: src/control-flow-basics/if.md +msgid "`if` expressions" +msgstr "" + +#: src/control-flow-basics/if.md +msgid "" +"You use [`if` expressions](https://doc.rust-lang.org/reference/expressions/" +"if-expr.html#if-expressions) exactly like `if` statements in other languages:" +msgstr "" + +#: src/control-flow-basics/if.md +msgid "\"zero!\"" +msgstr "" + +#: src/control-flow-basics/if.md +msgid "\"biggish\"" +msgstr "" + +#: src/control-flow-basics/if.md +msgid "\"huge\"" +msgstr "" + +#: src/control-flow-basics/if.md +msgid "" +"In addition, you can use `if` as an expression. The last expression of each " +"block becomes the value of the `if` expression:" +msgstr "" + +#: src/control-flow-basics/if.md +msgid "\"small\"" +msgstr "" + +#: src/control-flow-basics/if.md +msgid "\"large\"" +msgstr "" + +#: src/control-flow-basics/if.md +msgid "\"number size: {}\"" +msgstr "" + +#: src/control-flow-basics/if.md +msgid "" +"Because `if` is an expression and must have a particular type, both of its " +"branch blocks must have the same type. Show what happens if you add `;` " +"after `\"small\"` in the second example." +msgstr "" + +#: src/control-flow-basics/if.md +msgid "" +"An `if` expression should be used in the same way as the other expressions. " +"For example, when it is used in a `let` statement, the statement must be " +"terminated with a `;` as well. Remove the `;` before `println!` to see the " +"compiler error." +msgstr "" + +#: src/control-flow-basics/match.md +msgid "`match` can be used to check a value against one or more options:" +msgstr "" + +#: src/control-flow-basics/match.md +msgid "\"one\"" +msgstr "" + +#: src/control-flow-basics/match.md +msgid "\"ten\"" +msgstr "" + +#: src/control-flow-basics/match.md +msgid "\"one hundred\"" +msgstr "" + +#: src/control-flow-basics/match.md +msgid "\"something else\"" +msgstr "" + +#: src/control-flow-basics/match.md +msgid "Like `if` expressions, `match` can also return a value;" +msgstr "" + +#: src/control-flow-basics/match.md +msgid "\"The value of {flag} is {val}\"" +msgstr "" + +#: src/control-flow-basics/match.md +msgid "" +"`match` arms are evaluated from top to bottom, and the first one that " +"matches has its corresponding body executed." +msgstr "" + +#: src/control-flow-basics/match.md +msgid "" +"There is no fall-through between cases the way that `switch` works in other " +"languages." +msgstr "" + +#: src/control-flow-basics/match.md +msgid "" +"The body of a `match` arm can be a single expression or a block. Technically " +"this is the same thing, since blocks are also expressions, but students may " +"not fully understand that symmetry at this point." +msgstr "" + +#: src/control-flow-basics/match.md +msgid "" +"`match` expressions need to be exhaustive, meaning they either need to cover " +"all possible values or they need to have a default case such as `_`. " +"Exhaustiveness is easiest to demonstrate with enums, but enums haven't been " +"introduced yet. Instead we demonstrate matching on a `bool`, which is the " +"simplest primitive type." +msgstr "" + +#: src/control-flow-basics/match.md +msgid "" +"This slide introduces `match` without talking about pattern matching, giving " +"students a chance to get familiar with the syntax without front-loading too " +"much information. We'll be talking about pattern matching in more detail " +"tomorrow, so try not to go into too much detail here." +msgstr "" + +#: src/control-flow-basics/match.md +msgid "" +"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`, 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`." +msgstr "" + +#: src/control-flow-basics/match.md +msgid "" +"`match` also supports match guards, which allow you to add an arbitrary " +"logical condition that will get evaluated to determine if the match arm " +"should be taken. However talking about match guards requires explaining " +"about pattern matching, which we're trying to avoid on this slide." +msgstr "" + +#: src/control-flow-basics/loops.md +msgid "There are three looping keywords in Rust: `while`, `loop`, and `for`:" +msgstr "" + +#: src/control-flow-basics/loops.md +msgid "`while`" +msgstr "" + +#: src/control-flow-basics/loops.md +msgid "" +"The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-" +"expr.html#predicate-loops) works much like in other languages, executing the " +"loop body as long as the condition is true." +msgstr "" + +#: src/control-flow-basics/loops/for.md +msgid "" +"The [`for` loop](https://doc.rust-lang.org/std/keyword.for.html) iterates " +"over ranges of values or the items in a collection:" +msgstr "" + +#: src/control-flow-basics/loops/for.md +msgid "" +"Under the hood `for` loops use a concept called \"iterators\" to handle " +"iterating over different kinds of ranges/collections. Iterators will be " +"discussed in more detail later." +msgstr "" + +#: src/control-flow-basics/loops/for.md +msgid "" +"Note that the first `for` loop only iterates to `4`. Show the `1..=5` syntax " +"for an inclusive range." +msgstr "" + +#: src/control-flow-basics/loops/loop.md +msgid "" +"The [`loop` statement](https://doc.rust-lang.org/std/keyword.loop.html) just " +"loops forever, until a `break`." +msgstr "" + +#: src/control-flow-basics/loops/loop.md +msgid "" +"The `loop` statement works like a `while true` loop. Use it for things like " +"servers that will serve connections forever." +msgstr "" + +#: src/control-flow-basics/break-continue.md +msgid "" +"If you want to immediately start the next iteration use [`continue`](https://" +"doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)." +msgstr "" + +#: src/control-flow-basics/break-continue.md +msgid "" +"If you want to exit any kind of loop early, use [`break`](https://doc.rust-" +"lang.org/reference/expressions/loop-expr.html#break-expressions). With " +"`loop`, this can take an optional expression that becomes the value of the " +"`loop` expression." +msgstr "" + +#: src/control-flow-basics/break-continue.md +msgid "" +"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)." +msgstr "" + +#: src/control-flow-basics/break-continue/labels.md +msgid "" +"Both `continue` and `break` can optionally take a label argument that is " +"used to break out of nested loops:" +msgstr "" + +#: src/control-flow-basics/break-continue/labels.md +msgid "Labeled break also works on arbitrary blocks, e.g." +msgstr "" + +#: src/control-flow-basics/break-continue/labels.md +msgid "\"This line gets skipped\"" +msgstr "" + +#: src/control-flow-basics/functions.md +msgid "" +"Declaration parameters are followed by a type (the reverse of some " +"programming languages), then a return type." +msgstr "" + +#: src/control-flow-basics/functions.md +msgid "" +"The last expression in a function body (or any block) becomes the return " +"value. Simply omit the `;` at the end of the expression. The `return` " +"keyword can be used for early return, but the \"bare value\" form is " +"idiomatic at the end of a function (refactor `gcd` to use a `return`)." +msgstr "" + +#: src/control-flow-basics/functions.md +msgid "" +"Some functions have no return value, and return the 'unit type', `()`. The " +"compiler will infer this if the return type is omitted." +msgstr "" + +#: src/control-flow-basics/functions.md +msgid "" +"Overloading is not supported -- each function has a single implementation." +msgstr "" + +#: src/control-flow-basics/functions.md +msgid "" +"Always takes a fixed number of parameters. Default arguments are not " +"supported. Macros can be used to support variadic functions." +msgstr "" + +#: src/control-flow-basics/functions.md +msgid "" +"Always takes a single set of parameter types. These types can be generic, " +"which will be covered later." +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"Macros are expanded into Rust code during compilation, and can take a " +"variable number of arguments. They are distinguished by a `!` at the end. " +"The Rust standard library includes an assortment of useful macros." +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"`println!(format, ..)` prints a line to standard output, applying formatting " +"described in [`std::fmt`](https://doc.rust-lang.org/std/fmt/index.html)." +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"`format!(format, ..)` works just like `println!` but returns the result as a " +"string." +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "`dbg!(expression)` logs the value of the expression and returns it." +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"`todo!()` marks a bit of code as not-yet-implemented. If executed, it will " +"panic." +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "\"{n}! = {}\"" +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"The takeaway from this section is that these common conveniences exist, and " +"how to use them. Why they are defined as macros, and what they expand to, is " +"not especially critical." +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"The course does not cover defining macros, but a later section will describe " +"use of derive macros." +msgstr "" + +#: src/control-flow-basics/macros.md src/pattern-matching/match.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "More To Explore" +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"There are a number of other useful macros provided by the standard library. " +"Some other examples you can share with students if they want to know more:" +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"[`assert!`](https://doc.rust-lang.org/stable/std/macro.assert.html) and " +"related macros can be used to add assertions to your code. These are used " +"heavily in writing tests." +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"[`unreachable!`](https://doc.rust-lang.org/stable/std/macro.unreachable." +"html) is used to mark a branch of control flow that should never be hit." +msgstr "" + +#: src/control-flow-basics/macros.md +msgid "" +"[`eprintln!`](https://doc.rust-lang.org/stable/std/macro.eprintln.html) " +"allows you to print to stderr." +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "" +"The [Collatz Sequence](https://en.wikipedia.org/wiki/Collatz_conjecture) is " +"defined as follows, for an arbitrary n1 greater than zero:" +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "" +"If _ni_ is 1, then the sequence terminates at _ni_." +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "If _ni_ is even, then _ni+1 = ni / 2_." +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "" +"If _ni_ is odd, then _ni+1 = 3 * ni + 1_." +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "For example, beginning with _n1_ = 3:" +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "3 is odd, so _n2_ = 3 * 3 + 1 = 10;" +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "10 is even, so _n3_ = 10 / 2 = 5;" +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "5 is odd, so _n4_ = 3 * 5 + 1 = 16;" +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "16 is even, so _n5_ = 16 / 2 = 8;" +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "8 is even, so _n6_ = 8 / 2 = 4;" +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "4 is even, so _n7_ = 4 / 2 = 2;" +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "2 is even, so _n8_ = 1; and" +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "the sequence terminates." +msgstr "" + +#: src/control-flow-basics/exercise.md +msgid "" +"Write a function to calculate the length of the Collatz sequence for a given " +"initial `n`." +msgstr "" + +#: src/control-flow-basics/exercise.md src/control-flow-basics/solution.md +msgid "/// Determine the length of the collatz sequence beginning at `n`.\n" +msgstr "" + +#: src/control-flow-basics/exercise.md src/control-flow-basics/solution.md +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +msgid "\"Length: {}\"" +msgstr "" + +#: src/control-flow-basics/exercise.md src/control-flow-basics/solution.md +msgid "// should be 15\n" +msgstr "" + +#: src/control-flow-basics/solution.md +msgid "This solution demonstrates a few key Rust features:" +msgstr "" + +#: src/control-flow-basics/solution.md +msgid "" +"**`mut` arguments:** The `n` argument is declared as `mut n`. This makes the " +"local variable `n` mutable within the function scope. It does _not_ affect " +"the caller's value, as integers are `Copy` types passed by value." +msgstr "" + +#: src/control-flow-basics/solution.md +msgid "" +"**`if` expressions:** Rust's `if` is an expression, meaning it produces a " +"value. We assign the result of the `if`/`else` block directly to `n`. This " +"is more concise than writing `n = ...` inside each branch." +msgstr "" + +#: src/control-flow-basics/solution.md +msgid "" +"**Implicit return:** The function ends with `len` (without a semicolon), " +"which is automatically returned." +msgstr "" + +#: src/control-flow-basics/solution.md +msgid "" +"Note that `n` must be strictly greater than 0 for the Collatz sequence to be " +"valid. The function signature takes `i32`, but the problem description " +"implies positive integers. A more robust implementation might use `u32` or " +"return an `Option` or `Result` to handle invalid inputs (0 or negative " +"numbers), but panic or infinite loops are potential outcomes here if `n <= " +"0`." +msgstr "" + +#: src/control-flow-basics/solution.md +msgid "" +"The overflow is a potential issue if `n` grows too large, similar to the " +"Fibonacci exercise." +msgstr "" + +#: src/welcome-day-1-afternoon.md src/welcome-day-2-afternoon.md +#: src/welcome-day-3-afternoon.md src/welcome-day-4-afternoon.md +msgid "Welcome Back" +msgstr "" + +#: src/welcome-day-1-afternoon.md +msgid "" +"Including 10 minute breaks, this session should take about 2 hours and 45 " +"minutes. It contains:" +msgstr "" + +#: src/tuples-and-arrays.md +msgid "This segment should take about 35 minutes. It contains:" +msgstr "" + +#: src/tuples-and-arrays.md +msgid "" +"We have seen how primitive types work in Rust. Now it's time for you to " +"start building new composite types." +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "" +"Arrays can also be initialized using the shorthand syntax, e.g. `[0; 1024]`. " +"This can be useful when you want to initialize all elements to the same " +"value, or if you have a large array that would be hard to initialize " +"manually." +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "" +"A value of the array type `[T; N]` holds `N` (a compile-time constant) " +"elements of the same type `T`. Note that the length of the array is _part of " +"its type_, which means that `[u8; 3]` and `[u8; 4]` are considered two " +"different types. Slices, which have a size determined at runtime, are " +"covered later." +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "" +"Try accessing an out-of-bounds array element. The compiler is able to " +"determine that the index is unsafe, and will not compile the code:" +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "\"a: {a:?}\"" +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "" +"Array accesses are checked at runtime. Rust optimizes these checks away when " +"possible; meaning if the compiler can prove the access is safe, it removes " +"the runtime check for better performance. They can be avoided using unsafe " +"Rust. The optimization is so good that it's hard to give an example of " +"runtime checks failing. The following code will compile but panic at runtime:" +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "We can use literals to assign values to arrays." +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "" +"Arrays are not heap-allocated. They are regular values with a fixed size " +"known at compile time, meaning they go on the stack. This can be different " +"from what students expect if they come from a garbage-collected language, " +"where arrays may be heap allocated by default." +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "" +"There is no way to remove elements from an array, nor add elements to an " +"array. The length of an array is fixed at compile-time, and so its length " +"cannot change at runtime." +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "Debug Printing" +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "" +"The `println!` macro asks for the debug implementation with the `?` format " +"parameter: `{}` gives the default output, `{:?}` gives the debug output. " +"Types such as integers and strings implement the default output, but arrays " +"only implement the debug output. This means that we must use debug output " +"here." +msgstr "" + +#: src/tuples-and-arrays/arrays.md +msgid "" +"Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be " +"easier to read." +msgstr "" + +#: src/tuples-and-arrays/tuples.md +msgid "Like arrays, tuples have a fixed length." +msgstr "" + +#: src/tuples-and-arrays/tuples.md +msgid "Tuples group together values of different types into a compound type." +msgstr "" + +#: src/tuples-and-arrays/tuples.md +msgid "" +"Fields of a tuple can be accessed by the period and the index of the value, " +"e.g. `t.0`, `t.1`." +msgstr "" + +#: src/tuples-and-arrays/tuples.md +msgid "" +"The empty tuple `()` is referred to as the \"unit type\" and signifies " +"absence of a return value, akin to `void` in other languages." +msgstr "" + +#: src/tuples-and-arrays/tuples.md +msgid "" +"Unlike arrays, tuples cannot be used in a `for` loop. This is because a " +"`for` loop requires all the elements to have the same type, which may not be " +"the case for a tuple." +msgstr "" + +#: src/tuples-and-arrays/tuples.md +msgid "" +"There is no way to add or remove elements from a tuple. The number of " +"elements and their types are fixed at compile time and cannot be changed at " +"runtime." +msgstr "" + +#: src/tuples-and-arrays/iteration.md +msgid "The `for` statement supports iterating over arrays (but not tuples)." +msgstr "" + +#: src/tuples-and-arrays/iteration.md +msgid "" +"This functionality uses the `IntoIterator` trait, but we haven't covered " +"that yet." +msgstr "" + +#: src/tuples-and-arrays/iteration.md +msgid "" +"The `assert_ne!` macro is new here. There are also `assert_eq!` and `assert!" +"` macros. These are always checked, while debug-only variants like " +"`debug_assert!` compile to nothing in release builds." +msgstr "" + +#: src/tuples-and-arrays/destructuring.md +msgid "" +"Rust supports using pattern matching to destructure a larger value like a " +"tuple into its constituent parts:" +msgstr "" + +#: src/tuples-and-arrays/destructuring.md +msgid "\"{tuple:?}: {}\"" +msgstr "" + +#: src/tuples-and-arrays/destructuring.md +msgid "\"ordered\"" +msgstr "" + +#: src/tuples-and-arrays/destructuring.md +msgid "\"unordered\"" +msgstr "" + +#: src/tuples-and-arrays/destructuring.md +msgid "" +"The patterns used here are \"irrefutable\", meaning that the compiler can " +"statically verify that the value on the right of `=` has the same structure " +"as the pattern." +msgstr "" + +#: src/tuples-and-arrays/destructuring.md +msgid "" +"A variable name is an irrefutable pattern that always matches any value, " +"hence why we can also use `let` to declare a single variable." +msgstr "" + +#: src/tuples-and-arrays/destructuring.md +msgid "" +"Rust also supports using patterns in conditionals, allowing for equality " +"comparison and destructuring to happen at the same time. This form of " +"pattern matching will be discussed in more detail later." +msgstr "" + +#: src/tuples-and-arrays/destructuring.md +msgid "" +"Edit the examples above to show the compiler error when the pattern doesn't " +"match the value being matched on." +msgstr "" + +#: src/tuples-and-arrays/exercise.md +msgid "Arrays can contain other arrays:" +msgstr "" + +#: src/tuples-and-arrays/exercise.md +msgid "What is the type of this variable?" +msgstr "" + +#: src/tuples-and-arrays/exercise.md +msgid "" +"Use an array such as the above to write a function `transpose` that " +"transposes a matrix (turns rows into columns):" +msgstr "" + +#: src/tuples-and-arrays/exercise.md +msgid "" +"Copy the code below to and implement the " +"function. This function only operates on 3×3 matrices." +msgstr "" + +#: src/tuples-and-arrays/exercise.md src/tuples-and-arrays/solution.md +msgid "// <-- the comment makes rustfmt add a newline\n" +msgstr "" + +#: src/tuples-and-arrays/exercise.md src/tuples-and-arrays/solution.md +msgid "\"Original:\"" +msgstr "" + +#: src/tuples-and-arrays/exercise.md src/tuples-and-arrays/solution.md +msgid "\"{row:?}\"" +msgstr "" + +#: src/tuples-and-arrays/exercise.md src/tuples-and-arrays/solution.md +msgid "\"\\nTransposed:\"" +msgstr "" + +#: src/tuples-and-arrays/solution.md +msgid "" +"**Array Types:** The type `[[i32; 3]; 3]` represents an array of size 3, " +"where each element is itself an array of 3 `i32`s. This is how multi-" +"dimensional arrays are typically represented in Rust." +msgstr "" + +#: src/tuples-and-arrays/solution.md +msgid "" +"**Initialization:** We initialize `result` with zeros (`[[0; 3]; 3]`) before " +"filling it. Rust requires all variables to be initialized before use; there " +"is no concept of \"uninitialized memory\" in safe Rust." +msgstr "" + +#: src/tuples-and-arrays/solution.md +msgid "" +"**Copy Semantics:** Arrays of `Copy` types (like `i32`) are themselves " +"`Copy`. When we pass `matrix` to the function, it is copied by value. The " +"`result` variable is a new, separate array." +msgstr "" + +#: src/tuples-and-arrays/solution.md +msgid "" +"**Iteration:** We use standard `for` loops with ranges (`0..3`) to iterate " +"over indices. Rust also has powerful iterators, which we will see later, but " +"indexing is straightforward for this matrix transposition." +msgstr "" + +#: src/tuples-and-arrays/solution.md +msgid "" +"Mention that `[i32; 3]` is a distinct type from `[i32; 4]`. Array sizes are " +"part of the type signature." +msgstr "" + +#: src/tuples-and-arrays/solution.md +msgid "" +"Ask students what would happen if they tried to return `matrix` directly " +"after modifying it (if they changed the signature to `mut matrix`). (Answer: " +"It would work, but it would return a modified _copy_, leaving the original " +"in `main` unchanged)." +msgstr "" + +#: src/references.md src/smart-pointers.md src/iterators.md +#: src/error-handling.md src/concurrency/async-pitfalls.md +msgid "This segment should take about 55 minutes. It contains:" +msgstr "" + +#: src/references/shared.md +msgid "" +"A reference provides a way to access another value without taking ownership " +"of the value, and is also called \"borrowing\". Shared references are read-" +"only, and the referenced data cannot change." +msgstr "" + +#: src/references/shared.md src/std-traits/solution.md +msgid "'A'" +msgstr "" + +#: src/references/shared.md +msgid "'B'" +msgstr "" + +#: src/references/shared.md +msgid "" +"A shared reference to a type `T` has type `&T`. A reference value is made " +"with the `&` operator. The `*` operator \"dereferences\" a reference, " +"yielding its value." +msgstr "" + +#: src/references/shared.md +msgid "" +"References can never be null in Rust, so null checking is not necessary." +msgstr "" + +#: src/references/shared.md +msgid "" +"A reference is said to \"borrow\" the value it refers to, and this is a good " +"model for students not familiar with pointers: code can use the reference to " +"access the value, but is still \"owned\" by the original variable. The " +"course will get into more detail on ownership in day 3." +msgstr "" + +#: src/references/shared.md +msgid "" +"References are implemented as pointers, and a key advantage is that they can " +"be much smaller than the thing they point to. Students familiar with C or C+" +"+ will recognize references as pointers. Later parts of the course will " +"cover how Rust prevents the memory-safety bugs that come from using raw " +"pointers." +msgstr "" + +#: src/references/shared.md +msgid "" +"Explicit referencing with `&` is required, except when invoking methods, " +"where Rust performs automatic referencing and dereferencing." +msgstr "" + +#: src/references/shared.md +msgid "" +"Rust will auto-dereference in some cases, in particular when invoking " +"methods (try `r.is_ascii()`). There is no need for an `->` operator like in " +"C++." +msgstr "" + +#: src/references/shared.md +msgid "" +"In this example, `r` is mutable so that it can be reassigned (`r = &b`). " +"Note that this re-binds `r`, so that it refers to something else. This is " +"different from C++, where assignment to a reference changes the referenced " +"value." +msgstr "" + +#: src/references/shared.md +msgid "" +"A shared reference does not allow modifying the value it refers to, even if " +"that value was mutable. Try `*r = 'X'`." +msgstr "" + +#: src/references/shared.md +msgid "" +"Rust is tracking the lifetimes of all references to ensure they live long " +"enough. Dangling references cannot occur in safe Rust." +msgstr "" + +#: src/references/shared.md +msgid "" +"We will talk more about borrowing and preventing dangling references when we " +"get to ownership." +msgstr "" + +#: src/references/exclusive.md +msgid "" +"Exclusive references, also known as mutable references, allow changing the " +"value they refer to. They have type `&mut T`." +msgstr "" + +#: src/references/exclusive.md +msgid "" +"\"Exclusive\" means that only this reference can be used to access the " +"value. No other references (shared or exclusive) can exist at the same time, " +"and the referenced value cannot be accessed while the exclusive reference " +"exists. Try making an `&point.0` or changing `point.0` while `x_coord` is " +"alive." +msgstr "" + +#: src/references/exclusive.md +msgid "" +"Be sure to note the difference between `let mut x_coord: &i32` and `let " +"x_coord: &mut i32`. The first one is a shared reference that can be bound to " +"different values, while the second is an exclusive reference to a mutable " +"value." +msgstr "" + +#: src/references/slices.md +msgid "A slice gives you a view into a larger collection:" +msgstr "" + +#: src/references/slices.md +msgid "Slices borrow data from the sliced type." +msgstr "" + +#: src/references/slices.md +msgid "" +"We create a slice by borrowing `a` and specifying the starting and ending " +"indexes in brackets." +msgstr "" + +#: src/references/slices.md +msgid "" +"If the slice starts at index 0, Rust’s range syntax allows us to drop the " +"starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are " +"identical." +msgstr "" + +#: src/references/slices.md +msgid "" +"The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are " +"identical." +msgstr "" + +#: src/references/slices.md +msgid "" +"To easily create a slice of the full array, we can therefore use `&a[..]`." +msgstr "" + +#: src/references/slices.md +msgid "" +"`s` is a reference to a slice of `i32`s. Notice that the type of `s` " +"(`&[i32]`) no longer mentions the array length. This allows us to perform " +"computation on slices of different sizes." +msgstr "" + +#: src/references/slices.md +msgid "" +"Slices always borrow from another object. In this example, `a` has to remain " +"'alive' (in scope) for at least as long as our slice." +msgstr "" + +#: src/references/slices.md +msgid "You can't \"grow\" a slice once it's created:" +msgstr "" + +#: src/references/slices.md +msgid "" +"You can't append elements of the slice, since it doesn't own the backing " +"buffer." +msgstr "" + +#: src/references/slices.md +msgid "" +"You can't grow a slice to point to a larger section of the backing buffer. A " +"slice does not have information about the length of the underlying buffer " +"and so you can't know how large the slice can be grown." +msgstr "" + +#: src/references/slices.md +msgid "" +"To get a larger slice you have to go back to the original buffer and create " +"a larger slice from there." +msgstr "" + +#: src/references/strings.md +msgid "We can now understand the two string types in Rust:" +msgstr "" + +#: src/references/strings.md +msgid "`&str` is a slice of UTF-8 encoded bytes, similar to `&[u8]`." +msgstr "" + +#: src/references/strings.md +msgid "" +"`String` is an owned buffer of UTF-8 encoded bytes, similar to `Vec`." +msgstr "" + +#: src/references/strings.md src/std-traits/read-and-write.md +msgid "\"World\"" +msgstr "" + +#: src/references/strings.md +msgid "\"s1: {s1}\"" +msgstr "" + +#: src/references/strings.md +msgid "\"Hello \"" +msgstr "" + +#: src/references/strings.md +msgid "\"s2: {s2}\"" +msgstr "" + +#: src/references/strings.md +msgid "\"s3: {s3}\"" +msgstr "" + +#: src/references/strings.md +msgid "" +"`&str` introduces a string slice, which is an immutable reference to UTF-8 " +"encoded string data stored in a block of memory. String literals " +"(`\"Hello\"`), are stored in the program’s binary." +msgstr "" + +#: src/references/strings.md +msgid "" +"Rust's `String` type is a wrapper around a vector of bytes. As with a " +"`Vec`, it is owned." +msgstr "" + +#: src/references/strings.md +msgid "" +"As with many other types `String::from()` creates a string from a string " +"literal; `String::new()` creates a new empty string, to which string data " +"can be added using the `push()` and `push_str()` methods." +msgstr "" + +#: src/references/strings.md +msgid "" +"The `format!()` macro is a convenient way to generate an owned string from " +"dynamic values. It accepts the same format specification as `println!()`." +msgstr "" + +#: src/references/strings.md +msgid "" +"You can borrow `&str` slices from `String` via `&` and optionally range " +"selection. If you select a byte range that is not aligned to character " +"boundaries, the expression will panic. The `chars` iterator iterates over " +"characters and is preferred over trying to get character boundaries right." +msgstr "" + +#: src/references/strings.md +msgid "" +"For C++ programmers: think of `&str` as `std::string_view` from C++, but the " +"one that always points to a valid string in memory. Rust `String` is a rough " +"equivalent of `std::string` from C++ (main difference: it can only contain " +"UTF-8 encoded bytes and will never use a small-string optimization)." +msgstr "" + +#: src/references/strings.md +msgid "Byte strings literals allow you to create a `&[u8]` value directly:" +msgstr "" + +#: src/references/strings.md +msgid "" +"Raw strings allow you to create a `&str` value with escapes disabled: " +"`r\"\\n\" == \"\\\\n\"`. You can embed double-quotes by using an equal " +"amount of `#` on either side of the quotes:" +msgstr "" + +#: src/references/dangling.md +msgid "" +"Rust enforces a number of rules for references that make them always safe to " +"use. One rule is that references can never be `null`, making them safe to " +"use without `null` checks. The other rule we'll look at for now is that " +"references can't _outlive_ the data they point to." +msgstr "" + +#: src/references/dangling.md +msgid "" +"This slide gets students thinking about references as not simply being " +"pointers, since Rust has different rules for references than other languages." +msgstr "" + +#: src/references/dangling.md +msgid "" +"We'll look at the rest of Rust's borrowing rules on day 3 when we talk about " +"Rust's ownership system." +msgstr "" + +#: src/references/dangling.md +msgid "" +"Rust's equivalent of nullability is the `Option` type, which can be used to " +"make any type \"nullable\" (not just references/pointers). We haven't yet " +"introduced enums or pattern matching, though, so try not to go into too much " +"detail about this here." +msgstr "" + +#: src/references/exercise.md +msgid "" +"We will create a few utility functions for 3-dimensional geometry, " +"representing a point as `[f64;3]`. It is up to you to determine the function " +"signatures." +msgstr "" + +#: src/references/exercise.md +msgid "" +"// Calculate the magnitude of a vector by summing the squares of its " +"coordinates\n" +"// and taking the square root. Use the `sqrt()` method to calculate the " +"square\n" +"// root, like `v.sqrt()`.\n" +msgstr "" + +#: src/references/exercise.md +msgid "" +"// Normalize a vector by calculating its magnitude and dividing all of its\n" +"// coordinates by that magnitude.\n" +msgstr "" + +#: src/references/exercise.md +msgid "// Use the following `main` to test your work.\n" +msgstr "" + +#: src/references/exercise.md src/references/solution.md +msgid "\"Magnitude of a unit vector: {}\"" +msgstr "" + +#: src/references/exercise.md src/references/solution.md +msgid "\"Magnitude of {v:?}: {}\"" +msgstr "" + +#: src/references/exercise.md src/references/solution.md +msgid "\"Magnitude of {v:?} after normalization: {}\"" +msgstr "" + +#: src/references/solution.md +msgid "/// Calculate the magnitude of the given vector.\n" +msgstr "" + +#: src/references/solution.md +msgid "" +"/// Change the magnitude of the vector to 1.0 without changing its " +"direction.\n" +msgstr "" + +#: src/references/solution.md +msgid "" +"Note that in `normalize` we were able to do `*item /= mag` to modify each " +"element. This is because we're iterating using a mutable reference to an " +"array, which causes the `for` loop to give mutable references to each " +"element." +msgstr "" + +#: src/references/solution.md +msgid "" +"It is also possible to take slice references here, e.g., `fn " +"magnitude(vector: &[f64]) -> f64`. This makes the function more general, at " +"the cost of a runtime length check." +msgstr "" + +#: src/user-defined-types.md src/std-types.md src/std-traits.md +#: src/memory-management.md +msgid "This segment should take about 1 hour. It contains:" +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "Like C and C++, Rust has support for custom structs:" +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "\"{} is {} years old\"" +msgstr "" + +#: src/user-defined-types/named-structs.md +#: src/android/interoperability/with-c/bindgen.md +msgid "\"Peter\"" +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "\"Avery\"" +msgstr "" + +#: src/user-defined-types/named-structs.md src/user-defined-types/enums.md +#: src/pattern-matching/match.md src/methods-and-traits/methods.md +msgid "Key Points:" +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "Structs work like in C or C++." +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "Like in C++, and unlike in C, no typedef is needed to define a type." +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "Unlike in C++, there is no inheritance between structs." +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "" +"This may be a good time to let people know there are different types of " +"structs." +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "" +"Zero-sized structs (e.g. `struct Foo;`) might be used when implementing a " +"trait on some type but don’t have any data that you want to store in the " +"value itself." +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "" +"The next slide will introduce Tuple structs, used when the field names are " +"not important." +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "" +"If you already have variables with the right names, then you can create the " +"struct using a shorthand." +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "" +"Struct fields do not support default values. Default values are specified by " +"implementing the `Default` trait which we will cover later." +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "You can also demonstrate the struct update syntax here:" +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "\"Jackie\"" +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "" +"It allows us to copy the majority of the fields from the old struct without " +"having to explicitly type it all out. It must always be the last element." +msgstr "" + +#: src/user-defined-types/named-structs.md +msgid "" +"It is mainly used in combination with the `Default` trait. We will talk " +"about struct update syntax in more detail on the slide on the `Default` " +"trait, so we don't need to talk about it here unless students ask about it." +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "If the field names are unimportant, you can use a tuple struct:" +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "\"({}, {})\"" +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "This is often used for single-field wrappers (called newtypes):" +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "\"Ask a rocket scientist at NASA\"" +msgstr "" + +#: src/user-defined-types/tuple-structs.md +#: src/android/interoperability/cpp/cpp-bridge.md +#: src/bare-metal/microcontrollers/type-state.md +#: src/concurrency/async-pitfalls/cancellation.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "// ...\n" +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "" +"Newtypes are a great way to encode additional information about the value in " +"a primitive type, for example:" +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "The number is measured in some units: `Newtons` in the example above." +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "" +"The value passed some validation when it was created, so you no longer have " +"to validate it again at every use: `PhoneNumber(String)` or `OddNumber(u32)`." +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "" +"The newtype pattern is covered extensively in the [\"Idiomatic Rust\" module]" +"(../idiomatic/leveraging-the-type-system/newtype-pattern.md)." +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "" +"Demonstrate how to add a `f64` value to a `Newtons` type by accessing the " +"single field in the newtype." +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "" +"Rust generally avoids implicit conversions, like automatic unwrapping or " +"using booleans as integers." +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "" +"Operator overloading is discussed on Day 2 ([Standard Library Traits](../std-" +"traits.md))." +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "" +"When a tuple struct has zero fields, the `()` can be omitted. The result is " +"a zero-sized type (ZST), of which there is only one value (the name of the " +"type)." +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "" +"This is common for types that implement some behavior but have no data " +"(imagine a `NullReader` that implements some reader behavior by always " +"returning EOF)." +msgstr "" + +#: src/user-defined-types/tuple-structs.md +msgid "" +"The example is a subtle reference to the [Mars Climate Orbiter](https://en." +"wikipedia.org/wiki/Mars_Climate_Orbiter) failure." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"The `enum` keyword allows the creation of a type which has a few different " +"variants:" +msgstr "" + +#: src/user-defined-types/enums.md +msgid "// Simple variant\n" +msgstr "" + +#: src/user-defined-types/enums.md +msgid "// Tuple variant\n" +msgstr "" + +#: src/user-defined-types/enums.md +msgid "// Struct variant\n" +msgstr "" + +#: src/user-defined-types/enums.md +msgid "\"On this turn: {player_move:?}\"" +msgstr "" + +#: src/user-defined-types/enums.md +msgid "Enumerations allow you to collect a set of values under one type." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"`Direction` is a type with variants. There are two values of `Direction`: " +"`Direction::Left` and `Direction::Right`." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"`PlayerMove` is a type with three variants. In addition to the payloads, " +"Rust will store a discriminant so that it knows at runtime which variant is " +"in a `PlayerMove` value." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "This might be a good time to compare structs and enums:" +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"In both, you can have a simple version without fields (unit struct) or one " +"with different types of fields (variant payloads)." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"You could even implement the different variants of an enum with separate " +"structs but then they wouldn’t be the same type as they would if they were " +"all defined in an enum." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "Rust uses minimal space to store the discriminant." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "If necessary, it stores an integer of the smallest required size" +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"If the allowed variant values do not cover all bit patterns, it will use " +"invalid bit patterns to encode the discriminant (the \"niche " +"optimization\"). For example, `Option<&u8>` stores either a pointer to an " +"integer or `NULL` for the `None` variant." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"You can control the discriminant if needed (e.g., for compatibility with C):" +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2 " +"bytes." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"Rust has several optimizations it can employ to make enums take up less " +"space." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"Null pointer optimization: For [some types](https://doc.rust-lang.org/std/" +"option/#representation), Rust guarantees that `size_of::()` equals " +"`size_of::>()`." +msgstr "" + +#: src/user-defined-types/enums.md +msgid "" +"Example code if you want to show how the bitwise representation _may_ look " +"like in practice. It's important to note that the compiler provides no " +"guarantees regarding this representation, therefore this is totally unsafe." +msgstr "" + +#: src/user-defined-types/aliases.md +msgid "" +"A type alias creates a name for another type. The two types can be used " +"interchangeably." +msgstr "" + +#: src/user-defined-types/aliases.md +msgid "// Aliases are more useful with long, complex types:\n" +msgstr "" + +#: src/user-defined-types/aliases.md +msgid "" +"A [newtype](tuple-structs.html) is often a better alternative since it " +"creates a distinct type. Prefer `struct InventoryCount(usize)` to `type " +"InventoryCount = usize`." +msgstr "" + +#: src/user-defined-types/aliases.md +msgid "C programmers will recognize this as similar to a `typedef`." +msgstr "" + +#: src/user-defined-types/const.md +msgid "`const`" +msgstr "" + +#: src/user-defined-types/const.md +msgid "" +"Constants are evaluated at compile time and their values are [inlined]" +"(https://rust-lang.github.io/rfcs/0246-const-vs-static.html) wherever they " +"are used:" +msgstr "" + +#: src/user-defined-types/const.md +msgid "" +"Only functions marked `const` can be called at compile time to generate " +"`const` values. `const` functions can however be called at runtime." +msgstr "" + +#: src/user-defined-types/const.md +msgid "Mention that `const` behaves semantically similar to C++'s `constexpr`" +msgstr "" + +#: src/user-defined-types/static.md +msgid "`static`" +msgstr "" + +#: src/user-defined-types/static.md +msgid "" +"Static variables will live during the whole execution of the program, and " +"therefore will not move:" +msgstr "" + +#: src/user-defined-types/static.md +msgid "\"Welcome to RustOS 3.14\"" +msgstr "" + +#: src/user-defined-types/static.md +msgid "\"{BANNER}\"" +msgstr "" + +#: src/user-defined-types/static.md +msgid "" +"As noted in the [Rust RFC Book](https://rust-lang.github.io/rfcs/0246-const-" +"vs-static.html), these are not inlined upon use and have an actual " +"associated memory location. This is useful for unsafe and embedded code, and " +"the variable lives through the entirety of the program execution. When a " +"globally-scoped value does not have a reason to need object identity, " +"`const` is generally preferred." +msgstr "" + +#: src/user-defined-types/static.md +msgid "`static` is similar to mutable global variables in C++." +msgstr "" + +#: src/user-defined-types/static.md +msgid "" +"`static` provides object identity: an address in memory and state as " +"required by types with interior mutability such as `Mutex`." +msgstr "" + +#: src/user-defined-types/static.md +msgid "" +"Because `static` variables are accessible from any thread, they must be " +"`Sync`. Interior mutability is possible through a [`Mutex`](https://doc.rust-" +"lang.org/std/sync/struct.Mutex.html), atomic or similar." +msgstr "" + +#: src/user-defined-types/static.md +msgid "" +"It is common to use `OnceLock` in a static as a way to support " +"initialization on first use. `OnceCell` is not `Sync` and thus cannot be " +"used in this context." +msgstr "" + +#: src/user-defined-types/static.md +msgid "Thread-local data can be created with the macro `std::thread_local`." +msgstr "" + +#: src/user-defined-types/exercise.md +msgid "" +"We will create a data structure to represent an event in an elevator control " +"system. It is up to you to define the types and functions to construct " +"various events. Use `#[derive(Debug)]` to allow the types to be formatted " +"with `{:?}`." +msgstr "" + +#: src/user-defined-types/exercise.md +msgid "" +"This exercise only requires creating and populating data structures so that " +"`main` runs without errors. The next part of the course will cover getting " +"data out of these structures." +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "" +"/// An event in the elevator system that the controller must react to.\n" +msgstr "" + +#: src/user-defined-types/exercise.md +msgid "// TODO: add required variants\n" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "/// A direction of travel.\n" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "/// The car has arrived on the given floor.\n" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "/// The car doors have opened.\n" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "/// The car doors have closed.\n" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "" +"/// A directional button was pressed in an elevator lobby on the given " +"floor.\n" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "/// A floor button was pressed in the elevator car.\n" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "\"A ground floor passenger has pressed the up button: {:?}\"" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "\"The car has arrived on the ground floor: {:?}\"" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "\"The car door opened: {:?}\"" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "\"A passenger has pressed the 3rd floor button: {:?}\"" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "\"The car door closed: {:?}\"" +msgstr "" + +#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +msgid "\"The car has arrived on the 3rd floor: {:?}\"" +msgstr "" + +#: src/user-defined-types/exercise.md +msgid "" +"If students ask about `#![allow(dead_code)]` at the top of the exercise, " +"it's necessary because the only thing we do with the `Event` type is print " +"it out. Due to a nuance of how the compiler checks for dead code this causes " +"it to think the code is unused. They can ignore it for the purpose of this " +"exercise." +msgstr "" + +#: src/user-defined-types/solution.md +msgid "/// A button was pressed.\n" +msgstr "" + +#: src/user-defined-types/solution.md +msgid "/// The car has arrived at the given floor.\n" +msgstr "" + +#: src/user-defined-types/solution.md +msgid "/// The car's doors have opened.\n" +msgstr "" + +#: src/user-defined-types/solution.md +msgid "/// The car's doors have closed.\n" +msgstr "" + +#: src/user-defined-types/solution.md +msgid "/// A floor is represented as an integer.\n" +msgstr "" + +#: src/user-defined-types/solution.md +msgid "/// A user-accessible button.\n" +msgstr "" + +#: src/user-defined-types/solution.md +msgid "/// A button in the elevator lobby on the given floor.\n" +msgstr "" + +#: src/user-defined-types/solution.md +msgid "/// A floor button within the car.\n" +msgstr "" + +#: src/user-defined-types/solution.md +msgid "" +"**Enums with Data:** Rust `enum` variants can carry data. " +"`CarArrived(Floor)` carries an integer, and `ButtonPressed(Button)` carries " +"a nested `Button` enum. This allows `Event` to represent a rich set of " +"states in a type-safe way." +msgstr "" + +#: src/user-defined-types/solution.md +msgid "" +"**Type Aliases:** `type Floor = i32` gives a semantic name to `i32`. This " +"improves readability, but `Floor` is still just an `i32` to the compiler." +msgstr "" + +#: src/user-defined-types/solution.md +msgid "" +"**`#[derive(Debug)]`:** We use this attribute to automatically generate code " +"to format the enums for printing with `{:?}`. Without this, we would have to " +"manually implement the `fmt::Debug` trait." +msgstr "" + +#: src/user-defined-types/solution.md +msgid "" +"**Nested Enums:** The `Button` enum is nested inside `Event::ButtonPressed`. " +"This hierarchical structure is common in Rust for modeling complex domains." +msgstr "" + +#: src/user-defined-types/solution.md +msgid "" +"Note that `Event::CarDoorOpened` is a \"unit variant\" (it carries no data), " +"while `Event::CarArrived` is a \"tuple variant\"." +msgstr "" + +#: src/user-defined-types/solution.md +msgid "" +"You might discuss why `Button` is a separate enum rather than just having " +"`LobbyCallButtonPressed` and `CarFloorButtonPressed` variants on `Event`. " +"Both are valid, but grouping related concepts (like buttons) can make the " +"code cleaner." +msgstr "" + +#: src/welcome-day-2.md +msgid "Welcome to Day 2" +msgstr "" + +#: src/welcome-day-2.md +msgid "We have covered the foundations of Rust:" +msgstr "" + +#: src/welcome-day-2.md +msgid "**Basic Types:** Integers, booleans, characters, tuples, and arrays." +msgstr "" + +#: src/welcome-day-2.md +msgid "**Control Flow:** `if` expressions, loops, and `match` expressions." +msgstr "" + +#: src/welcome-day-2.md +msgid "**Functions:** How to define and call functions." +msgstr "" + +#: src/welcome-day-2.md +msgid "**User-Defined Types:** Model data with `struct` and `enum`." +msgstr "" + +#: src/welcome-day-2.md +msgid "**References:** Basic borrowing with `&` and `&mut`." +msgstr "" + +#: src/welcome-day-2.md +msgid "You can now construct any type in Rust and implement basic logic!" +msgstr "" + +#: src/welcome-day-2.md src/welcome-day-2-afternoon.md src/welcome-day-4.md +msgid "" +"Including 10 minute breaks, this session should take about 2 hours and 50 " +"minutes. It contains:" +msgstr "" + +#: src/pattern-matching.md src/generics.md +msgid "This segment should take about 50 minutes. It contains:" +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "" +"In day 1 we briefly saw how patterns can be used to _destructure_ compound " +"values. Let's review that and talk about a few other things patterns can " +"express:" +msgstr "" + +#: src/pattern-matching/infallible.md +#: src/pattern-matching/let-control-flow/if-let.md +#: src/pattern-matching/let-control-flow/while-let.md +#: src/pattern-matching/let-control-flow/let-else.md src/closures/syntax.md +#: src/closures/capturing.md src/closures/traits.md src/closures/exercise.md +#: src/closures/solution.md src/borrowing/interior-mutability/cell.md +#: src/borrowing/interior-mutability/refcell.md src/lifetimes/simple-borrows.md +#: src/lifetimes/returning-borrows.md src/lifetimes/multiple-borrows.md +#: src/lifetimes/borrow-both.md src/lifetimes/borrow-one.md +#: src/unsafe-rust/unsafe-functions/rust.md +#: src/unsafe-rust/unsafe-functions/extern-c.md +#: src/unsafe-rust/unsafe-functions/calling.md +#: src/android/interoperability/with-c/rust-library.md +#: src/bare-metal/aps/uart/using.md src/bare-metal/aps/safemmio/driver.md +#: src/bare-metal/aps/safemmio/using.md src/bare-metal/aps/aarch64-rt.md +#: src/concurrency/async/state-machine.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +#: src/idiomatic/foundations-api-design/predictable-api.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/new.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/get.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/push.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/is.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/mut.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md +#: src/idiomatic/leveraging-the-type-system/raii.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +#: src/idiomatic/leveraging-the-type-system/token-types.md +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +#: src/idiomatic/polymorphism.md src/idiomatic/polymorphism/refresher.md +#: src/idiomatic/polymorphism/refresher/traits.md +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +#: src/idiomatic/polymorphism/refresher/deriving-traits.md +#: src/idiomatic/polymorphism/refresher/default-impls.md +#: src/idiomatic/polymorphism/refresher/supertraits.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md +#: src/idiomatic/polymorphism/refresher/conditional-methods.md +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +#: src/idiomatic/polymorphism/refresher/sized.md +#: src/idiomatic/polymorphism/refresher/monomorphization.md +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/composition.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "// Copyright 2025 Google LLC\n" +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "// This does the same thing as above.\n" +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "// Ignore the first element, only bind the second and third.\n" +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "// Ignore everything but the last element.\n" +msgstr "" + +#: src/pattern-matching/infallible.md src/pattern-matching/match.md +#: src/generics/exercise.md src/generics/solution.md src/std-traits/solution.md +msgid "'a'" +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "" +"All of the demonstrated patterns are _irrefutable_, meaning that they will " +"always match the value on the right hand side." +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "" +"Patterns are type-specific, including irrefutable patterns. Try adding or " +"removing an element to the tuple and look at the resulting compiler errors." +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "" +"Variable names are patterns that always match and bind the matched value " +"into a new variable with that name." +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "" +"`_` is a pattern that always matches any value, discarding the matched value." +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "`..` allows you to ignore multiple values at once." +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "" +"You can also demonstrate more advanced usages of `..`, such as ignoring the " +"middle elements of a tuple." +msgstr "" + +#: src/pattern-matching/infallible.md +msgid "All of these patterns work with arrays as well:" +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"The `match` keyword lets you match a value against one or more _patterns_. " +"The patterns can be simple values, similarly to `switch` in C and C++, but " +"they can also be used to express more complex conditions:" +msgstr "" + +#: src/pattern-matching/match.md +msgid "'x'" +msgstr "" + +#: src/pattern-matching/match.md +msgid "'q'" +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"Quitting\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "'s'" +msgstr "" + +#: src/pattern-matching/match.md +msgid "'w'" +msgstr "" + +#: src/pattern-matching/match.md +msgid "'d'" +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"Moving around\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "'0'" +msgstr "" + +#: src/pattern-matching/match.md +msgid "'9'" +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"Number input\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"Lowercase: {key}\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"Something else\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"A variable in the pattern (`key` in this example) will create a binding that " +"can be used within the match arm. We will learn more about this on the next " +"slide." +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"A match guard causes the arm to match only if the condition is true. If the " +"condition is false the match will continue checking later cases." +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"You might point out how some specific characters are being used when in a " +"pattern" +msgstr "" + +#: src/pattern-matching/match.md +msgid "`|` as an `or`" +msgstr "" + +#: src/pattern-matching/match.md +msgid "`..` matches any number of items" +msgstr "" + +#: src/pattern-matching/match.md +msgid "`1..=5` represents an inclusive range" +msgstr "" + +#: src/pattern-matching/match.md +msgid "`_` is a wild card" +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"Match guards as a separate syntax feature are important and necessary when " +"we wish to concisely express more complex ideas than patterns alone would " +"allow." +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"Match guards are different from `if` expressions after the `=>`. An `if` " +"expression is evaluated after the match arm is selected. Failing the `if` " +"condition inside of that block won't result in other arms of the original " +"`match` expression being considered. In the following example, the wildcard " +"pattern `_ =>` is never even attempted." +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"Uppercase\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"Bug: this is never printed\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"The condition defined in the guard applies to every expression in a pattern " +"with an `|`." +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"Note that you can't use an existing variable as the condition in a match " +"arm, as it will instead be interpreted as a variable name pattern, which " +"creates a new variable that will shadow the existing one. For example:" +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"Expected value is 5, actual is {expected}\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"Value was something else\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"Here we're trying to match on the number 123, where we want the first case " +"to check if the value is 5. The naive expectation is that the first case " +"won't match because the value isn't 5, but instead this is interpreted as a " +"variable pattern which always matches, meaning the first branch will always " +"be taken. If a constant is used instead this will then work as expected." +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"Another piece of pattern syntax you can show students is the `@` syntax " +"which binds a part of a pattern to a variable. For example:" +msgstr "" + +#: src/pattern-matching/match.md +msgid "\"outer: {outer:?}, inner: {inner}\"" +msgstr "" + +#: src/pattern-matching/match.md +msgid "" +"In this example `inner` has the value 123 which it pulled from the `Option` " +"via destructuring, `outer` captures the entire `Some(inner)` expression, so " +"it contains the full `Option::Some(123)`. This is rarely used but can be " +"useful in more complex patterns." +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "Structs" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "Like tuples, structs can also be destructured by matching:" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "\"Standing still\"" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "\"{repeat} step x: {x}\"" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "\"Single step y: {y}\"" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "\"Other move\"" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "Change the literal values in `m` to match with the other patterns." +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "" +"Add a new field to `Movement` and make changes to the pattern as needed." +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "Note how `delta: (x, 0)` is a nested pattern." +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "" +"Try `match &m` and check the type of captures. The pattern syntax remains " +"the same, but the captures become shared references. This is [match " +"ergonomics](https://rust-lang.github.io/rfcs/2005-match-ergonomics.html) and " +"is often useful with `match self` when implementing methods on an enum." +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "" +"The same effect occurs with `match &mut m`: the captures become exclusive " +"references." +msgstr "" + +#: src/pattern-matching/destructuring-structs.md +msgid "" +"The distinction between a capture and a constant expression can be hard to " +"spot. Try changing the `10` in the first arm to a variable, and see that it " +"subtly doesn't work. Change it to a `const` and see it working again." +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "Like tuples, enums can also be destructured by matching:" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "" +"Patterns can also be used to bind variables to parts of your values. This is " +"how you inspect the structure of your types. Let us start with a simple " +"`enum` type:" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "\"cannot divide {n} into two equal parts\"" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "\"{n} divided in two is {half}\"" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "\"sorry, an error happened: {msg}\"" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "" +"Here we have used the arms to _destructure_ the `Result` value. In the first " +"arm, `half` is bound to the value inside the `Ok` variant. In the second " +"arm, `msg` is bound to the error message." +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "" +"The `if`/`else` expression is returning an enum that is later unpacked with " +"a `match`." +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "" +"You can try adding a third variant to the enum definition and displaying the " +"errors when running the code. Point out the places where your code is now " +"inexhaustive and how the compiler tries to give you hints." +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "" +"The values in the enum variants can only be accessed after being pattern " +"matched." +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "" +"Demonstrate what happens when the search is inexhaustive. Note the advantage " +"the Rust compiler provides by confirming when all cases are handled." +msgstr "" + +#: src/pattern-matching/destructuring-enums.md +msgid "" +"Demonstrate the syntax for a struct-style variant by adding one to the enum " +"definition and the `match`. Point out how this is syntactically similar to " +"matching on a struct." +msgstr "" + +#: src/pattern-matching/let-control-flow.md +msgid "" +"Rust has a few control flow constructs that differ from other languages. " +"They are used for pattern matching:" +msgstr "" + +#: src/pattern-matching/let-control-flow.md +msgid "`if let` expressions" +msgstr "" + +#: src/pattern-matching/let-control-flow.md +msgid "`while let` expressions" +msgstr "" + +#: src/pattern-matching/let-control-flow.md +msgid "`let else` expressions" +msgstr "" + +#: src/pattern-matching/let-control-flow/if-let.md +msgid "" +"The [`if let` expression](https://doc.rust-lang.org/reference/expressions/if-" +"expr.html#if-let-expressions) lets you execute different code depending on " +"whether a value matches a pattern:" +msgstr "" + +#: src/pattern-matching/let-control-flow/if-let.md +msgid "\"slept for {duration:?}\"" +msgstr "" + +#: src/pattern-matching/let-control-flow/if-let.md +msgid "" +"Unlike `match`, `if let` does not have to cover all branches. This can make " +"it more concise than `match`." +msgstr "" + +#: src/pattern-matching/let-control-flow/if-let.md +msgid "A common usage is handling `Some` values when working with `Option`." +msgstr "" + +#: src/pattern-matching/let-control-flow/if-let.md +msgid "" +"Unlike `match`, `if let` does not support guard clauses for pattern matching." +msgstr "" + +#: src/pattern-matching/let-control-flow/if-let.md +msgid "With an `else` clause, this can be used as an expression." +msgstr "" + +#: src/pattern-matching/let-control-flow/while-let.md +msgid "" +"Like with `if let`, there is a [`while let`](https://doc.rust-lang.org/" +"reference/expressions/loop-expr.html#predicate-pattern-loops) variant that " +"repeatedly tests a value against a pattern:" +msgstr "" + +#: src/pattern-matching/let-control-flow/while-let.md +msgid "\"Comprehensive Rust đŸĻ€\"" +msgstr "" + +#: src/pattern-matching/let-control-flow/while-let.md +msgid "// (There are more efficient ways to reverse a string!)\n" +msgstr "" + +#: src/pattern-matching/let-control-flow/while-let.md +msgid "" +"Here [`String::pop`](https://doc.rust-lang.org/stable/std/string/struct." +"String.html#method.pop) returns `Some(c)` until the string is empty, after " +"which it will return `None`. The `while let` lets us keep iterating through " +"all items." +msgstr "" + +#: src/pattern-matching/let-control-flow/while-let.md +msgid "" +"Point out that the `while let` loop will keep going as long as the value " +"matches the pattern." +msgstr "" + +#: src/pattern-matching/let-control-flow/while-let.md +msgid "" +"You could rewrite the `while let` loop as an infinite loop with an if " +"statement that breaks when there is no value to unwrap for `name.pop()`. The " +"`while let` provides syntactic sugar for the above scenario." +msgstr "" + +#: src/pattern-matching/let-control-flow/while-let.md +msgid "" +"This form cannot be used as an expression, because it may have no value if " +"the condition is false." +msgstr "" + +#: src/pattern-matching/let-control-flow/let-else.md +msgid "`let else` Statements" +msgstr "" + +#: src/pattern-matching/let-control-flow/let-else.md +msgid "" +"For the common case of matching a pattern and returning from the function, " +"use [`let else`](https://doc.rust-lang.org/rust-by-example/flow_control/" +"let_else.html). The \"else\" case must diverge (`return`, `break`, or panic " +"- anything but falling off the end of the block)." +msgstr "" + +#: src/pattern-matching/let-control-flow/let-else.md +msgid "\"got None\"" +msgstr "" + +#: src/pattern-matching/let-control-flow/let-else.md +msgid "\"got empty string\"" +msgstr "" + +#: src/pattern-matching/let-control-flow/let-else.md +msgid "\"not a hex digit\"" +msgstr "" + +#: src/pattern-matching/let-control-flow/let-else.md +msgid "\"result: {:?}\"" +msgstr "" + +#: src/pattern-matching/let-control-flow/let-else.md +#: src/generics/trait-bounds.md src/testing/solution.md src/android/testing.md +#: src/android/testing/googletest.md +msgid "\"foo\"" +msgstr "" + +#: src/pattern-matching/let-control-flow/let-else.md +msgid "" +"This early return-based control flow is common in Rust error handling code, " +"where you try to get a value out of a `Result`, returning an error if the " +"`Result` was `Err`." +msgstr "" + +#: src/pattern-matching/let-control-flow/let-else.md +msgid "" +"If students ask, you can also demonstrate how real error handling code would " +"be written with `?`." +msgstr "" + +#: src/pattern-matching/exercise.md +msgid "Let's write a simple recursive evaluator for arithmetic expressions." +msgstr "" + +#: src/pattern-matching/exercise.md +msgid "" +"An example of a small arithmetic expression could be `10 + 20`, which " +"evaluates to `30`. We can represent the expression as a tree:" +msgstr "" + +#: src/pattern-matching/exercise.md +msgid "" +"A bigger and more complex expression would be `(10 * 9) + ((3 - 4) * 5)`, " +"which evaluates to `85`. We represent this as a much bigger tree:" +msgstr "" + +#: src/pattern-matching/exercise.md +msgid "In code, we will represent the tree with two types:" +msgstr "" + +#: src/pattern-matching/exercise.md src/pattern-matching/solution.md +#: src/error-handling/exercise.md src/error-handling/solution.md +msgid "/// An operation to perform on two subexpressions.\n" +msgstr "" + +#: src/pattern-matching/exercise.md src/pattern-matching/solution.md +#: src/error-handling/exercise.md src/error-handling/solution.md +msgid "/// An expression, in tree form.\n" +msgstr "" + +#: src/pattern-matching/exercise.md src/pattern-matching/solution.md +#: src/error-handling/exercise.md src/error-handling/solution.md +msgid "/// An operation on two subexpressions.\n" +msgstr "" + +#: src/pattern-matching/exercise.md src/pattern-matching/solution.md +#: src/error-handling/exercise.md src/error-handling/solution.md +msgid "/// A literal value\n" +msgstr "" + +#: src/pattern-matching/exercise.md +msgid "" +"The `Box` type here is a smart pointer, and will be covered in detail later " +"in the course. An expression can be \"boxed\" with `Box::new` as seen in the " +"tests. To evaluate a boxed expression, use the deref operator (`*`) to " +"\"unbox\" it: `eval(*boxed_expr)`." +msgstr "" + +#: src/pattern-matching/exercise.md +msgid "" +"Copy and paste the code into the Rust playground, and begin implementing " +"`eval`. The final product should pass the tests. It may be helpful to use " +"`todo!()` and get the tests to pass one-by-one. You can also skip a test " +"temporarily with `#[ignore]`:" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"Rust allows you to associate functions with your new types. You do this with " +"an `impl` block:" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "// No receiver, a static method\n" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "// Exclusive borrowed read-write access to self\n" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "// Shared and read-only borrowed access to self\n" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "\"Recorded {} laps for {}:\"" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "\"Lap {idx}: {lap} sec\"" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "// Exclusive ownership of self (covered later)\n" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "\"Race {} is finished, total lap time: {}\"" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "\"Monaco Grand Prix\"" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "// race.add_lap(42);\n" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"The `self` arguments specify the \"receiver\" - the object the method acts " +"on. There are several common receivers for a method:" +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"`&self`: borrows the object from the caller using a shared and immutable " +"reference. The object can be used again afterwards." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"`&mut self`: borrows the object from the caller using a unique and mutable " +"reference. The object can be used again afterwards." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"`self`: takes ownership of the object and moves it away from the caller. The " +"method becomes the owner of the object. The object will be dropped " +"(deallocated) when the method returns, unless its ownership is explicitly " +"transmitted. Complete ownership does not automatically mean mutability." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "`mut self`: same as above, but the method can mutate the object." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"No receiver: this becomes a static method on the struct. Typically used to " +"create constructors that are called `new` by convention." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "It can be helpful to introduce methods by comparing them to functions." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"Methods are called on an instance of a type (such as a struct or enum), the " +"first parameter represents the instance as `self`." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"Developers may choose to use methods to take advantage of method receiver " +"syntax and to help keep them more organized. By using methods we can keep " +"all the implementation code in one predictable place." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"Note that methods can also be called like associated functions by explicitly " +"passing the receiver in, e.g. `CarRace::add_lap(&mut race, 20)`." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "Point out the use of the keyword `self`, a method receiver." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"Show that it is an abbreviated term for `self: Self` and perhaps show how " +"the struct name could also be used." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"Explain that `Self` is a type alias for the type the `impl` block is in and " +"can be used elsewhere in the block." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"Note how `self` is used like other structs and dot notation can be used to " +"refer to individual fields." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"This might be a good time to demonstrate how the `&self` differs from `self` " +"by trying to run `finish` twice." +msgstr "" + +#: src/methods-and-traits/methods.md +msgid "" +"Beyond variants on `self`, there are also [special wrapper types](https://" +"doc.rust-lang.org/reference/special-types-and-traits.html) allowed to be " +"receiver types, such as `Box`." +msgstr "" + +#: src/methods-and-traits/traits.md +msgid "" +"Rust lets you abstract over types with traits. They're similar to interfaces:" +msgstr "" + +#: src/methods-and-traits/traits.md +msgid "/// Return a sentence from this pet.\n" +msgstr "" + +#: src/methods-and-traits/traits.md +msgid "/// Print a string to the terminal greeting this pet.\n" +msgstr "" + +#: src/methods-and-traits/traits.md +msgid "" +"A trait defines a number of methods that types must have in order to " +"implement the trait." +msgstr "" + +#: src/methods-and-traits/traits.md +msgid "" +"In the \"Generics\" segment, next, we will see how to build functionality " +"that is generic over all types implementing a trait." +msgstr "" + +#: src/methods-and-traits/traits/implementing.md +msgid "\"Oh you're a cutie! What's your name? {}\"" +msgstr "" + +#: src/methods-and-traits/traits/implementing.md src/generics/dyn-trait.md +#: src/smart-pointers/trait-objects.md +msgid "\"Woof, my name is {}!\"" +msgstr "" + +#: src/methods-and-traits/traits/implementing.md src/generics/dyn-trait.md +#: src/smart-pointers/trait-objects.md +msgid "\"Fido\"" +msgstr "" + +#: src/methods-and-traits/traits/implementing.md +msgid "" +"To implement `Trait` for `Type`, you use an `impl Trait for Type { .. }` " +"block." +msgstr "" + +#: src/methods-and-traits/traits/implementing.md +msgid "" +"Unlike Go interfaces, just having matching methods is not enough: a `Cat` " +"type with a `talk()` method would not automatically satisfy `Pet` unless it " +"is in an `impl Pet` block." +msgstr "" + +#: src/methods-and-traits/traits/implementing.md +msgid "" +"Traits may provide default implementations of some methods. Default " +"implementations can rely on all the methods of the trait. In this case, " +"`greet` is provided, and relies on `talk`." +msgstr "" + +#: src/methods-and-traits/traits/implementing.md +msgid "" +"Multiple `impl` blocks are allowed for a given type. This includes both " +"inherent `impl` blocks and trait `impl` blocks. Likewise multiple traits can " +"be implemented for a given type (and often types implement many traits!). " +"`impl` blocks can even be spread across multiple modules/files." +msgstr "" + +#: src/methods-and-traits/traits/supertraits.md +msgid "" +"A trait can require that types implementing it also implement other traits, " +"called _supertraits_. Here, any type implementing `Pet` must implement " +"`Animal`." +msgstr "" + +#: src/methods-and-traits/traits/supertraits.md +msgid "\"Rex\"" +msgstr "" + +#: src/methods-and-traits/traits/supertraits.md +msgid "\"{} has {} legs\"" +msgstr "" + +#: src/methods-and-traits/traits/supertraits.md +msgid "" +"This is sometimes called \"trait inheritance\" but students should not " +"expect this to behave like OO inheritance. It just specifies an additional " +"requirement on implementations of a trait." +msgstr "" + +#: src/methods-and-traits/traits/associated-types.md +msgid "" +"Associated types are placeholder types that are supplied by the trait " +"implementation." +msgstr "" + +#: src/methods-and-traits/traits/associated-types.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +#: src/idiomatic/polymorphism/refresher/monomorphization.md +#: src/unsafe-deep-dive/safety-preconditions/determining.md +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "\"{:?}\"" +msgstr "" + +#: src/methods-and-traits/traits/associated-types.md +msgid "" +"Associated types are sometimes also called \"output types\". The key " +"observation is that the implementer, not the caller, chooses this type." +msgstr "" + +#: src/methods-and-traits/traits/associated-types.md +msgid "" +"Many standard library traits have associated types, including arithmetic " +"operators and `Iterator`." +msgstr "" + +#: src/methods-and-traits/deriving.md +msgid "" +"Supported traits can be automatically implemented for your custom types, as " +"follows:" +msgstr "" + +#: src/methods-and-traits/deriving.md +msgid "// Default trait adds `default` constructor.\n" +msgstr "" + +#: src/methods-and-traits/deriving.md +msgid "// Clone trait adds `clone` method.\n" +msgstr "" + +#: src/methods-and-traits/deriving.md +msgid "\"EldurScrollz\"" +msgstr "" + +#: src/methods-and-traits/deriving.md +msgid "// Debug trait adds support for printing with `{:?}`.\n" +msgstr "" + +#: src/methods-and-traits/deriving.md +msgid "\"{p1:?} vs. {p2:?}\"" +msgstr "" + +#: src/methods-and-traits/deriving.md +msgid "" +"Derivation is implemented with macros, and many crates provide useful derive " +"macros to add useful functionality. For example, `serde` can derive " +"serialization support for a struct using `#[derive(Serialize)]`." +msgstr "" + +#: src/methods-and-traits/deriving.md +msgid "" +"Derivation is usually provided for traits that have a common boilerplate " +"implementation that is correct for most cases. For example, demonstrate how " +"a manual `Clone` impl can be repetitive compared to deriving the trait:" +msgstr "" + +#: src/methods-and-traits/deriving.md +msgid "" +"Not all of the `.clone()`s in the above are necessary in this case, but this " +"demonstrates the generally boilerplate-y pattern that manual impls would " +"follow, which should help make the use of `derive` clear to students." +msgstr "" + +#: src/methods-and-traits/exercise.md +msgid "Exercise: Logger Trait" +msgstr "" + +#: src/methods-and-traits/exercise.md +msgid "" +"Let's design a simple logging utility, using a trait `Logger` with a `log` " +"method. Code that might log its progress can then take an `&impl Logger`. In " +"testing, this might put messages in the test logfile, while in a production " +"build it would send messages to a log server." +msgstr "" + +#: src/methods-and-traits/exercise.md +msgid "" +"However, the `StderrLogger` given below logs all messages, regardless of " +"verbosity. Your task is to write a `VerbosityFilter` type that will ignore " +"messages above a maximum verbosity." +msgstr "" + +#: src/methods-and-traits/exercise.md +msgid "" +"This is a common pattern: a struct wrapping a trait implementation and " +"implementing that same trait, adding behavior in the process. In the " +"\"Generics\" segment, we will see how to make the wrapper generic over the " +"wrapped type." +msgstr "" + +#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md +#: src/generics/generic-data.md src/closures/exercise.md +#: src/closures/solution.md +msgid "/// Log a message at the given verbosity level.\n" +msgstr "" + +#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md +#: src/generics/generic-data.md src/closures/exercise.md +#: src/closures/solution.md +msgid "\"verbosity={verbosity}: {message}\"" +msgstr "" + +#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md +#: src/generics/generic-data.md +msgid "/// Only log messages up to the given verbosity level.\n" +msgstr "" + +#: src/methods-and-traits/exercise.md +msgid "// TODO: Implement the `Logger` trait for `VerbosityFilter`.\n" +msgstr "" + +#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md +#: src/generics/generic-data.md src/closures/exercise.md +#: src/closures/solution.md +msgid "\"FYI\"" +msgstr "" + +#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md +#: src/generics/generic-data.md +msgid "\"Uhoh\"" +msgstr "" + +#: src/generics.md +msgid "impl Trait" +msgstr "" + +#: src/generics.md +msgid "dyn Trait" +msgstr "" + +#: src/generics.md +msgid "Exercise: Generic min" +msgstr "" + +#: src/generics/generic-functions.md +msgid "" +"Rust supports generics, which lets you abstract algorithms or data " +"structures (such as sorting or a binary tree) over the types used or stored." +msgstr "" + +#: src/generics/generic-functions.md +msgid "\"picked a number: {:?}\"" +msgstr "" + +#: src/generics/generic-functions.md +msgid "\"picked a string: {:?}\"" +msgstr "" + +#: src/generics/generic-functions.md +msgid "'L'" +msgstr "" + +#: src/generics/generic-functions.md +msgid "'R'" +msgstr "" + +#: src/generics/generic-functions.md +msgid "" +"It can be helpful to show the monomorphized versions of `pick`, either " +"before talking about the generic `pick` in order to show how generics can " +"reduce code duplication, or after talking about generics to show how " +"monomorphization works." +msgstr "" + +#: src/generics/generic-functions.md +msgid "" +"Rust infers a type for T based on the types of the arguments and return " +"value." +msgstr "" + +#: src/generics/generic-functions.md +msgid "" +"In this example we only use the primitive types `i32` and `char` for `T`, " +"but we can use any type here, including user-defined types:" +msgstr "" + +#: src/generics/generic-functions.md +msgid "" +"This is similar to C++ templates, but Rust partially compiles the generic " +"function immediately, so that function must be valid for all types matching " +"the constraints. For example, try modifying `pick` to return `left + right` " +"if `cond` is false. Even if only the `pick` instantiation with integers is " +"used, Rust still considers it invalid. C++ would let you do this." +msgstr "" + +#: src/generics/generic-functions.md +msgid "" +"Generic code is turned into non-generic code based on the call sites. This " +"is a zero-cost abstraction: you get exactly the same result as if you had " +"hand-coded the data structures without the abstraction." +msgstr "" + +#: src/generics/trait-bounds.md +msgid "" +"When working with generics, you often want to require the types to implement " +"some trait, so that you can call this trait's methods." +msgstr "" + +#: src/generics/trait-bounds.md +msgid "You can do this with `T: Trait`:" +msgstr "" + +#: src/generics/trait-bounds.md +msgid "\"{pair:?}\"" +msgstr "" + +#: src/generics/trait-bounds.md +msgid "Try making a `NotCloneable` and passing it to `duplicate`." +msgstr "" + +#: src/generics/trait-bounds.md +msgid "When multiple traits are necessary, use `+` to join them." +msgstr "" + +#: src/generics/trait-bounds.md +msgid "Show a `where` clause, students will encounter it when reading code." +msgstr "" + +#: src/generics/trait-bounds.md +msgid "It declutters the function signature if you have many parameters." +msgstr "" + +#: src/generics/trait-bounds.md +msgid "It has additional features making it more powerful." +msgstr "" + +#: src/generics/trait-bounds.md +msgid "" +"If someone asks, the extra feature is that the type on the left of \":\" can " +"be arbitrary, like `Option`." +msgstr "" + +#: src/generics/trait-bounds.md +msgid "" +"Note that Rust does not (yet) support specialization. For example, given the " +"original `duplicate`, it is invalid to add a specialized `duplicate(a: u32)`." +msgstr "" + +#: src/generics/generic-data.md +msgid "" +"You can use generics to abstract over the concrete field type. Returning to " +"the exercise for the previous segment:" +msgstr "" + +#: src/generics/generic-data.md +msgid "" +"_Q:_ Why is `L` specified twice in `impl .. VerbosityFilter`? " +"Isn't that redundant?" +msgstr "" + +#: src/generics/generic-data.md +msgid "" +"This is because it is a generic implementation section for generic type. " +"They are independently generic." +msgstr "" + +#: src/generics/generic-data.md +msgid "It means these methods are defined for any `L`." +msgstr "" + +#: src/generics/generic-data.md +msgid "It is possible to write `impl VerbosityFilter { .. }`." +msgstr "" + +#: src/generics/generic-data.md +msgid "" +"`VerbosityFilter` is still generic and you can use `VerbosityFilter`, " +"but methods in this block will only be available for " +"`VerbosityFilter`." +msgstr "" + +#: src/generics/generic-data.md +msgid "" +"Note that we don't put a trait bound on the `VerbosityFilter` type itself. " +"You can put bounds there as well, but generally in Rust we only put the " +"trait bounds on the impl blocks." +msgstr "" + +#: src/generics/generic-traits.md +msgid "" +"Traits can also be generic, just like types and functions. A trait's " +"parameters get concrete types when it is used. For example the [`From`]" +"(https://doc.rust-lang.org/std/convert/trait.From.html) trait is used to " +"define type conversions:" +msgstr "" + +#: src/generics/generic-traits.md +msgid "\"Converted from integer: {from}\"" +msgstr "" + +#: src/generics/generic-traits.md +msgid "\"Converted from bool: {from}\"" +msgstr "" + +#: src/generics/generic-traits.md +msgid "" +"The `From` trait will be covered later in the course, but its [definition in " +"the `std` docs](https://doc.rust-lang.org/std/convert/trait.From.html) is " +"simple, and copied here for reference." +msgstr "" + +#: src/generics/generic-traits.md +msgid "" +"Implementations of the trait do not need to cover all possible type " +"parameters. Here, `Foo::from(\"hello\")` would not compile because there is " +"no `From<&str>` implementation for `Foo`." +msgstr "" + +#: src/generics/generic-traits.md +msgid "" +"Generic traits take types as \"input\", while associated types are a kind of " +"\"output\" type. A trait can have multiple implementations for different " +"input types." +msgstr "" + +#: src/generics/generic-traits.md +msgid "" +"In fact, Rust requires that at most one implementation of a trait match for " +"any type T. Unlike some other languages, Rust has no heuristic for choosing " +"the \"most specific\" match. There is work on adding this support, called " +"[specialization](https://rust-lang.github.io/rfcs/1210-impl-specialization." +"html)." +msgstr "" + +#: src/generics/impl-trait.md +msgid "" +"Similar to trait bounds, an `impl Trait` syntax can be used in function " +"arguments and return values:" +msgstr "" + +#: src/generics/impl-trait.md +msgid "" +"// Syntactic sugar for:\n" +"// fn add_42_millions>(x: T) -> i32 {\n" +msgstr "" + +#: src/generics/impl-trait.md +msgid "" +"`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." +msgstr "" + +#: src/generics/impl-trait.md +msgid "" +"For a parameter, `impl Trait` is like an anonymous generic parameter with a " +"trait bound." +msgstr "" + +#: src/generics/impl-trait.md +msgid "" +"For a return type, it means that the return type is some concrete type that " +"implements the trait, without naming the type. This can be useful when you " +"don't want to expose the concrete type in a public API." +msgstr "" + +#: src/generics/impl-trait.md +msgid "" +"Inference is hard in return position. A function returning `impl Foo` picks " +"the concrete type it returns, without writing it out in the source. A " +"function returning a generic type like `collect() -> B` can return any " +"type satisfying `B`, and the caller may need to choose one, such as with " +"`let x: Vec<_> = foo.collect()` or with the turbofish, `foo.collect::" +">()`." +msgstr "" + +#: src/generics/impl-trait.md +msgid "" +"What is the type of `debuggable`? Try `let debuggable: () = ..` to see what " +"the error message shows." +msgstr "" + +#: src/generics/dyn-trait.md +msgid "" +"In addition to using traits for static dispatch via generics, Rust also " +"supports using them for type-erased, dynamic dispatch via trait objects:" +msgstr "" + +#: src/generics/dyn-trait.md src/smart-pointers/trait-objects.md +msgid "\"Miau!\"" +msgstr "" + +#: src/generics/dyn-trait.md +msgid "// Uses generics and static dispatch.\n" +msgstr "" + +#: src/generics/dyn-trait.md src/smart-pointers/trait-objects.md +msgid "\"Hello, who are you? {}\"" +msgstr "" + +#: src/generics/dyn-trait.md +msgid "// Uses type-erasure and dynamic dispatch.\n" +msgstr "" + +#: src/generics/dyn-trait.md +msgid "" +"Generics, including `impl Trait`, use monomorphization to create a " +"specialized 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 that type's trait implementation to " +"use." +msgstr "" + +#: src/generics/dyn-trait.md +msgid "" +"When using `dyn Trait`, it instead uses dynamic dispatch through a [virtual " +"method table](https://en.wikipedia.org/wiki/Virtual_method_table) (vtable). " +"This means that there's a single version of `fn dynamic` that is used " +"regardless of what type of `Pet` is passed in." +msgstr "" + +#: src/generics/dyn-trait.md +msgid "" +"When using `dyn Trait`, the trait object needs to be behind some kind of " +"indirection. In this case it's a reference, though smart pointer types like " +"`Box` can also be used (this will be demonstrated on day 3)." +msgstr "" + +#: src/generics/dyn-trait.md +msgid "" +"At runtime, a `&dyn Pet` is represented as a \"fat pointer\", i.e. a pair of " +"two pointers: One pointer points to the concrete object that implements " +"`Pet`, and the other points to the vtable for the trait implementation for " +"that type. When calling the `talk` method on `&dyn Pet` the compiler looks " +"up the function pointer for `talk` in the vtable and then invokes the " +"function, passing the pointer to the `Dog` or `Cat` into that function. The " +"compiler doesn't need to know the concrete type of the `Pet` in order to do " +"this." +msgstr "" + +#: src/generics/dyn-trait.md +msgid "" +"A `dyn Trait` is considered to be \"type-erased\", because we no longer have " +"compile-time knowledge of what the concrete type is." +msgstr "" + +#: src/generics/exercise.md +msgid "" +"In this short exercise, you will implement a generic `min` function that " +"determines the minimum of two values, using the [`Ord`](https://doc.rust-" +"lang.org/stable/std/cmp/trait.Ord.html) trait." +msgstr "" + +#: src/generics/exercise.md +msgid "// TODO: implement the `min` function used in the tests.\n" +msgstr "" + +#: src/generics/exercise.md src/generics/solution.md +msgid "'z'" +msgstr "" + +#: src/generics/exercise.md src/generics/solution.md +msgid "'7'" +msgstr "" + +#: src/generics/exercise.md src/generics/solution.md +msgid "'1'" +msgstr "" + +#: src/generics/exercise.md src/generics/solution.md +#: src/std-traits/from-and-into.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "\"hello\"" +msgstr "" + +#: src/generics/exercise.md src/generics/solution.md +msgid "\"goodbye\"" +msgstr "" + +#: src/generics/exercise.md src/generics/solution.md +msgid "\"bat\"" +msgstr "" + +#: src/generics/exercise.md src/generics/solution.md +msgid "\"armadillo\"" +msgstr "" + +#: src/generics/exercise.md +msgid "" +"Show students the [`Ord`](https://doc.rust-lang.org/stable/std/cmp/trait.Ord." +"html) trait and [`Ordering`](https://doc.rust-lang.org/stable/std/cmp/enum." +"Ordering.html) enum." +msgstr "" + +#: src/closures.md src/concurrency/threads.md src/concurrency/shared-state.md +msgid "This segment should take about 30 minutes. It contains:" +msgstr "" + +#: src/closures/syntax.md +msgid "Closures are created with vertical bars: `|..| ..`." +msgstr "" + +#: src/closures/syntax.md +msgid "// Argument and return type can be inferred for lightweight syntax:\n" +msgstr "" + +#: src/closures/syntax.md +msgid "// Or we can specify types and bracket the body to be fully explicit:\n" +msgstr "" + +#: src/closures/syntax.md +msgid "" +"The arguments go between the `|..|`. The body can be surrounded by `{ .. }`, " +"but if it is a single expression these can be omitted." +msgstr "" + +#: src/closures/syntax.md +msgid "" +"Argument types are optional, and are inferred if not given. The return type " +"is also optional, but can only be written if using `{ .. }` around the body." +msgstr "" + +#: src/closures/syntax.md +msgid "" +"The examples can both be written as mere nested functions instead -- they do " +"not capture any variables from their lexical environment. We will see " +"captures next." +msgstr "" + +#: src/closures/syntax.md +msgid "" +"The ability to store functions in variables doesn't just apply to closures, " +"regular functions can be put in variables and then invoked the same way that " +"closures can: [Example in the playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2024&gist=817cbeeefc49f3d0d180a3d6d54c8bda)." +msgstr "" + +#: src/closures/syntax.md +msgid "" +"The linked example also demonstrates that closures that don't capture " +"anything can also coerce to a regular function pointer." +msgstr "" + +#: src/closures/capturing.md +msgid "" +"A closure can capture variables from the environment where it was defined." +msgstr "" + +#: src/closures/capturing.md +msgid "" +"By default, a closure captures values by reference. Here `max_value` is " +"captured by `clamp`, but still available to `main` for printing. Try making " +"`max_value` mutable, changing it, and printing the clamped values again. Why " +"doesn't this work?" +msgstr "" + +#: src/closures/capturing.md +msgid "" +"If a closure mutates values, it will capture them by mutable reference. Try " +"adding `max_value += 1` to `clamp`." +msgstr "" + +#: src/closures/capturing.md +msgid "" +"You can force a closure to move values instead of referencing them with the " +"`move` keyword. This can help with lifetimes, for example if the closure " +"must outlive the captured values (more on lifetimes later)." +msgstr "" + +#: src/closures/capturing.md +msgid "" +"This looks like `move |v| ..`. Try adding this keyword and see if `main` can " +"still access `max_value` after defining `clamp`." +msgstr "" + +#: src/closures/capturing.md +msgid "" +"By default, closures will capture each variable from an outer scope by the " +"least demanding form of access they can (by shared reference if possible, " +"then exclusive reference, then by move). The `move` keyword forces capture " +"by value." +msgstr "" + +#: src/closures/traits.md +msgid "Closure traits" +msgstr "" + +#: src/closures/traits.md +msgid "" +"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:" +msgstr "" + +#: src/closures/traits.md +msgid "" +"The special types `fn(..) -> T` refer to function pointers - either the " +"address of a function, or a closure that captures nothing." +msgstr "" + +#: src/closures/traits.md +msgid "\"Calling {func_name}({input}): {}\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"-itis\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"{x}{suffix}\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"add_suffix\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"senior\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"appendix\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"/\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"accumulate\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"red\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"green\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"blue\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"take_and_reverse\"" +msgstr "" + +#: src/closures/traits.md +msgid "\"reversed: \"" +msgstr "" + +#: src/closures/traits.md +msgid "" +"An `Fn` (e.g. `add_suffix`) neither consumes nor mutates captured values. It " +"can be called needing only a shared reference to the closure, which means " +"the closure can be executed repeatedly and even concurrently." +msgstr "" + +#: src/closures/traits.md +msgid "" +"An `FnMut` (e.g. `accumulate`) might mutate captured values. The closure " +"object is accessed via exclusive reference, so it can be called repeatedly " +"but not concurrently." +msgstr "" + +#: src/closures/traits.md +msgid "" +"If you have an `FnOnce` (e.g. `take_and_reverse`), you may only call it " +"once. Doing so consumes the closure and any values captured by move." +msgstr "" + +#: src/closures/traits.md +msgid "" +"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. " +"I.e. you can use an `FnMut` wherever an `FnOnce` is called for, and you can " +"use an `Fn` wherever an `FnMut` or `FnOnce` is called for." +msgstr "" + +#: src/closures/traits.md +msgid "" +"When you define a function that takes a closure, you should take `FnOnce` if " +"you can (i.e. you call it once), or `FnMut` else, and last `Fn`. This allows " +"the most flexibility for the caller." +msgstr "" + +#: src/closures/traits.md +msgid "" +"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 three closure traits), then " +"`FnMut`, and lastly `FnOnce`." +msgstr "" + +#: src/closures/traits.md +msgid "" +"The compiler also infers `Copy` (e.g. for `add_suffix`) and `Clone` (e.g. " +"`take_and_reverse`), depending on what the closure captures. Function " +"pointers (references to `fn` items) implement `Copy` and `Fn`." +msgstr "" + +#: src/closures/exercise.md +msgid "" +"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." +msgstr "" + +#: src/closures/exercise.md +msgid "// TODO: Define and implement `Filter`.\n" +msgstr "" + +#: src/closures/exercise.md src/closures/solution.md +msgid "\"yikes\"" +msgstr "" + +#: src/closures/exercise.md src/closures/solution.md +msgid "\"yikes, something went wrong\"" +msgstr "" + +#: src/closures/exercise.md src/closures/solution.md +msgid "\"uhoh\"" +msgstr "" + +#: src/closures/solution.md +msgid "/// Only log messages matching a filtering predicate.\n" +msgstr "" + +#: src/closures/solution.md +msgid "" +"**Storing Closures:** To store a closure in a struct, we use a generic type " +"parameter (here `P`). This is because every closure in Rust has a unique, " +"anonymous type generated by the compiler." +msgstr "" + +#: src/closures/solution.md +msgid "" +"**`Fn` Trait Bound:** The bound `P: Fn(u8, &str) -> bool` tells the compiler " +"that `P` can be called as a function with the specified arguments and return " +"type. We use `Fn` (instead of `FnMut` or `FnOnce`) because `log` takes " +"`&self`, so we can only access the predicate immutably." +msgstr "" + +#: src/closures/solution.md +msgid "" +"**Calling fields:** We invoke the closure using `(self.predicate)(...)`. The " +"parentheses around `self.predicate` are necessary to disambiguate between " +"calling a method named `predicate` and calling the field itself." +msgstr "" + +#: src/closures/solution.md +msgid "" +"Discuss why `Fn` is required. If we used `FnMut`, `log` would need to take " +"`&mut self`, which conflicts with the `Logger` trait signature. If we used " +"`FnOnce`, we could only log a single message!" +msgstr "" + +#: src/closures/solution.md +msgid "" +"The `impl` block for `new` also includes the bounds. While technically not " +"strictly required for the struct definition itself (bounds can be placed " +"only on `impl` blocks that use them), putting them on `new` helps type " +"inference." +msgstr "" + +#: src/std-types.md src/std-types/option.md +msgid "Option" +msgstr "" + +#: src/std-types.md src/std-types/result.md src/error-handling.md +msgid "Result" +msgstr "" + +#: src/std-types.md src/std-types/string.md +msgid "String" +msgstr "" + +#: src/std-types.md +msgid "Vec" +msgstr "" + +#: src/std-types.md +msgid "HashMap" +msgstr "" + +#: src/std-types.md +msgid "" +"For each of the slides in this section, spend some time reviewing the " +"documentation pages, highlighting some of the more common methods." +msgstr "" + +#: src/std-types/std.md +msgid "" +"Rust comes with a standard library that helps establish a set of common " +"types used by Rust libraries and programs. This way, two libraries can work " +"together smoothly because they both use the same `String` type." +msgstr "" + +#: src/std-types/std.md +msgid "" +"In fact, Rust contains several layers of the Standard Library: `core`, " +"`alloc` and `std`." +msgstr "" + +#: src/std-types/std.md +msgid "" +"`core` includes the most basic types and functions that don't depend on " +"`libc`, allocator or even the presence of an operating system." +msgstr "" + +#: src/std-types/std.md +msgid "" +"`alloc` includes types that require a global heap allocator, such as `Vec`, " +"`Box` and `Arc`." +msgstr "" + +#: src/std-types/std.md +msgid "" +"Embedded Rust applications typically only use `core`, and sometimes `alloc`." +msgstr "" + +#: src/std-types/docs.md +msgid "Rust comes with extensive documentation. For example:" +msgstr "" + +#: src/std-types/docs.md +msgid "" +"All of the details about [loops](https://doc.rust-lang.org/stable/reference/" +"expressions/loop-expr.html)." +msgstr "" + +#: src/std-types/docs.md +msgid "" +"Primitive types like [`u8`](https://doc.rust-lang.org/stable/std/primitive." +"u8.html)." +msgstr "" + +#: src/std-types/docs.md +msgid "" +"Standard library types like [`Option`](https://doc.rust-lang.org/stable/std/" +"option/enum.Option.html) or [`BinaryHeap`](https://doc.rust-lang.org/stable/" +"std/collections/struct.BinaryHeap.html)." +msgstr "" + +#: src/std-types/docs.md +msgid "Use `rustup doc --std` or to view the documentation." +msgstr "" + +#: src/std-types/docs.md +msgid "In fact, you can document your own code:" +msgstr "" + +#: src/std-types/docs.md +msgid "" +"/// Determine whether the first argument is divisible by the second " +"argument.\n" +"///\n" +"/// If the second argument is zero, the result is false.\n" +msgstr "" + +#: src/std-types/docs.md +msgid "" +"The contents are treated as Markdown. All published Rust library crates are " +"automatically documented at [`docs.rs`](https://docs.rs) using the [rustdoc]" +"(https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It is " +"idiomatic to document all public items in an API using this pattern." +msgstr "" + +#: src/std-types/docs.md +msgid "" +"To document an item from inside the item (such as inside a module), use `//!" +"` or `/*! .. */`, called \"inner doc comments\":" +msgstr "" + +#: src/std-types/docs.md +msgid "" +"//! This module contains functionality relating to divisibility of " +"integers.\n" +msgstr "" + +#: src/std-types/docs.md +msgid "" +"Show students the generated docs for the `rand` crate at ." +msgstr "" + +#: src/std-types/option.md +msgid "" +"We have already seen some use of `Option`. It stores either a value of " +"type `T` or nothing. For example, [`String::find`](https://doc.rust-lang.org/" +"stable/std/string/struct.String.html#method.find) returns an `Option`." +msgstr "" + +#: src/std-types/option.md +msgid "\"LÃļwe 老虎 LÊopard Gepardi\"" +msgstr "" + +#: src/std-types/option.md +msgid "'Ê'" +msgstr "" + +#: src/std-types/option.md +msgid "'Z'" +msgstr "" + +#: src/std-types/option.md +msgid "\"Character not found\"" +msgstr "" + +#: src/std-types/option.md +msgid "`Option` is widely used, not just in the standard library." +msgstr "" + +#: src/std-types/option.md +msgid "" +"`unwrap` will return the value in an `Option`, or panic. `expect` is similar " +"but takes an error message." +msgstr "" + +#: src/std-types/option.md +msgid "" +"You can panic on None, but you can't \"accidentally\" forget to check for " +"None." +msgstr "" + +#: src/std-types/option.md +msgid "" +"It's common to `unwrap`/`expect` all over the place when hacking something " +"together, but production code typically handles `None` in a nicer fashion." +msgstr "" + +#: src/std-types/option.md +msgid "" +"The \"niche optimization\" means that `Option` typically has the same " +"size in memory as `T`, if there is some representation that is not a valid " +"value of T. For example, a reference cannot be NULL, so `Option<&T>` " +"automatically uses NULL to represent the `None` variant, and thus can be " +"stored in the same memory as `&T`." +msgstr "" + +#: src/std-types/result.md +msgid "" +"`Result` is similar to `Option`, but indicates the success or failure of an " +"operation, each with a different enum variant. It is generic: `Result` " +"where `T` is used in the `Ok` variant and `E` appears in the `Err` variant." +msgstr "" + +#: src/std-types/result.md src/error-handling/result.md +msgid "\"diary.txt\"" +msgstr "" + +#: src/std-types/result.md src/error-handling/result.md +msgid "\"Dear diary: {contents} ({bytes} bytes)\"" +msgstr "" + +#: src/std-types/result.md src/error-handling/result.md +msgid "\"Could not read file content\"" +msgstr "" + +#: src/std-types/result.md src/error-handling/result.md +msgid "\"The diary could not be opened: {err}\"" +msgstr "" + +#: src/std-types/result.md +msgid "" +"As with `Option`, the successful value sits inside of `Result`, forcing the " +"developer to explicitly extract it. This encourages error checking. In the " +"case where an error should never happen, `unwrap()` or `expect()` can be " +"called, and this is a signal of the developer intent too." +msgstr "" + +#: src/std-types/result.md +msgid "" +"`Result` documentation is a recommended read. Not during the course, but it " +"is worth mentioning. It contains many convenience methods and functions that " +"help functional-style programming." +msgstr "" + +#: src/std-types/result.md +msgid "" +"`Result` is the standard type to implement error handling as we will see on " +"Day 4." +msgstr "" + +#: src/std-types/string.md +msgid "" +"[`String`](https://doc.rust-lang.org/std/string/struct.String.html) is a " +"growable UTF-8 encoded string:" +msgstr "" + +#: src/std-types/string.md src/std-traits/comparisons.md +#: src/std-traits/read-and-write.md src/memory-management/review.md +#: src/testing/unit-tests.md src/concurrency/threads/scoped.md +msgid "\"Hello\"" +msgstr "" + +#: src/std-types/string.md +msgid "\"s1: len = {}, capacity = {}\"" +msgstr "" + +#: src/std-types/string.md +msgid "'!'" +msgstr "" + +#: src/std-types/string.md +msgid "\"s2: len = {}, capacity = {}\"" +msgstr "" + +#: src/std-types/string.md +msgid "\"🇨🇭\"" +msgstr "" + +#: src/std-types/string.md +msgid "\"s3: len = {}, number of chars = {}\"" +msgstr "" + +#: src/std-types/string.md +msgid "" +"`String` implements [`Deref`](https://doc.rust-lang.org/std/" +"string/struct.String.html#deref-methods-str), which means that you can call " +"all `str` methods on a `String`." +msgstr "" + +#: src/std-types/string.md +msgid "" +"`String::new` returns a new empty string, use `String::with_capacity` when " +"you know how much data you want to push to the string." +msgstr "" + +#: src/std-types/string.md +msgid "" +"`String::len` returns the size of the `String` in bytes (which can be " +"different from its length in characters)." +msgstr "" + +#: src/std-types/string.md +msgid "" +"`String::chars` returns an iterator over the actual characters. Note that a " +"`char` can be different from what a human will consider a \"character\" due " +"to [grapheme clusters](https://docs.rs/unicode-segmentation/latest/" +"unicode_segmentation/struct.Graphemes.html)." +msgstr "" + +#: src/std-types/string.md +msgid "" +"When people refer to strings they could either be talking about `&str` or " +"`String`." +msgstr "" + +#: src/std-types/string.md +msgid "" +"When a type implements `Deref`, the compiler will let you " +"transparently call methods from `T`." +msgstr "" + +#: src/std-types/string.md +msgid "" +"We haven't discussed the `Deref` trait yet, so at this point this mostly " +"explains the structure of the sidebar in the documentation." +msgstr "" + +#: src/std-types/string.md +msgid "" +"`String` implements `Deref` which transparently gives it " +"access to `str`'s methods." +msgstr "" + +#: src/std-types/string.md +msgid "Write and compare `let s3 = s1.deref();` and `let s3 = &*s1;`." +msgstr "" + +#: src/std-types/string.md +msgid "" +"`String` is implemented as a wrapper around a vector of bytes, many of the " +"operations you see supported on vectors are also supported on `String`, but " +"with some extra guarantees." +msgstr "" + +#: src/std-types/string.md +msgid "Compare the different ways to index a `String`:" +msgstr "" + +#: src/std-types/string.md +msgid "" +"To a character by using `s3.chars().nth(i).unwrap()` where `i` is in-bound, " +"out-of-bounds." +msgstr "" + +#: src/std-types/string.md +msgid "" +"To a substring by using `s3[0..4]`, where that slice is on character " +"boundaries or not." +msgstr "" + +#: src/std-types/string.md +msgid "" +"Many types can be converted to a string with the [`to_string`](https://doc." +"rust-lang.org/std/string/trait.ToString.html#tymethod.to_string) method. " +"This trait is automatically implemented for all types that implement " +"`Display`, so anything that can be formatted can also be converted to a " +"string." +msgstr "" + +#: src/std-types/vec.md +msgid "" +"[`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html) is the standard " +"resizable heap-allocated buffer:" +msgstr "" + +#: src/std-types/vec.md +msgid "\"v1: len = {}, capacity = {}\"" +msgstr "" + +#: src/std-types/vec.md +msgid "\"v2: len = {}, capacity = {}\"" +msgstr "" + +#: src/std-types/vec.md +msgid "// Canonical macro to initialize a vector with elements.\n" +msgstr "" + +#: src/std-types/vec.md +msgid "// Retain only the even elements.\n" +msgstr "" + +#: src/std-types/vec.md +msgid "\"{v3:?}\"" +msgstr "" + +#: src/std-types/vec.md +msgid "// Remove consecutive duplicates.\n" +msgstr "" + +#: src/std-types/vec.md +msgid "" +"`Vec` implements [`Deref`](https://doc.rust-lang.org/std/vec/" +"struct.Vec.html#deref-methods-%5BT%5D), which means that you can call slice " +"methods on a `Vec`." +msgstr "" + +#: src/std-types/vec.md +msgid "" +"`Vec` is a type of collection, along with `String` and `HashMap`. The data " +"it contains is stored on the heap. This means the amount of data doesn't " +"need to be known at compile time. It can grow or shrink at runtime." +msgstr "" + +#: src/std-types/vec.md +msgid "" +"Notice how `Vec` is a generic type too, but you don't have to specify `T` " +"explicitly. As always with Rust type inference, the `T` was established " +"during the first `push` call." +msgstr "" + +#: src/std-types/vec.md +msgid "" +"`vec![...]` is a canonical macro to use instead of `Vec::new()` and it " +"supports adding initial elements to the vector." +msgstr "" + +#: src/std-types/vec.md +msgid "" +"To index the vector you use `[` `]`, but they will panic if out of bounds. " +"Alternatively, using `get` will return an `Option`. The `pop` function will " +"remove the last element." +msgstr "" + +#: src/std-types/hashmap.md +msgid "Standard hash map with protection against HashDoS attacks:" +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"Adventures of Huckleberry Finn\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"Grimms' Fairy Tales\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"Pride and Prejudice\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"Les MisÊrables\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"We know about {} books, but not Les MisÊrables.\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"Alice's Adventure in Wonderland\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"{book}: {count} pages\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"{book} is unknown.\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "// Use the .entry() method to insert a value if nothing is found.\n" +msgstr "" + +#: src/std-types/hashmap.md +msgid "" +"`HashMap` is not defined in the prelude and needs to be brought into scope." +msgstr "" + +#: src/std-types/hashmap.md +msgid "" +"Try the following lines of code. The first line will see if a book is in the " +"hashmap and if not return an alternative value. The second line will insert " +"the alternative value in the hashmap if the book is not found." +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"Harry Potter and the Sorcerer's Stone\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "\"The Hunger Games\"" +msgstr "" + +#: src/std-types/hashmap.md +msgid "Unlike `vec!`, there is unfortunately no standard `hashmap!` macro." +msgstr "" + +#: src/std-types/hashmap.md +msgid "" +"Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`](https://" +"doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#impl-" +"From%3C%5B(K,+V);+N%5D%3E-for-HashMap%3CK,+V,+RandomState%3E), which allows " +"us to easily initialize a hash map from a literal array:" +msgstr "" + +#: src/std-types/hashmap.md +msgid "" +"Alternatively HashMap can be built from any `Iterator` that yields key-value " +"tuples." +msgstr "" + +#: src/std-types/hashmap.md +msgid "" +"This type has several \"method-specific\" return types, such as `std::" +"collections::hash_map::Keys`. These types often appear in searches of the " +"Rust docs. Show students the docs for this type, and the helpful link back " +"to the `keys` method." +msgstr "" + +#: src/std-types/exercise.md +msgid "" +"In this exercise you will take a very simple data structure and make it " +"generic. It uses a [`std::collections::HashMap`](https://doc.rust-lang.org/" +"stable/std/collections/struct.HashMap.html) to keep track of what values " +"have been seen and how many times each one has appeared." +msgstr "" + +#: src/std-types/exercise.md +msgid "" +"The initial version of `Counter` is hardcoded to only work for `u32` values. " +"Make the struct and its methods generic over the type of value being " +"tracked, that way `Counter` can track any type of value." +msgstr "" + +#: src/std-types/exercise.md +msgid "" +"If you finish early, try using the [`entry`](https://doc.rust-lang.org/" +"stable/std/collections/struct.HashMap.html#method.entry) method to halve the " +"number of hash lookups required to implement the `count` method." +msgstr "" + +#: src/std-types/exercise.md src/std-types/solution.md +msgid "" +"/// Counter counts the number of times each value of type T has been seen.\n" +msgstr "" + +#: src/std-types/exercise.md src/std-types/solution.md +msgid "/// Create a new Counter.\n" +msgstr "" + +#: src/std-types/exercise.md src/std-types/solution.md +msgid "/// Count an occurrence of the given value.\n" +msgstr "" + +#: src/std-types/exercise.md src/std-types/solution.md +msgid "/// Return the number of times the given value has been seen.\n" +msgstr "" + +#: src/std-types/exercise.md src/std-types/solution.md +msgid "\"saw {} values equal to {}\"" +msgstr "" + +#: src/std-types/exercise.md src/std-types/solution.md +msgid "\"apple\"" +msgstr "" + +#: src/std-types/exercise.md src/std-types/solution.md +msgid "\"orange\"" +msgstr "" + +#: src/std-types/exercise.md src/std-types/solution.md +msgid "\"got {} apples\"" +msgstr "" + +#: src/std-traits.md +msgid "Read and Write" +msgstr "" + +#: src/std-traits.md +msgid "Default, struct update syntax" +msgstr "" + +#: src/std-traits.md +msgid "" +"As with the standard library types, spend time reviewing the documentation " +"for each trait." +msgstr "" + +#: src/std-traits.md +msgid "This section is long. Take a break midway through." +msgstr "" + +#: src/std-traits/comparisons.md +msgid "" +"These traits support comparisons between values. All traits can be derived " +"for types containing fields that implement these traits." +msgstr "" + +#: src/std-traits/comparisons.md +msgid "`PartialEq` and `Eq`" +msgstr "" + +#: src/std-traits/comparisons.md +msgid "" +"`PartialEq` is a partial equivalence relation, with required method `eq` and " +"provided method `ne`. The `==` and `!=` operators will call these methods." +msgstr "" + +#: src/std-traits/comparisons.md +msgid "" +"`Eq` is a full equivalence relation (reflexive, symmetric, and transitive) " +"and implies `PartialEq`. Functions that require full equivalence will use " +"`Eq` as a trait bound." +msgstr "" + +#: src/std-traits/comparisons.md +msgid "`PartialOrd` and `Ord`" +msgstr "" + +#: src/std-traits/comparisons.md +msgid "" +"`PartialOrd` defines a partial ordering, with a `partial_cmp` method. It is " +"used to implement the `<`, `<=`, `>=`, and `>` operators." +msgstr "" + +#: src/std-traits/comparisons.md +msgid "`Ord` is a total ordering, with `cmp` returning `Ordering`." +msgstr "" + +#: src/std-traits/comparisons.md +msgid "" +"`PartialEq` can be implemented between different types, but `Eq` cannot, " +"because it is reflexive:" +msgstr "" + +#: src/std-traits/comparisons.md +msgid "" +"In practice, it's common to derive these traits, but uncommon to implement " +"them." +msgstr "" + +#: src/std-traits/comparisons.md +msgid "" +"When comparing references in Rust, it will compare the value of the things " +"pointed to, it will NOT compare the references themselves. That means that " +"references to two different things can compare as equal if the values " +"pointed to are the same:" +msgstr "" + +#: src/std-traits/operators.md +msgid "" +"Operator overloading is implemented via traits in [`std::ops`](https://doc." +"rust-lang.org/std/ops/index.html):" +msgstr "" + +#: src/std-traits/operators.md +msgid "\"{p1:?} + {p2:?} = {:?}\"" +msgstr "" + +#: src/std-traits/operators.md src/memory-management/drop.md +msgid "Discussion points:" +msgstr "" + +#: src/std-traits/operators.md +msgid "" +"You could implement `Add` for `&Point`. In which situations is that useful?" +msgstr "" + +#: src/std-traits/operators.md +msgid "" +"Answer: `Add:add` consumes `self`. If type `T` for which you are overloading " +"the operator is not `Copy`, you should consider overloading the operator for " +"`&T` as well. This avoids unnecessary cloning on the call site." +msgstr "" + +#: src/std-traits/operators.md +msgid "" +"Why is `Output` an associated type? Could it be made a type parameter of the " +"method?" +msgstr "" + +#: src/std-traits/operators.md +msgid "" +"Short answer: Function type parameters are controlled by the caller, but " +"associated types (like `Output`) are controlled by the implementer of a " +"trait." +msgstr "" + +#: src/std-traits/operators.md +msgid "" +"You could implement `Add` for two different types, e.g. `impl Add<(i32, " +"i32)> for Point` would add a tuple to a `Point`." +msgstr "" + +#: src/std-traits/operators.md +msgid "" +"The `Not` trait (`!` operator) is notable because it does not convert the " +"argument to `bool` like the same operator in C-family languages; instead, " +"for integer types it flips each bit of the number, which, arithmetically, is " +"equivalent to subtracting the argument from `-1`: `!5 == -6`." +msgstr "" + +#: src/std-traits/from-and-into.md +msgid "" +"Types implement [`From`](https://doc.rust-lang.org/std/convert/trait.From." +"html) and [`Into`](https://doc.rust-lang.org/std/convert/trait.Into.html) to " +"facilitate type conversions. Unlike `as`, these traits correspond to " +"lossless, infallible conversions." +msgstr "" + +#: src/std-traits/from-and-into.md +msgid "\"{s}, {addr}, {one}, {bigger}\"" +msgstr "" + +#: src/std-traits/from-and-into.md +msgid "" +"[`Into`](https://doc.rust-lang.org/std/convert/trait.Into.html) is " +"automatically implemented when [`From`](https://doc.rust-lang.org/std/" +"convert/trait.From.html) is implemented:" +msgstr "" + +#: src/std-traits/from-and-into.md +msgid "" +"That's why it is common to only implement `From`, as your type will get " +"`Into` implementation too." +msgstr "" + +#: src/std-traits/from-and-into.md +msgid "" +"When declaring a function argument input type like \"anything that can be " +"converted into a `String`\", the rule is opposite, you should use `Into`. " +"Your function will accept types that implement `From` and those that _only_ " +"implement `Into`." +msgstr "" + +#: src/std-traits/casting.md +msgid "" +"Rust has no _implicit_ type conversions, but does support explicit casts " +"with `as`. These generally follow C semantics where those are defined." +msgstr "" + +#: src/std-traits/casting.md +msgid "\"as u16: {}\"" +msgstr "" + +#: src/std-traits/casting.md +msgid "\"as i16: {}\"" +msgstr "" + +#: src/std-traits/casting.md +msgid "\"as u8: {}\"" +msgstr "" + +#: src/std-traits/casting.md +msgid "" +"The results of `as` are _always_ defined in Rust and consistent across " +"platforms. This might not match your intuition for changing sign or casting " +"to a smaller type -- check the docs, and comment for clarity." +msgstr "" + +#: src/std-traits/casting.md +msgid "" +"Casting with `as` is a relatively sharp tool that is easy to use " +"incorrectly, and can be a source of subtle bugs as future maintenance work " +"changes the types that are used or the ranges of values in types. Casts are " +"best used only when the intent is to indicate unconditional truncation (e.g. " +"selecting the bottom 32 bits of a `u64` with `as u32`, regardless of what " +"was in the high bits)." +msgstr "" + +#: src/std-traits/casting.md +msgid "" +"For infallible casts (e.g. `u32` to `u64`), prefer using `From` or `Into` " +"over `as` to confirm that the cast is in fact infallible. For fallible " +"casts, `TryFrom` and `TryInto` are available when you want to handle casts " +"that fit differently from those that don't." +msgstr "" + +#: src/std-traits/casting.md +msgid "Consider taking a break after this slide." +msgstr "" + +#: src/std-traits/casting.md +msgid "" +"`as` is similar to a C++ static cast. Use of `as` in cases where data might " +"be lost is generally discouraged, or at least deserves an explanatory " +"comment." +msgstr "" + +#: src/std-traits/casting.md +msgid "This is common in casting integers to `usize` for use as an index." +msgstr "" + +#: src/std-traits/read-and-write.md +msgid "" +"Using [`Read`](https://doc.rust-lang.org/std/io/trait.Read.html) and " +"[`BufRead`](https://doc.rust-lang.org/std/io/trait.BufRead.html), you can " +"abstract over `u8` sources:" +msgstr "" + +#: src/std-traits/read-and-write.md +msgid "b\"foo\\nbar\\nbaz\\n\"" +msgstr "" + +#: src/std-traits/read-and-write.md +msgid "\"lines in slice: {}\"" +msgstr "" + +#: src/std-traits/read-and-write.md +msgid "\"lines in file: {}\"" +msgstr "" + +#: src/std-traits/read-and-write.md +msgid "" +"Similarly, [`Write`](https://doc.rust-lang.org/std/io/trait.Write.html) lets " +"you abstract over `u8` sinks:" +msgstr "" + +#: src/std-traits/read-and-write.md +msgid "\"\\n\"" +msgstr "" + +#: src/std-traits/read-and-write.md +msgid "\"Logged: {buffer:?}\"" +msgstr "" + +#: src/std-traits/default.md +msgid "The `Default` Trait" +msgstr "" + +#: src/std-traits/default.md +msgid "" +"The [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) " +"trait produces a default value for a type." +msgstr "" + +#: src/std-traits/default.md +msgid "\"John Smith\"" +msgstr "" + +#: src/std-traits/default.md +msgid "\"Y is set!\"" +msgstr "" + +#: src/std-traits/default.md +msgid "" +"It can be implemented directly or it can be derived via `#[derive(Default)]`." +msgstr "" + +#: src/std-traits/default.md +msgid "" +"A derived implementation will produce a value where all fields are set to " +"their default values." +msgstr "" + +#: src/std-traits/default.md +msgid "This means all types in the struct must implement `Default` too." +msgstr "" + +#: src/std-traits/default.md +msgid "" +"Standard Rust types commonly implement `Default` with reasonable values (e." +"g. `0`, `\"\"`, etc)." +msgstr "" + +#: src/std-traits/default.md +msgid "The partial struct initialization works nicely with default." +msgstr "" + +#: src/std-traits/default.md +msgid "" +"The Rust standard library is aware that types can implement `Default` and " +"provides convenience methods that use it." +msgstr "" + +#: src/std-traits/default.md +msgid "" +"The `..` syntax is called [struct update syntax](https://doc.rust-lang.org/" +"book/ch05-01-defining-structs.html#creating-instances-from-other-instances-" +"with-struct-update-syntax)." +msgstr "" + +#: src/std-traits/exercise.md +msgid "" +"In this example, you will implement the classic [\"ROT13\" cipher](https://" +"en.wikipedia.org/wiki/ROT13). Copy this code to the playground, and " +"implement the missing bits. Only rotate ASCII alphabetic characters, to " +"ensure the result is still valid UTF-8." +msgstr "" + +#: src/std-traits/exercise.md +msgid "// Implement the `Read` trait for `RotDecoder`.\n" +msgstr "" + +#: src/std-traits/exercise.md src/std-traits/solution.md +msgid "\"Gb trg gb gur bgure fvqr!\"" +msgstr "" + +#: src/std-traits/exercise.md src/std-traits/solution.md +msgid "\"To get to the other side!\"" +msgstr "" + +#: src/std-traits/exercise.md +msgid "" +"What happens if you chain two `RotDecoder` instances together, each rotating " +"by 13 characters?" +msgstr "" + +#: src/welcome-day-3.md +msgid "Welcome to Day 3" +msgstr "" + +#: src/welcome-day-3.md +msgid "We have now seen all the core language features:" +msgstr "" + +#: src/welcome-day-3.md +msgid "" +"**Foundations:** Basic types, control flow, functions, and data structures." +msgstr "" + +#: src/welcome-day-3.md +msgid "**Pattern Matching:** Destructuring data effectively." +msgstr "" + +#: src/welcome-day-3.md +msgid "**Polymorphism:** Methods, Traits, and Generics." +msgstr "" + +#: src/welcome-day-3.md +msgid "" +"**Standard Library:** Using essential types like `Option`, `Result`, `Vec`, " +"and `String`." +msgstr "" + +#: src/welcome-day-3.md +msgid "**Closures:** Anonymous functions that can capture their environment." +msgstr "" + +#: src/welcome-day-3.md +msgid "" +"You can write any type and associate behavior with it. We are now shifting " +"gears to apply these concepts to memory management and system design." +msgstr "" + +#: src/welcome-day-3.md src/welcome-day-4-afternoon.md +msgid "" +"Including 10 minute breaks, this session should take about 2 hours and 20 " +"minutes. It contains:" +msgstr "" + +#: src/memory-management.md +msgid "Drop" +msgstr "" + +#: src/memory-management/review.md +msgid "Programs allocate memory in two ways:" +msgstr "" + +#: src/memory-management/review.md +msgid "Stack: Continuous area of memory for local variables." +msgstr "" + +#: src/memory-management/review.md +msgid "Values have fixed sizes known at compile time." +msgstr "" + +#: src/memory-management/review.md +msgid "Extremely fast: just move a stack pointer." +msgstr "" + +#: src/memory-management/review.md +msgid "Easy to manage: follows function calls." +msgstr "" + +#: src/memory-management/review.md +msgid "Great memory locality." +msgstr "" + +#: src/memory-management/review.md +msgid "Heap: Storage of values outside of function calls." +msgstr "" + +#: src/memory-management/review.md +msgid "Values have dynamic sizes determined at runtime." +msgstr "" + +#: src/memory-management/review.md +msgid "Slightly slower than the stack: some bookkeeping needed." +msgstr "" + +#: src/memory-management/review.md +msgid "No guarantee of memory locality." +msgstr "" + +#: src/memory-management/review.md +msgid "" +"Creating a `String` puts fixed-sized metadata on the stack and dynamically " +"sized data, the actual string, on the heap:" +msgstr "" + +#: src/memory-management/review.md +msgid "" +"Mention that a `String` is backed by a `Vec`, so it has a capacity and " +"length and can grow if mutable via reallocation on the heap." +msgstr "" + +#: src/memory-management/review.md +msgid "" +"If students ask about it, you can mention that the underlying memory is heap " +"allocated using the [System Allocator](https://doc.rust-lang.org/std/alloc/" +"struct.System.html) and custom allocators can be implemented using the " +"[Allocator API](https://doc.rust-lang.org/std/alloc/index.html)" +msgstr "" + +#: src/memory-management/review.md +msgid "" +"We can inspect the memory layout with `unsafe` Rust. However, you should " +"point out that this is rightfully unsafe!" +msgstr "" + +#: src/memory-management/review.md src/testing/unit-tests.md +msgid "' '" +msgstr "" + +#: src/memory-management/review.md +msgid "\"world\"" +msgstr "" + +#: src/memory-management/review.md +msgid "" +"// DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could lead " +"to\n" +" // undefined behavior.\n" +msgstr "" + +#: src/memory-management/review.md +msgid "\"capacity = {capacity}, ptr = {ptr:#x}, len = {len}\"" +msgstr "" + +#: src/memory-management/approaches.md +msgid "Traditionally, languages have fallen into two broad categories:" +msgstr "" + +#: src/memory-management/approaches.md +msgid "Full control via manual memory management: C, C++, Pascal, ..." +msgstr "" + +#: src/memory-management/approaches.md +msgid "Programmer decides when to allocate or free heap memory." +msgstr "" + +#: src/memory-management/approaches.md +msgid "" +"Programmer must determine whether a pointer still points to valid memory." +msgstr "" + +#: src/memory-management/approaches.md +msgid "Studies show, programmers make mistakes." +msgstr "" + +#: src/memory-management/approaches.md +msgid "" +"Full safety via automatic memory management at runtime: Java, Python, Go, " +"Haskell, ..." +msgstr "" + +#: src/memory-management/approaches.md +msgid "" +"A runtime system ensures that memory is not freed until it can no longer be " +"referenced." +msgstr "" + +#: src/memory-management/approaches.md +msgid "Typically implemented with reference counting or garbage collection." +msgstr "" + +#: src/memory-management/approaches.md +msgid "Rust offers a new mix:" +msgstr "" + +#: src/memory-management/approaches.md +msgid "" +"Full control _and_ safety via compile time enforcement of correct memory " +"management." +msgstr "" + +#: src/memory-management/approaches.md +msgid "It does this with an explicit ownership concept." +msgstr "" + +#: src/memory-management/approaches.md +msgid "" +"This slide is intended to help students coming from other languages to put " +"Rust in context." +msgstr "" + +#: src/memory-management/approaches.md +msgid "" +"C must manage heap manually with `malloc` and `free`. Common errors include " +"forgetting to call `free`, calling it multiple times for the same pointer, " +"or dereferencing a pointer after the memory it points to has been freed." +msgstr "" + +#: src/memory-management/approaches.md +msgid "" +"C++ has tools like smart pointers (`unique_ptr`, `shared_ptr`) that take " +"advantage of language guarantees about calling destructors to ensure memory " +"is freed when a function returns. It is still quite easy to misuse these " +"tools and create similar bugs to C." +msgstr "" + +#: src/memory-management/approaches.md +msgid "" +"Java, Go, and Python rely on the garbage collector to identify memory that " +"is no longer reachable and discard it. This guarantees that any pointer can " +"be dereferenced, eliminating use-after-free and other classes of bugs. But, " +"GC has a runtime cost and is difficult to tune properly." +msgstr "" + +#: src/memory-management/approaches.md +msgid "" +"Rust's ownership and borrowing model can, in many cases, get the performance " +"of C, with alloc and free operations precisely where they are required -- " +"zero-cost. It also provides tools similar to C++'s smart pointers. When " +"required, other options such as reference counting are available, and there " +"are even crates available to support runtime garbage collection (not covered " +"in this class)." +msgstr "" + +#: src/memory-management/ownership.md +msgid "" +"All variable bindings have a _scope_ where they are valid and it is an error " +"to use a variable outside its scope:" +msgstr "" + +#: src/memory-management/ownership.md +msgid "" +"We say that the variable _owns_ the value. Every Rust value has precisely " +"one owner at all times." +msgstr "" + +#: src/memory-management/ownership.md +msgid "" +"At the end of the scope, the variable is _dropped_ and the data is freed. A " +"destructor can run here to free up resources." +msgstr "" + +#: src/memory-management/ownership.md +msgid "" +"Students familiar with garbage collection implementations will know that a " +"garbage collector starts with a set of \"roots\" to find all reachable " +"memory. Rust's \"single owner\" principle is a similar idea." +msgstr "" + +#: src/memory-management/move.md +msgid "An assignment will transfer _ownership_ between variables:" +msgstr "" + +#: src/memory-management/move.md src/concurrency/async-control-flow/select.md +msgid "\"Hello!\"" +msgstr "" + +#: src/memory-management/move.md +msgid "// dbg!(s1);\n" +msgstr "" + +#: src/memory-management/move.md +msgid "The assignment of `s1` to `s2` transfers ownership." +msgstr "" + +#: src/memory-management/move.md +msgid "When `s1` goes out of scope, nothing happens: it does not own anything." +msgstr "" + +#: src/memory-management/move.md +msgid "When `s2` goes out of scope, the string data is freed." +msgstr "" + +#: src/memory-management/move.md +msgid "Before move to `s2`:" +msgstr "" + +#: src/memory-management/move.md +msgid "After move to `s2`:" +msgstr "" + +#: src/memory-management/move.md +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 \"(inaccessible)\" : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| H | e | l | l | o | ! | :\n" +": | len | 6 | : | : +----+----+----+----+----+----+ :\n" +": | capacity | 6 | : | : :\n" +": +-----------+-------+ : | : :\n" +": : | `- - - - - - - - - - - - - - - - - - -'\n" +": s2 : |\n" +": +-----------+-------+ : |\n" +": | ptr | o---+---+--'\n" +": | len | 6 | :\n" +": | capacity | 6 | :\n" +": +-----------+-------+ :\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/memory-management/move.md +msgid "" +"When you pass a value to a function, the value is assigned to the function " +"parameter. This transfers ownership:" +msgstr "" + +#: src/memory-management/move.md src/memory-management/clone.md +msgid "\"Hello {name}\"" +msgstr "" + +#: src/memory-management/move.md src/memory-management/clone.md +#: src/android/aidl/types/parcelables.md src/android/interoperability/java.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "\"Alice\"" +msgstr "" + +#: src/memory-management/move.md +msgid "// say_hello(name);\n" +msgstr "" + +#: src/memory-management/move.md +msgid "" +"Mention that this is the opposite of the defaults in C++, which copies by " +"value unless you use `std::move` (and the move constructor is defined!)." +msgstr "" + +#: src/memory-management/move.md +msgid "" +"It is only the ownership that moves. Whether any machine code is generated " +"to manipulate the data itself is a matter of optimization, and such copies " +"are aggressively optimized away." +msgstr "" + +#: src/memory-management/move.md +msgid "" +"Simple values (such as integers) can be marked `Copy` (see later slides)." +msgstr "" + +#: src/memory-management/move.md +msgid "In Rust, clones are explicit (by using `clone`)." +msgstr "" + +#: src/memory-management/move.md +msgid "In the `say_hello` example:" +msgstr "" + +#: src/memory-management/move.md +msgid "" +"With the first call to `say_hello`, `main` gives up ownership of `name`. " +"Afterwards, `name` cannot be used anymore within `main`." +msgstr "" + +#: src/memory-management/move.md +msgid "" +"The heap memory allocated for `name` will be freed at the end of the " +"`say_hello` function." +msgstr "" + +#: src/memory-management/move.md +msgid "" +"`main` can retain ownership if it passes `name` as a reference (`&name`) and " +"if `say_hello` accepts a reference as a parameter." +msgstr "" + +#: src/memory-management/move.md +msgid "" +"Alternatively, `main` can pass a clone of `name` in the first call (`name." +"clone()`)." +msgstr "" + +#: src/memory-management/move.md +msgid "" +"Rust makes it harder than C++ to inadvertently create copies by making move " +"semantics the default, and by forcing programmers to make clones explicit." +msgstr "" + +#: src/memory-management/move.md +msgid "Defensive Copies in Modern C++" +msgstr "" + +#: src/memory-management/move.md +msgid "Modern C++ solves this differently:" +msgstr "" + +#: src/memory-management/move.md +msgid "\"Cpp\"" +msgstr "" + +#: src/memory-management/move.md +msgid "// Duplicate the data in s1.\n" +msgstr "" + +#: src/memory-management/move.md +msgid "" +"The heap data from `s1` is duplicated and `s2` gets its own independent copy." +msgstr "" + +#: src/memory-management/move.md +msgid "When `s1` and `s2` go out of scope, they each free their own memory." +msgstr "" + +#: src/memory-management/move.md +msgid "Before copy-assignment:" +msgstr "" + +#: src/memory-management/move.md +msgid "After copy-assignment:" +msgstr "" + +#: src/memory-management/move.md +msgid "" +"C++ has made a slightly different choice than Rust. Because `=` copies data, " +"the string data has to be cloned. Otherwise we would get a double-free when " +"either string goes out of scope." +msgstr "" + +#: src/memory-management/move.md +msgid "" +"C++ also has [`std::move`](https://en.cppreference.com/w/cpp/utility/move), " +"which is used to indicate when a value may be moved from. If the example had " +"been `s2 = std::move(s1)`, no heap allocation would take place. After the " +"move, `s1` would be in a valid but unspecified state. Unlike Rust, the " +"programmer is allowed to keep using `s1`." +msgstr "" + +#: src/memory-management/move.md +msgid "" +"Unlike Rust, `=` in C++ can run arbitrary code as determined by the type " +"that is being copied or moved." +msgstr "" + +#: src/memory-management/clone.md +msgid "" +"Sometimes you _want_ to make a copy of a value. The `Clone` trait " +"accomplishes this." +msgstr "" + +#: src/memory-management/clone.md +msgid "" +"The idea of `Clone` is to make it easy to spot where heap allocations are " +"occurring. Look for `.clone()` and a few others like `vec!` or `Box::new`." +msgstr "" + +#: src/memory-management/clone.md +msgid "" +"It's common to \"clone your way out\" of problems with the borrow checker, " +"and return later to try to optimize those clones away." +msgstr "" + +#: src/memory-management/clone.md +msgid "" +"`clone` generally performs a deep copy of the value, meaning that if you e." +"g. clone an array, all of the elements of the array are cloned as well." +msgstr "" + +#: src/memory-management/clone.md +msgid "" +"The behavior for `clone` is user-defined, so it can perform custom cloning " +"logic if needed." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "" +"While move semantics are the default, certain types are copied by default:" +msgstr "" + +#: src/memory-management/copy-types.md +msgid "These types implement the `Copy` trait." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "You can opt-in your own types to use copy semantics:" +msgstr "" + +#: src/memory-management/copy-types.md +msgid "After the assignment, both `p1` and `p2` own their own data." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "We can also use `p1.clone()` to explicitly copy the data." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "Copying and cloning are not the same thing:" +msgstr "" + +#: src/memory-management/copy-types.md +msgid "" +"Copying refers to bitwise copies of memory regions and does not work on " +"arbitrary objects." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "" +"Copying does not allow for custom logic (unlike copy constructors in C++)." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "" +"Cloning is a more general operation and also allows for custom behavior by " +"implementing the `Clone` trait." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "Copying does not work on types that implement the `Drop` trait." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "In the above example, try the following:" +msgstr "" + +#: src/memory-management/copy-types.md +msgid "" +"Add a `String` field to `struct Point`. It will not compile because `String` " +"is not a `Copy` type." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "" +"Remove `Copy` from the `derive` attribute. The compiler error is now in the " +"`println!` for `p1`." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "Show that it works if you clone `p1` instead." +msgstr "" + +#: src/memory-management/copy-types.md +msgid "" +"Shared references are `Copy`/`Clone`, mutable references are not. This is " +"because Rust requires that mutable references be exclusive, so while it's " +"valid to make a copy of a shared reference, creating a copy of a mutable " +"reference would violate Rust's borrowing rules." +msgstr "" + +#: src/memory-management/drop.md +msgid "The `Drop` Trait" +msgstr "" + +#: src/memory-management/drop.md +msgid "" +"Values which implement [`Drop`](https://doc.rust-lang.org/std/ops/trait.Drop." +"html) can specify code to run when they go out of scope:" +msgstr "" + +#: src/memory-management/drop.md +msgid "\"Dropping {}\"" +msgstr "" + +#: src/memory-management/drop.md src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"a\"" +msgstr "" + +#: src/memory-management/drop.md src/android/testing/googletest.md +msgid "\"b\"" +msgstr "" + +#: src/memory-management/drop.md +msgid "\"c\"" +msgstr "" + +#: src/memory-management/drop.md +msgid "\"d\"" +msgstr "" + +#: src/memory-management/drop.md +msgid "\"Exiting innermost block\"" +msgstr "" + +#: src/memory-management/drop.md +msgid "\"Exiting next block\"" +msgstr "" + +#: src/memory-management/drop.md +msgid "\"Exiting main\"" +msgstr "" + +#: src/memory-management/drop.md +msgid "Note that `std::mem::drop` is not the same as `std::ops::Drop::drop`." +msgstr "" + +#: src/memory-management/drop.md +msgid "Values are automatically dropped when they go out of scope." +msgstr "" + +#: src/memory-management/drop.md +msgid "" +"When a value is dropped, if it implements `std::ops::Drop` then its `Drop::" +"drop` implementation will be called." +msgstr "" + +#: src/memory-management/drop.md +msgid "" +"All its fields will then be dropped too, whether or not it implements `Drop`." +msgstr "" + +#: src/memory-management/drop.md +msgid "" +"`std::mem::drop` is just an empty function that takes any value. The " +"significance is that it takes ownership of the value, so at the end of its " +"scope it gets dropped. This makes it a convenient way to explicitly drop " +"values earlier than they would otherwise go out of scope." +msgstr "" + +#: src/memory-management/drop.md +msgid "" +"This is useful for objects that do some work on `drop`: releasing locks, " +"closing files, etc." +msgstr "" + +#: src/memory-management/drop.md +msgid "Why doesn't `Drop::drop` take `self`?" +msgstr "" + +#: src/memory-management/drop.md +msgid "" +"Short-answer: If it did, `std::mem::drop` would be called at the end of the " +"block, resulting in another call to `Drop::drop`, and a stack overflow!" +msgstr "" + +#: src/memory-management/drop.md +msgid "Try replacing `drop(a)` with `a.drop()`." +msgstr "" + +#: src/memory-management/exercise.md +msgid "" +"In this example, we will implement a complex data type that owns all of its " +"data. We will use the \"builder pattern\" to support building a new value " +"piece-by-piece, using convenience functions." +msgstr "" + +#: src/memory-management/exercise.md +msgid "Fill in the missing pieces." +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "/// A representation of a software package.\n" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "" +"/// Return a representation of this package as a dependency, for use in\n" +" /// building other packages.\n" +msgstr "" + +#: src/memory-management/exercise.md +msgid "\"1\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "" +"/// A builder for a Package. Use `build()` to create the `Package` itself.\n" +msgstr "" + +#: src/memory-management/exercise.md +msgid "\"2\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "/// Set the package version.\n" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "/// Set the package authors.\n" +msgstr "" + +#: src/memory-management/exercise.md +msgid "\"3\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "/// Add an additional dependency.\n" +msgstr "" + +#: src/memory-management/exercise.md +msgid "\"4\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "/// Set the language. If not set, language defaults to None.\n" +msgstr "" + +#: src/memory-management/exercise.md +msgid "\"5\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "\"base64\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "\"0.13\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "\"log\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "\"0.4\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "\"serde\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "\"djmitche\"" +msgstr "" + +#: src/memory-management/exercise.md src/memory-management/solution.md +msgid "\"4.0\"" +msgstr "" + +#: src/memory-management/solution.md +msgid "\"0.1\"" +msgstr "" + +#: src/smart-pointers.md +msgid "Box" +msgstr "" + +#: src/smart-pointers.md +msgid "Rc" +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"[`Box`](https://doc.rust-lang.org/std/boxed/struct.Box.html) is an owned " +"pointer to data on the heap:" +msgstr "" + +#: src/smart-pointers/box.md +msgid "\"five: {}\"" +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"`Box` implements `Deref`, which means that you can [call " +"methods from `T` directly on a `Box`](https://doc.rust-lang.org/std/ops/" +"trait.Deref.html#more-on-deref-coercion)." +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"Recursive data types or data types with dynamic sizes cannot be stored " +"inline without a pointer indirection. `Box` accomplishes that indirection:" +msgstr "" + +#: src/smart-pointers/box.md +msgid "/// A non-empty list: first element and the rest of the list.\n" +msgstr "" + +#: src/smart-pointers/box.md +msgid "/// An empty list.\n" +msgstr "" + +#: src/smart-pointers/box.md +msgid "\"{list:?}\"" +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - - . .- - - - - - - - - - - - - - - - - - - - " +"- - - - -.\n" +": : : :\n" +": " +"list : : :\n" +": +---------+----+----+ : : +---------+----+----+ +------+----" +"+----+ :\n" +": | Element | 1 | o--+----+-----+--->| Element | 2 | o--+--->| Nil | // " +"| // | :\n" +": +---------+----+----+ : : +---------+----+----+ +------+----" +"+----+ :\n" +": : : :\n" +": : : :\n" +"'- - - - - - - - - - - - - - ' '- - - - - - - - - - - - - - - - - - - - " +"- - - - -'\n" +"```" +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"`Box` is like `std::unique_ptr` in C++, except that it's guaranteed to be " +"not null." +msgstr "" + +#: src/smart-pointers/box.md +msgid "A `Box` can be useful when you:" +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"have a type whose size can't be known at compile time, but the Rust compiler " +"wants to know an exact size." +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"want to transfer ownership of a large amount of data. To avoid copying large " +"amounts of data on the stack, instead store the data on the heap in a `Box` " +"so only the pointer is moved." +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"If `Box` was not used and we attempted to embed a `List` directly into the " +"`List`, the compiler would not be able to compute a fixed size for the " +"struct in memory (the `List` would be of infinite size)." +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"`Box` solves this problem as it has the same size as a regular pointer and " +"just points at the next element of the `List` in the heap." +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"Remove the `Box` in the List definition and show the compiler error. We get " +"the message \"recursive without indirection\", because for data recursion, " +"we have to use indirection, a `Box` or reference of some kind, instead of " +"storing the value directly." +msgstr "" + +#: src/smart-pointers/box.md +msgid "" +"Though `Box` looks like `std::unique_ptr` in C++, it cannot be empty/null. " +"This makes `Box` one of the types that allow the compiler to optimize " +"storage of some enums (the \"niche optimization\")." +msgstr "" + +#: src/smart-pointers/rc.md +msgid "" +"[`Rc`](https://doc.rust-lang.org/std/rc/struct.Rc.html) is a reference-" +"counted shared pointer. Use this when you need to refer to the same data " +"from multiple places:" +msgstr "" + +#: src/smart-pointers/rc.md +msgid "" +"Each `Rc` points to the same shared data structure, containing strong and " +"weak pointers and the value:" +msgstr "" + +#: src/smart-pointers/rc.md +msgid "" +"See [`Arc`](../concurrency/shared-state/arc.md) and [`Mutex`](https://doc." +"rust-lang.org/std/sync/struct.Mutex.html) if you are in a multi-threaded " +"context." +msgstr "" + +#: src/smart-pointers/rc.md +msgid "" +"You can _downgrade_ a shared pointer into a [`Weak`](https://doc.rust-lang." +"org/std/rc/struct.Weak.html) pointer to create cycles that will get dropped." +msgstr "" + +#: src/smart-pointers/rc.md +msgid "" +"`Rc`'s count ensures that its contained value is valid for as long as there " +"are references." +msgstr "" + +#: src/smart-pointers/rc.md +msgid "`Rc` in Rust is like `std::shared_ptr` in C++." +msgstr "" + +#: src/smart-pointers/rc.md +msgid "" +"`Rc::clone` is cheap: it creates a pointer to the same allocation and " +"increases the reference count. Does not make a deep clone and can generally " +"be ignored when looking for performance issues in code." +msgstr "" + +#: src/smart-pointers/rc.md +msgid "" +"`make_mut` actually clones the inner value if necessary (\"clone-on-write\") " +"and returns a mutable reference." +msgstr "" + +#: src/smart-pointers/rc.md +msgid "Use `Rc::strong_count` to check the reference count." +msgstr "" + +#: src/smart-pointers/rc.md +msgid "" +"`Rc::downgrade` gives you a _weakly reference-counted_ object to create " +"cycles that will be dropped properly (likely in combination with `RefCell`)." +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "" +"We previously saw how trait objects can be used with references, e.g `&dyn " +"Pet`. However, we can also use trait objects with smart pointers like `Box` " +"to create an owned trait object: `Box`." +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "Memory layout after allocating `pets`:" +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - " +"- - - -.\n" +": : : :\n" +": \"pets: Vec>\" : : \"data: Cat\" +----+----" +"+----+----+ :\n" +": +-----------+-------+ : : +-------+-------+ | F | i | d " +"| o | :\n" +": | ptr | o---+-------+--. : | lives | 9 | +----+----+----" +"+----+ :\n" +": | len | 2 | : | : +-------+-------+ " +"^ :\n" +": | capacity | 2 | : | : ^ " +"| :\n" +": +-----------+-------+ : | : | " +"'-------. :\n" +": : | : | data:" +"\"Dog\"| :\n" +": : | : | +-------" +"+--|-------+ :\n" +"`- - - - - - - - - - - - - - - -' | : +---|-+-----+ | name | o, " +"4, 4 | :\n" +" `--+-->| o o | o o-|----->| age " +"| 5 | :\n" +" : +-|---+-|---+ +-------" +"+----------+ :\n" +" : | " +"| :\n" +" `- - -| - - |- - - - - - - - - - - - - " +"- - - -'\n" +" | |\n" +" | | " +"\"Program text\"\n" +" .- - -| - - |- - - - - - - - - - - - - " +"- - - -.\n" +" : | | " +"vtable :\n" +" : | | " +"+----------------------+ :\n" +" : | `----->| \"::" +"talk\" | :\n" +" : | " +"+----------------------+ :\n" +" : | " +"vtable :\n" +" : | " +"+----------------------+ :\n" +" : '----------->| \"::" +"talk\" | :\n" +" : " +"+----------------------+ :\n" +" : :\n" +" '- - - - - - - - - - - - - - - - - - - " +"- - - -'\n" +"```" +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "" +"Types that implement a given trait may be of different sizes. This makes it " +"impossible to have things like `Vec` in the example above." +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "" +"`dyn Pet` is a way to tell the compiler about a dynamically sized type that " +"implements `Pet`." +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "" +"In the example, `pets` is allocated on the stack and the vector data is on " +"the heap. The two vector elements are _fat pointers_:" +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "" +"A fat pointer is a double-width pointer. It has two components: a pointer to " +"the actual object and a pointer to the [virtual method table](https://en." +"wikipedia.org/wiki/Virtual_method_table) (vtable) for the `Pet` " +"implementation of that particular object." +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "" +"The data for the `Dog` named Fido is the `name` and `age` fields. The `Cat` " +"has a `lives` field." +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "Compare these outputs in the above example:" +msgstr "" + +#: src/smart-pointers/trait-objects.md +msgid "\"{} {}\"" +msgstr "" + +#: src/smart-pointers/trait-objects.md src/modules/exercise.md +#: src/modules/solution.md src/android/build-rules/library.md +#: src/android/interoperability/cpp/rust-bridge.md +#: src/concurrency/async-pitfalls/cancellation.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +#: src/idiomatic/polymorphism/refresher/conditional-methods.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/crying-wolf.md +msgid "\"{}\"" +msgstr "" + +#: src/smart-pointers/exercise.md +msgid "" +"A binary tree is a tree-type data structure where every node has two " +"children (left and right). We will create a tree where each node stores a " +"value. For a given node N, all nodes in a N's left subtree contain smaller " +"values, and all nodes in N's right subtree will contain larger values. A " +"given value should only be stored in the tree once, i.e. no duplicate nodes." +msgstr "" + +#: src/smart-pointers/exercise.md +msgid "Implement the following types, so that the given tests pass." +msgstr "" + +#: src/smart-pointers/exercise.md src/smart-pointers/solution.md +msgid "/// A node in the binary tree.\n" +msgstr "" + +#: src/smart-pointers/exercise.md src/smart-pointers/solution.md +msgid "/// A possibly-empty subtree.\n" +msgstr "" + +#: src/smart-pointers/exercise.md src/smart-pointers/solution.md +msgid "" +"/// A container storing a set of values, using a binary tree.\n" +"///\n" +"/// If the same value is added multiple times, it is only stored once.\n" +msgstr "" + +#: src/smart-pointers/exercise.md +msgid "" +"// Implement `new` for `Node`.\n" +"// Implement `new`, `insert`, `len`, and `has` for `Subtree`.\n" +msgstr "" + +#: src/smart-pointers/exercise.md src/smart-pointers/solution.md +msgid "// not a unique item\n" +msgstr "" + +#: src/welcome-day-3-afternoon.md +msgid "" +"Including 10 minute breaks, this session should take about 2 hours and 30 " +"minutes. It contains:" +msgstr "" + +#: src/borrowing.md src/unsafe-rust.md +msgid "This segment should take about 1 hour and 15 minutes. It contains:" +msgstr "" + +#: src/borrowing/shared.md +msgid "" +"As we saw before, instead of transferring ownership when calling a function, " +"you can let a function _borrow_ the value:" +msgstr "" + +#: src/borrowing/shared.md +msgid "The `add` function _borrows_ two points and returns a new point." +msgstr "" + +#: src/borrowing/shared.md +msgid "The caller retains ownership of the inputs." +msgstr "" + +#: src/borrowing/shared.md +msgid "" +"This slide is a review of the material on references from day 1, expanding " +"slightly to include function arguments and return values." +msgstr "" + +#: src/borrowing/shared.md +msgid "Notes on stack returns and inlining:" +msgstr "" + +#: src/borrowing/shared.md +msgid "" +"Demonstrate that the return from `add` is cheap because the compiler can " +"eliminate the copy operation, by inlining the call to add into main. Change " +"the above code to print stack addresses and run it on the [Playground]" +"(https://play.rust-lang.org/?" +"version=stable&mode=release&edition=2024&gist=0cb13be1c05d7e3446686ad9947c4671) " +"or look at the assembly in [Godbolt](https://rust.godbolt.org/). In the " +"\"DEBUG\" optimization level, the addresses should change, while they stay " +"the same when changing to the \"RELEASE\" setting:" +msgstr "" + +#: src/borrowing/shared.md +msgid "" +"The Rust compiler can do automatic inlining, that can be disabled on a " +"function level with `#[inline(never)]`." +msgstr "" + +#: src/borrowing/shared.md +msgid "" +"Once disabled, the printed address will change on all optimization levels. " +"Looking at Godbolt or Playground, one can see that in this case, the return " +"of the value depends on the ABI, e.g. on amd64 the two i32 that is making up " +"the point will be returned in 2 registers (eax and edx)." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"Rust's _borrow checker_ puts constraints on the ways you can borrow values. " +"We've already seen that a reference cannot _outlive_ the value it borrows:" +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"There's also a second main rule that the borrow checker enforces: The " +"_aliasing_ rule. For a given value, at any time:" +msgstr "" + +#: src/borrowing/borrowck.md +msgid "You can have one or more shared references to the value, _or_" +msgstr "" + +#: src/borrowing/borrowck.md +msgid "You can have exactly one exclusive reference to the value." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"The \"outlives\" rule was demonstrated previously when we first looked at " +"references. We review it here to show students that the borrow checking is " +"following a few different rules to validate borrowing." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"The above code does not compile because `a` is borrowed as mutable (through " +"`c`) and as immutable (through `b`) at the same time." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"Note that the requirement is that conflicting references not _exist_ at the " +"same point. It does not matter where the reference is dereferenced. Try " +"commenting out `*c = 20` and show that the compiler error still occurs even " +"if we never use `c`." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"Note that the intermediate reference `c` isn't necessary to trigger a borrow " +"conflict. Replace `c` with a direct mutation of `a` and demonstrate that " +"this produces a similar error. This is because direct mutation of a value " +"effectively creates a temporary mutable reference." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"Move the `dbg!` statement for `b` before the scope that introduces `c` to " +"make the code compile." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"After that change, the compiler realizes that `b` is only ever used before " +"the new mutable borrow of `a` through `c`. This is a feature of the borrow " +"checker called \"non-lexical lifetimes\"." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"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 invalidating the original reference. [This " +"playground example](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2024&gist=8f5896878611566845fe3b0f4dc5af68) " +"demonstrates that behavior." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"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 a piece of data at a time." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"Rust also uses this constraint to optimize code. For example, a value behind " +"a shared reference can be safely cached in a register for the lifetime of " +"that reference." +msgstr "" + +#: src/borrowing/borrowck.md +msgid "" +"Fields of a struct can be borrowed independently of each other, but calling " +"a method on a struct will borrow the whole struct, potentially invalidating " +"references to individual fields. See [this playground snippet](https://play." +"rust-lang.org/?" +"version=stable&mode=debug&edition=2024&gist=f293a31f2d4d0d31770486247c2e8437) " +"for an example of this." +msgstr "" + +#: src/borrowing/examples.md +msgid "" +"As a concrete example of how these borrowing rules prevent memory errors, " +"consider the case of modifying a collection while there are references to " +"its elements:" +msgstr "" + +#: src/borrowing/examples.md +msgid "Similarly, consider the case of iterator invalidation:" +msgstr "" + +#: src/borrowing/examples.md +msgid "" +"In both of these cases, modifying the collection by pushing new elements " +"into it can potentially invalidate existing references to the collection's " +"elements if the collection has to reallocate." +msgstr "" + +#: src/borrowing/interior-mutability.md +msgid "" +"In some situations, it's necessary to modify data behind a shared (read-" +"only) reference. For example, a shared data structure might have an internal " +"cache, and wish to update that cache from read-only methods." +msgstr "" + +#: src/borrowing/interior-mutability.md +msgid "" +"The \"interior mutability\" pattern allows exclusive (mutable) access behind " +"a shared reference. The standard library provides several ways to do this, " +"all while still ensuring safety, typically by performing a runtime check." +msgstr "" + +#: src/borrowing/interior-mutability.md +msgid "" +"The main thing to take away from this slide is that Rust provides _safe_ " +"ways to modify data behind a shared reference. There are a variety of ways " +"to ensure that safety, and the next sub-slides present a few of them." +msgstr "" + +#: src/borrowing/interior-mutability/cell.md +msgid "" +"`Cell` wraps a value and allows getting or setting the value using only a " +"shared reference to the `Cell`. However, it does not allow any references to " +"the inner value. Since there are no references, borrowing rules cannot be " +"broken." +msgstr "" + +#: src/borrowing/interior-mutability/cell.md +#: src/borrowing/interior-mutability/refcell.md +msgid "// Note that `cell` is NOT declared as mutable.\n" +msgstr "" + +#: src/borrowing/interior-mutability/cell.md +msgid "" +"`Cell` is a simple means to ensure safety: it has a `set` method that takes " +"`&self`. This needs no runtime check, but requires moving values, which can " +"have its own cost." +msgstr "" + +#: src/borrowing/interior-mutability/refcell.md +msgid "" +"`RefCell` allows accessing and mutating a wrapped value by providing " +"alternative types `Ref` and `RefMut` that emulate `&T`/`&mut T` without " +"actually being Rust references." +msgstr "" + +#: src/borrowing/interior-mutability/refcell.md +msgid "" +"These types perform dynamic checks using a counter in the `RefCell` to " +"prevent existence of a `RefMut` alongside another `Ref`/`RefMut`." +msgstr "" + +#: src/borrowing/interior-mutability/refcell.md +msgid "" +"By implementing `Deref` (and `DerefMut` for `RefMut`), these types allow " +"calling methods on the inner value without allowing references to escape." +msgstr "" + +#: src/borrowing/interior-mutability/refcell.md +msgid "" +"// This triggers an error at runtime.\n" +" // let other = cell.borrow();\n" +" // println!(\"{}\", other);\n" +msgstr "" + +#: src/borrowing/interior-mutability/refcell.md +msgid "\"{cell:?}\"" +msgstr "" + +#: src/borrowing/interior-mutability/refcell.md +msgid "" +"`RefCell` enforces Rust's usual borrowing rules (either multiple shared " +"references or a single exclusive reference) with a runtime check. In this " +"case, all borrows are very short and never overlap, so the checks always " +"succeed." +msgstr "" + +#: src/borrowing/interior-mutability/refcell.md +msgid "" +"The extra block in the example is to end the borrow created by the call to " +"`borrow_mut` before we print the cell. Trying to print a borrowed `RefCell` " +"just shows the message `\"{borrowed}\"`." +msgstr "" + +#: src/borrowing/interior-mutability/refcell.md +msgid "" +"There are also `OnceCell` and `OnceLock`, which allow initialization on " +"first use. Making these useful requires some more knowledge than students " +"have at this time." +msgstr "" + +#: src/borrowing/exercise.md +msgid "" +"In this exercise, you will manage a wizard's inventory using what you have " +"learned about borrowing and ownership." +msgstr "" + +#: src/borrowing/exercise.md +msgid "" +"The wizard has a collection of spells. You need to implement functions to " +"add spells to the inventory and to cast spells from them." +msgstr "" + +#: src/borrowing/exercise.md +msgid "" +"Spells have a limited number of uses. When a spell has no uses left, it must " +"be removed from the wizard's inventory." +msgstr "" + +#: src/borrowing/exercise.md +msgid "" +"// TODO: Implement `add_spell` to take ownership of a spell and add it to\n" +" // the wizard's inventory.\n" +msgstr "" + +#: src/borrowing/exercise.md +msgid "" +"// TODO: Implement `cast_spell` to borrow a spell from the inventory and\n" +" // cast it. The wizard's mana should decrease by the spell's cost and " +"the\n" +" // number of uses for the spell should decrease by 1.\n" +" //\n" +" // If the wizard doesn't have enough mana, the spell should fail.\n" +" // If the spell has no uses left, it is removed from the inventory.\n" +msgstr "" + +#: src/borrowing/exercise.md src/borrowing/solution.md +msgid "\"Fireball\"" +msgstr "" + +#: src/borrowing/exercise.md src/borrowing/solution.md +msgid "\"Ice Blast\"" +msgstr "" + +#: src/borrowing/exercise.md src/borrowing/solution.md +msgid "// Casts successfully\n" +msgstr "" + +#: src/borrowing/exercise.md src/borrowing/solution.md +msgid "// Casts successfully, then removed\n" +msgstr "" + +#: src/borrowing/exercise.md src/borrowing/solution.md +msgid "// Fails (not found)\n" +msgstr "" + +#: src/borrowing/exercise.md +msgid "" +"The goal of this exercise is to practice the core concepts of ownership and " +"borrowing, specifically the rule that you cannot mutate a collection while " +"holding a reference to one of its elements." +msgstr "" + +#: src/borrowing/exercise.md +msgid "" +"`add_spell` should take ownership of a `Spell` and move it into the " +"`Wizard`'s inventory." +msgstr "" + +#: src/borrowing/exercise.md +msgid "`cast_spell` is the core of the exercise. It needs to:" +msgstr "" + +#: src/borrowing/exercise.md +msgid "Find the spell (by index or by reference)." +msgstr "" + +#: src/borrowing/exercise.md +msgid "Check mana and decrement it." +msgstr "" + +#: src/borrowing/exercise.md +msgid "Decrement the spell's `uses`." +msgstr "" + +#: src/borrowing/exercise.md +msgid "Remove the spell if `uses == 0`." +msgstr "" + +#: src/borrowing/exercise.md +msgid "" +"**Borrow Checker Conflict:** If students try to hold a reference to the " +"spell (e.g., `let spell = &mut self.spells[i]`) and then call `self.spells." +"remove(i)` while that reference is still \"alive\" in the same scope, the " +"borrow checker will complain. This is a great opportunity to show how to " +"structure code to satisfy the borrow checker (e.g., by using indices or by " +"ensuring the borrow ends before the mutation)." +msgstr "" + +#: src/borrowing/solution.md +msgid "Solution: Wizard's Inventory" +msgstr "" + +#: src/borrowing/solution.md +msgid "\"Spell {} not found!\"" +msgstr "" + +#: src/borrowing/solution.md +msgid "\"Casting {}! Mana left: {}. Uses left: {}\"" +msgstr "" + +#: src/borrowing/solution.md +msgid "\"Not enough mana to cast {}!\"" +msgstr "" + +#: src/lifetimes.md +msgid "This segment should take about 1 hour and 5 minutes. It contains:" +msgstr "" + +#: src/lifetimes/simple-borrows.md +msgid "Borrowing with Functions" +msgstr "" + +#: src/lifetimes/simple-borrows.md +msgid "" +"As part of borrow checking, the compiler needs to reason about how borrows " +"flow into and out of functions. In the simplest case borrows last for the " +"duration of the function call:" +msgstr "" + +#: src/lifetimes/simple-borrows.md +msgid "// Borrow `val` for the function call.\n" +msgstr "" + +#: src/lifetimes/simple-borrows.md +msgid "// Borrow has ended and we're free to mutate.\n" +msgstr "" + +#: src/lifetimes/simple-borrows.md +msgid "" +"In this example we borrow `val` for the call to `borrows`. This would limit " +"our ability to mutate `val`, but once the function call returns the borrow " +"has ended and we're free to mutate again." +msgstr "" + +#: src/lifetimes/returning-borrows.md +msgid "" +"But we can also have our function return a reference! This means that a " +"borrow flows back out of a function:" +msgstr "" + +#: src/lifetimes/returning-borrows.md +msgid "// x = 5; // đŸ› ī¸âŒ `x` is still borrowed!\n" +msgstr "" + +#: src/lifetimes/returning-borrows.md +msgid "" +"Rust functions can return references, meaning that a borrow can flow back " +"out of a function." +msgstr "" + +#: src/lifetimes/returning-borrows.md +msgid "" +"If a function returns a reference (or another kind of borrow), it was likely " +"derived from one of its arguments. This means that the return value of the " +"function will extend the borrow for one or more argument borrows." +msgstr "" + +#: src/lifetimes/returning-borrows.md +msgid "" +"This case is still fairly simple, in that only one borrow is passed into the " +"function, so the returned borrow has to be the same one." +msgstr "" + +#: src/lifetimes/multiple-borrows.md +msgid "" +"But what about when there are multiple borrows passed into a function and " +"one being returned?" +msgstr "" + +#: src/lifetimes/multiple-borrows.md +msgid "\"Return either `a` or `b`\"" +msgstr "" + +#: src/lifetimes/multiple-borrows.md +msgid "" +"// Which one is still borrowed?\n" +" // Should either mutation be allowed?\n" +msgstr "" + +#: src/lifetimes/multiple-borrows.md +msgid "" +"This code does not compile right now because it is missing lifetime " +"annotations. Before we get it to compile, use this opportunity to have " +"students to think about which of our argument borrows should be extended by " +"the return value." +msgstr "" + +#: src/lifetimes/multiple-borrows.md +msgid "" +"We pass two borrows into `multiple` and one is going to come back out, which " +"means we will need to extend the borrow of one of the argument lifetimes. " +"Which one should be extended? Do we need to see the body of `multiple` to " +"figure this out?" +msgstr "" + +#: src/lifetimes/multiple-borrows.md +msgid "" +"When borrow checking, the compiler doesn't look at the body of `multiple` to " +"reason about the borrows flowing out, instead it looks only at the signature " +"of the function for borrow analysis." +msgstr "" + +#: src/lifetimes/multiple-borrows.md +msgid "" +"In this case there is not enough information to determine if `a` or `b` will " +"be borrowed by the returned reference. Show students the compiler errors and " +"introduce the lifetime syntax:" +msgstr "" + +#: src/lifetimes/borrow-both.md +msgid "" +"In this case, we have a function where either `a` or `b` may be returned. In " +"this case we use the lifetime annotations to tell the compiler that both " +"borrows may flow into the return value." +msgstr "" + +#: src/lifetimes/borrow-both.md +msgid "" +"// Which one is still borrowed?\n" +" // Should either mutation be allowed?\n" +" // a += 7;\n" +" // b += 7;\n" +msgstr "" + +#: src/lifetimes/borrow-both.md +msgid "" +"The `pick` function will return either `a` or `b` depending on the value of " +"`c`, which means we can't know at compile time which one will be returned." +msgstr "" + +#: src/lifetimes/borrow-both.md +msgid "" +"To express this to the compiler, we use the same lifetime for both `a` and " +"`b`, along with the return type. This means that the returned reference will " +"borrow BOTH `a` and `b`!" +msgstr "" + +#: src/lifetimes/borrow-both.md +msgid "" +"Uncomment both of the commented lines and show that `r` is borrowing both " +"`a` and `b`, even though at runtime it will only point to one of them." +msgstr "" + +#: src/lifetimes/borrow-both.md +msgid "" +"Change the first argument to `pick` to show that the result is the same " +"regardless of if `a` or `b` is returned." +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "" +"In this example `find_nearest` takes in multiple borrows but returns only " +"one of them. The lifetime annotations explicitly tie the returned borrow to " +"the corresponding argument borrow." +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "" +"/// Searches `points` for the point closest to `query`.\n" +"/// Assumes there's at least one point in `points`.\n" +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "// query // What happens if we do this instead?\n" +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "// `query` isn't borrowed at this point.\n" +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "" +"It may be helpful to collapse the definition of `find_nearest` to put more " +"focus on the signature of the function. The actual logic in the function is " +"somewhat complex and isn't important for the purpose of borrow analysis." +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "" +"When we call `find_nearest` the returned reference doesn't borrow `query`, " +"and so we are free to drop it while `nearest` is still active." +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "" +"But what happens if we return the wrong borrow? Change the last line of " +"`find_nearest` to return `query` instead. Show the compiler error to the " +"students." +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "" +"The first thing we have to do is add a lifetime annotation to `query`. Show " +"students that we can add a second lifetime `'b` to `find_nearest`." +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "" +"Show the new error to the students. The borrow checker verifies that the " +"logic in the function body actually returns a reference with the correct " +"lifetime, enforcing that the function adheres to the contract set by the " +"function's signature." +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "" +"The \"help\" message in the error notes that we can add a lifetime bound " +"`'b: 'a` to say that `'b` will live at least as long as `'a`, which would " +"then allow us to return `query`. This is an example of lifetime subtyping, " +"which allows us to return a longer lifetime where a shorter one is expected." +msgstr "" + +#: src/lifetimes/borrow-one.md +msgid "" +"We can do something similar by returning a `'static` lifetime, e.g., a " +"reference to a `static` variable. The `'static` lifetime is guaranteed to be " +"longer than any other lifetime, so it's always safe to return in place of a " +"shorter lifetime." +msgstr "" + +#: src/lifetimes/lifetime-elision.md +msgid "" +"Lifetimes for function arguments and return values must be fully specified, " +"but Rust allows lifetimes to be elided in most cases with [a few simple " +"rules](https://doc.rust-lang.org/nomicon/lifetime-elision.html). This is not " +"inference -- it is just a syntactic shorthand." +msgstr "" + +#: src/lifetimes/lifetime-elision.md +msgid "Each argument which does not have a lifetime annotation is given one." +msgstr "" + +#: src/lifetimes/lifetime-elision.md +msgid "" +"If there is only one argument lifetime, it is given to all un-annotated " +"return values." +msgstr "" + +#: src/lifetimes/lifetime-elision.md +msgid "" +"If there are multiple argument lifetimes, but the first one is for `self`, " +"that lifetime is given to all un-annotated return values." +msgstr "" + +#: src/lifetimes/lifetime-elision.md +msgid "" +"Walk through applying the lifetime elision rules to each of the example " +"functions. `only_args` is completed by the first rule, `identity` is " +"completed by the second, and `Foo::get` is completed by the third." +msgstr "" + +#: src/lifetimes/lifetime-elision.md +msgid "" +"If all lifetimes have not been filled in by applying the three elision rules " +"then you will get a compiler error telling you to add annotations manually." +msgstr "" + +#: src/lifetimes/struct-lifetimes.md +msgid "" +"If a data type stores borrowed data, it must be annotated with a lifetime:" +msgstr "" + +#: src/lifetimes/struct-lifetimes.md +msgid "\"The quick brown fox jumps over the lazy dog.\"" +msgstr "" + +#: src/lifetimes/struct-lifetimes.md +msgid "// drop(doc);\n" +msgstr "" + +#: src/lifetimes/struct-lifetimes.md +msgid "" +"In the above example, the annotation on `Highlight` enforces that the data " +"underlying the contained `&str` lives at least as long as any instance of " +"`Highlight` that uses that data. A struct cannot live longer than the data " +"it references." +msgstr "" + +#: src/lifetimes/struct-lifetimes.md +msgid "" +"If `doc` is dropped before the end of the lifetime of `noun` or `verb`, the " +"borrow checker throws an error." +msgstr "" + +#: src/lifetimes/struct-lifetimes.md +msgid "" +"Types with borrowed data force users to hold on to the original data. This " +"can be useful for creating lightweight views, but it generally makes them " +"somewhat harder to use." +msgstr "" + +#: src/lifetimes/struct-lifetimes.md +msgid "When possible, make data structures own their data directly." +msgstr "" + +#: src/lifetimes/struct-lifetimes.md +msgid "" +"Some structs with multiple references inside can have more than one lifetime " +"annotation. This can be necessary if there is a need to describe lifetime " +"relationships between the references themselves, in addition to the lifetime " +"of the struct itself. Those are very advanced use cases." +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"In this exercise, you will build a parser for the [protobuf binary encoding]" +"(https://protobuf.dev/programming-guides/encoding/). Don't worry, it's " +"simpler than it seems! This illustrates a common parsing pattern, passing " +"slices of data. The underlying data itself is never copied." +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"Fully parsing a protobuf message requires knowing the types of the fields, " +"indexed by their field numbers. That is typically provided in a `proto` " +"file. In this exercise, we'll encode that information into `match` " +"statements in functions that get called for each field." +msgstr "" + +#: src/lifetimes/exercise.md +msgid "We'll use the following proto:" +msgstr "" + +#: src/lifetimes/exercise.md +msgid "Messages" +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"A proto message is encoded as a series of fields, one after the next. Each " +"is implemented as a \"tag\" followed by the value. The tag contains a field " +"number (e.g., `2` for the `id` field of a `Person` message) and a wire type " +"defining how the payload should be determined from the byte stream. These " +"are combined into a single integer, as decoded in `unpack_tag` below." +msgstr "" + +#: src/lifetimes/exercise.md +msgid "Varint" +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"Integers, including the tag, are represented with a variable-length encoding " +"called VARINT. Luckily, `parse_varint` is defined for you below." +msgstr "" + +#: src/lifetimes/exercise.md +msgid "Wire Types" +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"Proto defines several wire types, only two of which are used in this " +"exercise." +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"The `Varint` wire type contains a single varint, and is used to encode proto " +"values of type `int32` such as `Person.id`." +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"The `Len` wire type contains a length expressed as a varint, followed by a " +"payload of that number of bytes. This is used to encode proto values of type " +"`string` such as `Person.name`. It is also used to encode proto values " +"containing sub-messages such as `Person.phones`, where the payload contains " +"an encoding of the sub-message." +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"The given code also defines callbacks to handle `Person` and `PhoneNumber` " +"fields, and to parse a message into a series of calls to those callbacks." +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"What remains for you is to implement the `parse_field` function and the " +"`ProtoMessage` trait for `Person` and `PhoneNumber`." +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "/// A wire type as seen on the wire.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "/// The Varint WireType indicates the value is a single VARINT.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "" +"// The I64 WireType indicates that the value is precisely 8 bytes in\n" +" // little-endian order containing a 64-bit signed integer or double " +"type.\n" +" //I64, -- not needed for this exercise\n" +" /// The Len WireType indicates that the value is a length represented as " +"a\n" +" /// VARINT followed by exactly that number of bytes.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "" +"// The I32 WireType indicates that the value is precisely 4 bytes in\n" +" // little-endian order containing a 32-bit signed integer or float " +"type.\n" +" //I32, -- not needed for this exercise\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "/// A field's value, typed based on the wire type.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "//I64(i64), -- not needed for this exercise\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "//I32(i32), -- not needed for this exercise\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "/// A field, containing the field number and its value.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "//1 => WireType::I64, -- not needed for this exercise\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "//5 => WireType::I32, -- not needed for this exercise\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"Invalid wire type: {value}\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"Expected string to be a `Len` field\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"Invalid string\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"Expected bytes to be a `Len` field\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"Expected `u64` to be a `Varint` field\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "" +"/// Parse a VARINT, returning the parsed value and the remaining bytes.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"Not enough bytes for varint\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "" +"// This is the last byte of the VARINT, so convert it to\n" +" // a u64 and return it.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "// More than 7 bytes is invalid.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"Too many bytes for varint\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "/// Convert a tag into a field number and a WireType.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "/// Parse a field, returning the remaining bytes\n" +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"\"Based on the wire type, build a Field, consuming as many bytes as " +"necessary.\"" +msgstr "" + +#: src/lifetimes/exercise.md +msgid "\"Return the field, and any un-consumed bytes.\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "" +"/// Parse a message in the given data, calling `T::add_field` for each field " +"in\n" +"/// the message.\n" +"///\n" +"/// The entire input is consumed.\n" +msgstr "" + +#: src/lifetimes/exercise.md +msgid "// TODO: Implement ProtoMessage for Person and PhoneNumber.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md src/modules/exercise.md +#: src/modules/solution.md src/testing/unit-tests.md src/testing/solution.md +msgid "\"\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"beautiful name\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"Evan\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"+1234-777-9090\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"home\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "// Put that all together into a single parse.\n" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"maxwell\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"+1202-555-1212\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"+1800-867-5308\"" +msgstr "" + +#: src/lifetimes/exercise.md src/lifetimes/solution.md +msgid "\"mobile\"" +msgstr "" + +#: src/lifetimes/exercise.md +msgid "" +"In this exercise there are various cases where protobuf parsing might fail, " +"e.g. if you try to parse an `i32` when there are fewer than 4 bytes left in " +"the data buffer. In normal Rust code we'd handle this with the `Result` " +"enum, but for simplicity in this exercise we panic if any errors are " +"encountered. On day 4 we'll cover error handling in Rust in more detail." +msgstr "" + +#: src/lifetimes/solution.md +msgid "// cast for simplicity\n" +msgstr "" + +#: src/lifetimes/solution.md +msgid "// skip everything else\n" +msgstr "" + +#: src/welcome-day-4.md +msgid "Welcome to Day 4" +msgstr "" + +#: src/welcome-day-4.md +msgid "We have mastered the core language and its unique safety model:" +msgstr "" + +#: src/welcome-day-4.md +msgid "" +"**Foundations & Abstraction:** Traits, generics, and the standard library." +msgstr "" + +#: src/welcome-day-4.md +msgid "**Ownership:** Move semantics and the `Drop` trait." +msgstr "" + +#: src/welcome-day-4.md +msgid "**Memory Management:** Borrowing rules (`&` vs `&mut`) and lifetimes." +msgstr "" + +#: src/welcome-day-4.md +msgid "" +"**Smart Pointers:** `Box`, `Rc`, and `RefCell` for complex data structures." +msgstr "" + +#: src/welcome-day-4.md +msgid "" +"You now understand how Rust guarantees memory safety at compile time! Today " +"we focus on applying this knowledge to build robust, large-scale " +"applications." +msgstr "" + +#: src/iterators.md +msgid "Iterator Trait" +msgstr "" + +#: src/iterators.md +msgid "Iterator Helper Methods" +msgstr "" + +#: src/iterators.md +msgid "collect" +msgstr "" + +#: src/iterators.md +msgid "IntoIterator" +msgstr "" + +#: src/iterators/motivation.md +msgid "Motivating Iterators" +msgstr "" + +#: src/iterators/motivation.md +msgid "" +"If you want to iterate over the contents of an array, you'll need to define:" +msgstr "" + +#: src/iterators/motivation.md +msgid "" +"Some state to keep track of where you are in the iteration process, e.g. an " +"index." +msgstr "" + +#: src/iterators/motivation.md +msgid "A condition to determine when iteration is done." +msgstr "" + +#: src/iterators/motivation.md +msgid "Logic for updating the state of iteration each loop." +msgstr "" + +#: src/iterators/motivation.md +msgid "Logic for fetching each element using that iteration state." +msgstr "" + +#: src/iterators/motivation.md +msgid "In a C-style for loop you declare these things directly:" +msgstr "" + +#: src/iterators/motivation.md +msgid "" +"In Rust we bundle this state and logic together into an object known as an " +"\"iterator\"." +msgstr "" + +#: src/iterators/motivation.md +msgid "" +"This slide provides context for what Rust iterators do under the hood. We " +"use the (hopefully) familiar construct of a C-style `for` loop to show how " +"iteration requires some state and some logic, that way on the next slide we " +"can show how an iterator bundles these together." +msgstr "" + +#: src/iterators/motivation.md +msgid "" +"Rust doesn't have a C-style `for` loop, but we can express the same thing " +"with `while`:" +msgstr "" + +#: src/iterators/motivation.md +msgid "" +"There's another way to express array iteration using `for` in C and C++: You " +"can use a pointer to the front and a pointer to the end of the array and " +"then compare those pointers to determine when the loop should end." +msgstr "" + +#: src/iterators/motivation.md +msgid "" +"If students ask, you can point out that this is how Rust's slice and array " +"iterators work under the hood (though implemented as a Rust iterator)." +msgstr "" + +#: src/iterators/iterator.md +msgid "" +"The [`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) " +"trait defines how an object can be used to produce a sequence of values. For " +"example, if we wanted to create an iterator that can produce the elements of " +"a slice it might look something like this:" +msgstr "" + +#: src/iterators/iterator.md +msgid "" +"The `SliceIter` example implements the same logic as the C-style `for` loop " +"demonstrated on the last slide." +msgstr "" + +#: src/iterators/iterator.md +msgid "" +"Point out to the students that iterators are lazy: Creating the iterator " +"just initializes the struct but does not otherwise do any work. No work " +"happens until the `next` method is called." +msgstr "" + +#: src/iterators/iterator.md +msgid "" +"Iterators don't need to be finite! It's entirely valid to have an iterator " +"that will produce values forever. For example, a half open range like `0..` " +"will keep going until integer overflow occurs." +msgstr "" + +#: src/iterators/iterator.md +msgid "" +"The \"real\" version of `SliceIter` is the [`slice::Iter`](https://doc.rust-" +"lang.org/stable/std/slice/struct.Iter.html) type in the standard library, " +"however the real version uses pointers under the hood instead of an index in " +"order to eliminate bounds checks." +msgstr "" + +#: src/iterators/iterator.md +msgid "" +"The `SliceIter` example is a good example of a struct that contains a " +"reference and therefore uses lifetime annotations." +msgstr "" + +#: src/iterators/iterator.md +msgid "" +"You can also demonstrate adding a generic parameter to `SliceIter` to allow " +"it to work with any kind of slice (not just `&[i32]`)." +msgstr "" + +#: src/iterators/helpers.md +msgid "" +"In addition to the `next` method that defines how an iterator behaves, the " +"`Iterator` trait provides 70+ helper methods that can be used to build " +"customized iterators." +msgstr "" + +#: src/iterators/helpers.md +msgid "// Create a range from 1 to 10\n" +msgstr "" + +#: src/iterators/helpers.md +msgid "// Keep only even numbers\n" +msgstr "" + +#: src/iterators/helpers.md +msgid "// Square each number\n" +msgstr "" + +#: src/iterators/helpers.md +msgid "// Sum up all the squared numbers\n" +msgstr "" + +#: src/iterators/helpers.md +msgid "\"The sum of squares of even numbers from 1 to 10 is: {}\"" +msgstr "" + +#: src/iterators/helpers.md +msgid "" +"The `Iterator` trait implements many common functional programming " +"operations over collections (e.g. `map`, `filter`, `reduce`, etc). This is " +"the trait where you can find all the documentation about them." +msgstr "" + +#: src/iterators/helpers.md +msgid "" +"Many of these helper methods take the original iterator and produce a new " +"iterator with different behavior. These are know as \"iterator adapter " +"methods\"." +msgstr "" + +#: src/iterators/helpers.md +msgid "" +"Some methods, like `sum` and `count`, consume the iterator and pull all of " +"the elements out of it." +msgstr "" + +#: src/iterators/helpers.md +msgid "" +"These methods are designed to be chained together so that it's easy to build " +"a custom iterator that does exactly what you need." +msgstr "" + +#: src/iterators/helpers.md +msgid "" +"Rust's iterators are extremely efficient and highly optimizable. Even " +"complex iterators made by combining many adapter methods will still result " +"in code as efficient as equivalent imperative implementations." +msgstr "" + +#: src/iterators/collect.md +msgid "" +"The [`collect`](https://doc.rust-lang.org/std/iter/trait.Iterator." +"html#method.collect) method lets you build a collection from an [`Iterator`]" +"(https://doc.rust-lang.org/std/iter/trait.Iterator.html)." +msgstr "" + +#: src/iterators/collect.md +msgid "\"prime_squares: {prime_squares:?}\"" +msgstr "" + +#: src/iterators/collect.md +msgid "" +"Any iterator can be collected in to a `Vec`, `VecDeque`, or `HashSet`. " +"Iterators that produce key-value pairs (i.e. a two-element tuple) can also " +"be collected into `HashMap` and `BTreeMap`." +msgstr "" + +#: src/iterators/collect.md +msgid "" +"Show the students the definition for `collect` in the standard library docs. " +"There are two ways to specify the generic type `B` for this method:" +msgstr "" + +#: src/iterators/collect.md +msgid "" +"With the \"turbofish\": `some_iterator.collect::()`, as " +"shown. The `_` shorthand used here lets Rust infer the type of the `Vec` " +"elements." +msgstr "" + +#: src/iterators/collect.md +msgid "" +"With type inference: `let prime_squares: Vec<_> = some_iterator.collect()`. " +"Rewrite the example to use this form." +msgstr "" + +#: src/iterators/collect.md +msgid "" +"If students are curious about how this works, you can bring up the " +"[`FromIterator`](https://doc.rust-lang.org/std/iter/trait.FromIterator.html) " +"trait, which defines how each type of collection gets built from an iterator." +msgstr "" + +#: src/iterators/collect.md +msgid "" +"In addition to the basic implementations of `FromIterator` for `Vec`, " +"`HashMap`, etc., there are also more specialized implementations which let " +"you do cool things like convert an `Iterator>` into a " +"`Result, E>`." +msgstr "" + +#: src/iterators/collect.md +msgid "" +"The reason type annotations are often needed with `collect` is because it's " +"generic over its return type. This makes it harder for the compiler to infer " +"the correct type in many cases." +msgstr "" + +#: src/iterators/intoiterator.md +msgid "" +"The `Iterator` trait tells you how to _iterate_ once you have created an " +"iterator. The related trait [`IntoIterator`](https://doc.rust-lang.org/std/" +"iter/trait.IntoIterator.html) defines how to create an iterator for a type. " +"It is used automatically by the `for` loop." +msgstr "" + +#: src/iterators/intoiterator.md +msgid "\"point = {x}, {y}\"" +msgstr "" + +#: src/iterators/intoiterator.md +msgid "" +"`IntoIterator` is the trait that makes for loops work. It is implemented by " +"collection types such as `Vec` and references to them such as `&Vec` " +"and `&[T]`. Ranges also implement it. This is why you can iterate over a " +"vector with `for i in some_vec { .. }` but `some_vec.next()` doesn't exist." +msgstr "" + +#: src/iterators/intoiterator.md +msgid "" +"Click through to the docs for `IntoIterator`. Every implementation of " +"`IntoIterator` must declare two types:" +msgstr "" + +#: src/iterators/intoiterator.md +msgid "`Item`: the type to iterate over, such as `i8`," +msgstr "" + +#: src/iterators/intoiterator.md +msgid "`IntoIter`: the `Iterator` type returned by the `into_iter` method." +msgstr "" + +#: src/iterators/intoiterator.md +msgid "" +"Note that `IntoIter` and `Item` are linked: the iterator must have the same " +"`Item` type, which means that it returns `Option`" +msgstr "" + +#: src/iterators/intoiterator.md +msgid "The example iterates over all combinations of x and y coordinates." +msgstr "" + +#: src/iterators/intoiterator.md +msgid "" +"Try iterating over the grid twice in `main`. Why does this fail? Note that " +"`IntoIterator::into_iter` takes ownership of `self`." +msgstr "" + +#: src/iterators/intoiterator.md +msgid "" +"Fix this issue by implementing `IntoIterator` for `&Grid` and creating a " +"`GridRefIter` that iterates by reference. A version with both `GridIter` and " +"`GridRefIter` is available [in this playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2024&gist=947e371c7295af758504f01f149023a1)." +msgstr "" + +#: src/iterators/intoiterator.md +msgid "" +"The same problem can occur for standard library types: `for e in " +"some_vector` will take ownership of `some_vector` and iterate over owned " +"elements from that vector. Use `for e in &some_vector` instead, to iterate " +"over references to elements of `some_vector`." +msgstr "" + +#: src/iterators/exercise.md +msgid "" +"In this exercise, you will need to find and use some of the provided methods " +"in the [`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) " +"trait to implement a complex calculation." +msgstr "" + +#: src/iterators/exercise.md +msgid "" +"Copy the following code to and make the tests " +"pass. Use an iterator expression and `collect` the result to construct the " +"return value." +msgstr "" + +#: src/iterators/exercise.md src/iterators/solution.md +msgid "" +"/// Calculate the differences between elements of `values` offset by " +"`offset`,\n" +"/// wrapping around from the end of `values` to the beginning.\n" +"///\n" +"/// Element `n` of the result is `values[(n+offset)%len] - values[n]`.\n" +msgstr "" + +#: src/modules.md src/modules/paths.md +msgid "use, super, self" +msgstr "" + +#: src/modules/modules.md +msgid "We have seen how `impl` blocks let us namespace functions to a type." +msgstr "" + +#: src/modules/modules.md +msgid "Similarly, `mod` lets us namespace types and functions:" +msgstr "" + +#: src/modules/modules.md +msgid "\"In the foo module\"" +msgstr "" + +#: src/modules/modules.md +msgid "\"In the bar module\"" +msgstr "" + +#: src/modules/modules.md +msgid "" +"Packages provide functionality and include a `Cargo.toml` file that " +"describes how to build a bundle of 1+ crates." +msgstr "" + +#: src/modules/modules.md +msgid "" +"Crates are a tree of modules, where a binary crate creates an executable and " +"a library crate compiles to a library." +msgstr "" + +#: src/modules/modules.md +msgid "Modules define organization, scope, and are the focus of this section." +msgstr "" + +#: src/modules/filesystem.md +msgid "" +"Omitting the module content will tell Rust to look for it in another file:" +msgstr "" + +#: src/modules/filesystem.md +msgid "" +"This tells Rust that the `garden` module content is found at `src/garden." +"rs`. Similarly, a `garden::vegetables` module can be found at `src/garden/" +"vegetables.rs`." +msgstr "" + +#: src/modules/filesystem.md +msgid "The `crate` root is in:" +msgstr "" + +#: src/modules/filesystem.md +msgid "`src/lib.rs` (for a library crate)" +msgstr "" + +#: src/modules/filesystem.md +msgid "`src/main.rs` (for a binary crate)" +msgstr "" + +#: src/modules/filesystem.md +msgid "" +"Modules defined in files can be documented, too, using \"inner doc " +"comments\". These document the item that contains them -- in this case, a " +"module." +msgstr "" + +#: src/modules/filesystem.md +msgid "" +"//! This module implements the garden, including a highly performant " +"germination\n" +"//! implementation.\n" +msgstr "" + +#: src/modules/filesystem.md +msgid "// Re-export types from this module.\n" +msgstr "" + +#: src/modules/filesystem.md +msgid "/// Sow the given seed packets.\n" +msgstr "" + +#: src/modules/filesystem.md +msgid "/// Harvest the produce in the garden that is ready.\n" +msgstr "" + +#: src/modules/filesystem.md +msgid "" +"Before Rust 2018, modules needed to be located at `module/mod.rs` instead of " +"`module.rs`, and this is still a working alternative for editions after 2018." +msgstr "" + +#: src/modules/filesystem.md +msgid "" +"The main reason to introduce `filename.rs` as alternative to `filename/mod." +"rs` was because many files named `mod.rs` can be hard to distinguish in IDEs." +msgstr "" + +#: src/modules/filesystem.md +msgid "Deeper nesting can use folders, even if the main module is a file:" +msgstr "" + +#: src/modules/filesystem.md +msgid "" +"The place Rust will look for modules can be changed with a compiler " +"directive:" +msgstr "" + +#: src/modules/filesystem.md +msgid "\"some/path.rs\"" +msgstr "" + +#: src/modules/filesystem.md +msgid "" +"This is useful, for example, if you would like to place tests for a module " +"in a file named `some_module_test.rs`, similar to the convention in Go." +msgstr "" + +#: src/modules/visibility.md +msgid "Modules are a privacy boundary:" +msgstr "" + +#: src/modules/visibility.md +msgid "Module items are private by default (hides implementation details)." +msgstr "" + +#: src/modules/visibility.md +msgid "Parent and sibling items are always visible." +msgstr "" + +#: src/modules/visibility.md +msgid "" +"In other words, if an item is visible in module `foo`, it's visible in all " +"the descendants of `foo`." +msgstr "" + +#: src/modules/visibility.md +msgid "\"outer::private\"" +msgstr "" + +#: src/modules/visibility.md +msgid "\"outer::public\"" +msgstr "" + +#: src/modules/visibility.md +msgid "\"outer::inner::private\"" +msgstr "" + +#: src/modules/visibility.md +msgid "\"outer::inner::public\"" +msgstr "" + +#: src/modules/visibility.md +msgid "Use the `pub` keyword to make modules public." +msgstr "" + +#: src/modules/visibility.md +msgid "" +"Additionally, there are advanced `pub(...)` specifiers to restrict the scope " +"of public visibility." +msgstr "" + +#: src/modules/visibility.md +msgid "" +"See the [Rust Reference](https://doc.rust-lang.org/reference/visibility-and-" +"privacy.html#pubin-path-pubcrate-pubsuper-and-pubself)." +msgstr "" + +#: src/modules/visibility.md +msgid "Configuring `pub(crate)` visibility is a common pattern." +msgstr "" + +#: src/modules/visibility.md +msgid "Less commonly, you can give visibility to a specific path." +msgstr "" + +#: src/modules/visibility.md +msgid "" +"In any case, visibility must be granted to an ancestor module (and all of " +"its descendants)." +msgstr "" + +#: src/modules/encapsulation.md +msgid "Visibility and Encapsulation" +msgstr "" + +#: src/modules/encapsulation.md +msgid "" +"Like with items in a module, struct fields are also private by default. " +"Private fields are likewise visible within the rest of the module (including " +"child modules). This allows us to encapsulate implementation details of " +"struct, controlling what data and functionality is visible externally." +msgstr "" + +#: src/modules/encapsulation.md +msgid "\"Is {} big? {}\"" +msgstr "" + +#: src/modules/encapsulation.md +msgid "\"foo.val = {}\"" +msgstr "" + +#: src/modules/encapsulation.md +msgid "// let foo = Foo { val: 42, is_big: true };\n" +msgstr "" + +#: src/modules/encapsulation.md +msgid "// println!(\"Is {} big? {}\", foo.val, foo.is_big);\n" +msgstr "" + +#: src/modules/encapsulation.md +msgid "" +"This slide demonstrates how privacy in structs is module-based. Students " +"coming from object-oriented languages may be used to types being the " +"encapsulation boundary, so this demonstrates how Rust behaves differently " +"while showing how we can still achieve encapsulation." +msgstr "" + +#: src/modules/encapsulation.md +msgid "" +"Note how the `is_big` field is fully controlled by `Foo`, allowing `Foo` to " +"control how it's initialized and enforce any invariants it needs to (e.g. " +"that `is_big` is only `true` if `val > 100`)." +msgstr "" + +#: src/modules/encapsulation.md +msgid "" +"Point out how helper functions can be defined in the same module (including " +"child modules) in order to get access to the type's private fields/methods." +msgstr "" + +#: src/modules/encapsulation.md +msgid "" +"The first commented out line demonstrates that you cannot initialize a " +"struct with private fields. The second one demonstrates that you also can't " +"directly access private fields." +msgstr "" + +#: src/modules/encapsulation.md +msgid "" +"Enums do not support privacy: Variants and data within those variants is " +"always public." +msgstr "" + +#: src/modules/encapsulation.md +msgid "" +"If students want more information about privacy (or lack thereof) in enums, " +"you can bring up `#[doc_hidden]` and `#[non_exhaustive]` and show how " +"they're used to limit what can be done with an enum." +msgstr "" + +#: src/modules/encapsulation.md +msgid "" +"Module privacy still applies when there are `impl` blocks in other modules " +"[(example in the playground)](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2024&gist=3e61f43c88de12bcdf69c1d6df9ab3da)." +msgstr "" + +#: src/modules/paths.md +msgid "" +"A module can bring symbols from another module into scope with `use`. You " +"will typically see something like this at the top of each module:" +msgstr "" + +#: src/modules/paths.md +msgid "Paths" +msgstr "" + +#: src/modules/paths.md +msgid "Paths are resolved as follows:" +msgstr "" + +#: src/modules/paths.md +msgid "As a relative path:" +msgstr "" + +#: src/modules/paths.md +msgid "`foo` or `self::foo` refers to `foo` in the current module," +msgstr "" + +#: src/modules/paths.md +msgid "`super::foo` refers to `foo` in the parent module." +msgstr "" + +#: src/modules/paths.md +msgid "As an absolute path:" +msgstr "" + +#: src/modules/paths.md +msgid "`crate::foo` refers to `foo` in the root of the current crate," +msgstr "" + +#: src/modules/paths.md +msgid "`bar::foo` refers to `foo` in the `bar` crate." +msgstr "" + +#: src/modules/paths.md +msgid "" +"It is common to \"re-export\" symbols at a shorter path. For example, the " +"top-level `lib.rs` in a crate might have" +msgstr "" + +#: src/modules/paths.md +msgid "" +"making `DiskStorage` and `NetworkStorage` available to other crates with a " +"convenient, short path." +msgstr "" + +#: src/modules/paths.md +msgid "" +"For the most part, only items that appear in a module need to be `use`'d. " +"However, a trait must be in scope to call any methods on that trait, even if " +"a type implementing that trait is already in scope. For example, to use the " +"`read_to_string` method on a type implementing the `Read` trait, you need to " +"`use std::io::Read`." +msgstr "" + +#: src/modules/paths.md +msgid "" +"The `use` statement can have a wildcard: `use std::io::*`. This is " +"discouraged because it is not clear which items are imported, and those " +"might change over time." +msgstr "" + +#: src/modules/exercise.md +msgid "" +"In this exercise, you will reorganize a small GUI Library implementation. " +"This library defines a `Widget` trait and a few implementations of that " +"trait, as well as a `main` function." +msgstr "" + +#: src/modules/exercise.md +msgid "" +"It is typical to put each type or set of closely-related types into its own " +"module, so each widget type should get its own module." +msgstr "" + +#: src/modules/exercise.md +msgid "Cargo Setup" +msgstr "" + +#: src/modules/exercise.md +msgid "" +"The Rust playground only supports one file, so you will need to make a Cargo " +"project on your local filesystem:" +msgstr "" + +#: src/modules/exercise.md +msgid "" +"Edit the resulting `src/main.rs` to add `mod` statements, and add additional " +"files in the `src` directory." +msgstr "" + +#: src/modules/exercise.md +msgid "Source" +msgstr "" + +#: src/modules/exercise.md +msgid "Here's the single-module implementation of the GUI library:" +msgstr "" + +#: src/modules/exercise.md src/modules/solution.md +msgid "/// Natural width of `self`.\n" +msgstr "" + +#: src/modules/exercise.md src/modules/solution.md +msgid "/// Draw the widget into a buffer.\n" +msgstr "" + +#: src/modules/exercise.md src/modules/solution.md +msgid "/// Draw the widget on standard output.\n" +msgstr "" + +#: src/modules/exercise.md src/modules/solution.md +msgid "\"{buffer}\"" +msgstr "" + +#: src/modules/exercise.md +msgid "// Add 4 paddings for borders\n" +msgstr "" + +#: src/modules/exercise.md +msgid "" +"// TODO: Change draw_into to return Result<(), std::fmt::Error>. Then use " +"the\n" +" // ?-operator here instead of .unwrap().\n" +msgstr "" + +#: src/modules/exercise.md src/modules/solution.md +msgid "\"+-{:-. Then use\n" +" // the ?-operator here instead of .unwrap().\n" +msgstr "" + +#: src/modules/solution.md +msgid "// ---- src/main.rs ----\n" +msgstr "" + +#: src/testing/unit-tests.md +msgid "" +"Rust and Cargo come with a simple unit test framework. Tests are marked with " +"`#[test]`. Unit tests are often put in a nested `tests` module, using " +"`#[cfg(test)]` to conditionally compile them only when building tests." +msgstr "" + +#: src/testing/unit-tests.md +msgid "\"Hello World\"" +msgstr "" + +#: src/testing/unit-tests.md +msgid "This lets you unit test private helpers." +msgstr "" + +#: src/testing/unit-tests.md +msgid "The `#[cfg(test)]` attribute is only active when you run `cargo test`." +msgstr "" + +#: src/testing/other.md +msgid "Integration Tests" +msgstr "" + +#: src/testing/other.md +msgid "If you want to test your library as a client, use an integration test." +msgstr "" + +#: src/testing/other.md +msgid "Create a `.rs` file under `tests/`:" +msgstr "" + +#: src/testing/other.md +msgid "// tests/my_library.rs\n" +msgstr "" + +#: src/testing/other.md +msgid "These tests only have access to the public API of your crate." +msgstr "" + +#: src/testing/other.md +msgid "Documentation Tests" +msgstr "" + +#: src/testing/other.md +msgid "Rust has built-in support for documentation tests:" +msgstr "" + +#: src/testing/other.md +msgid "" +"/// Shortens a string to the given length.\n" +"///\n" +"/// ```\n" +"/// # use playground::shorten_string;\n" +"/// assert_eq!(shorten_string(\"Hello World\", 5), \"Hello\");\n" +"/// assert_eq!(shorten_string(\"Hello World\", 20), \"Hello World\");\n" +"/// ```\n" +msgstr "" + +#: src/testing/other.md +msgid "Code blocks in `///` comments are automatically seen as Rust code." +msgstr "" + +#: src/testing/other.md +msgid "The code will be compiled and executed as part of `cargo test`." +msgstr "" + +#: src/testing/other.md +msgid "" +"Adding `#` in the code will hide it from the docs, but will still compile/" +"run it." +msgstr "" + +#: src/testing/other.md +msgid "" +"Test the above code on the [Rust Playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2024&gist=3ce2ad13ea1302f6572cb15cd96becf0)." +msgstr "" + +#: src/testing/lints.md +msgid "" +"The Rust compiler produces fantastic error messages, as well as helpful " +"built-in lints. [Clippy](https://doc.rust-lang.org/clippy/) provides even " +"more lints, organized into groups that can be enabled per-project." +msgstr "" + +#: src/testing/lints.md +msgid "\"X probably fits in a u16, right? {}\"" +msgstr "" + +#: src/testing/lints.md +msgid "" +"There are compiler lints visible here, but not clippy lints. Run `clippy` on " +"the playground site to show clippy warnings. Clippy has extensive " +"documentation of its lints, and adds new lints (including default-deny " +"lints) all the time." +msgstr "" + +#: src/testing/lints.md +msgid "" +"Note that errors or warnings with `help: ...` can be fixed with `cargo fix` " +"or via your editor." +msgstr "" + +#: src/testing/exercise.md +msgid "" +"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used " +"to validate credit card numbers. The algorithm takes a string as input and " +"does the following to validate the credit card number:" +msgstr "" + +#: src/testing/exercise.md +msgid "" +"Ignore all spaces. Reject numbers with fewer than two digits. Reject letters " +"and other non-digit characters." +msgstr "" + +#: src/testing/exercise.md +msgid "" +"Moving from **right to left**, double every second digit: for the number " +"`1234`, we double `3` and `1`. For the number `98765`, we double `6` and `8`." +msgstr "" + +#: src/testing/exercise.md +msgid "" +"After doubling a digit, sum the digits if the result is greater than 9. So " +"doubling `7` becomes `14` which becomes `1 + 4 = 5`." +msgstr "" + +#: src/testing/exercise.md +msgid "Sum all the undoubled and doubled digits." +msgstr "" + +#: src/testing/exercise.md +msgid "The credit card number is valid if the sum ends with `0`." +msgstr "" + +#: src/testing/exercise.md +msgid "" +"The provided code provides a buggy implementation of the Luhn algorithm, " +"along with two basic unit tests that confirm that most of the algorithm is " +"implemented correctly." +msgstr "" + +#: src/testing/exercise.md +msgid "" +"Copy the code below to and write additional " +"tests to uncover bugs in the provided implementation, fixing any bugs you " +"find." +msgstr "" + +#: src/testing/exercise.md src/testing/solution.md +msgid "\"4263 9826 4026 9299\"" +msgstr "" + +#: src/testing/exercise.md src/testing/solution.md +msgid "\"4539 3195 0343 6467\"" +msgstr "" + +#: src/testing/exercise.md src/testing/solution.md +msgid "\"7992 7398 713\"" +msgstr "" + +#: src/testing/exercise.md src/testing/solution.md +msgid "\"4223 9826 4026 9299\"" +msgstr "" + +#: src/testing/exercise.md src/testing/solution.md +msgid "\"4539 3195 0343 6476\"" +msgstr "" + +#: src/testing/exercise.md src/testing/solution.md +msgid "\"8273 1232 7352 0569\"" +msgstr "" + +#: src/testing/solution.md +msgid "// New: accept whitespace.\n" +msgstr "" + +#: src/testing/solution.md +msgid "// New: reject all other characters.\n" +msgstr "" + +#: src/testing/solution.md +msgid "// New: check that we have at least two digits\n" +msgstr "" + +#: src/testing/solution.md +msgid "\"foo 0 0\"" +msgstr "" + +#: src/testing/solution.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md +msgid "\" \"" +msgstr "" + +#: src/testing/solution.md +msgid "\" \"" +msgstr "" + +#: src/testing/solution.md +msgid "\" \"" +msgstr "" + +#: src/testing/solution.md +msgid "\"0\"" +msgstr "" + +#: src/testing/solution.md +msgid "\" 0 0 \"" +msgstr "" + +#: src/error-handling.md +msgid "Error Trait" +msgstr "" + +#: src/error-handling.md +msgid "thiserror" +msgstr "" + +#: src/error-handling.md +msgid "anyhow" +msgstr "" + +#: src/error-handling.md src/error-handling/exercise.md +msgid "Exercise: Rewriting with Result" +msgstr "" + +#: src/error-handling/panics.md +msgid "In case of a fatal runtime error, Rust triggers a \"panic\":" +msgstr "" + +#: src/error-handling/panics.md +msgid "Panics are for unrecoverable and unexpected errors." +msgstr "" + +#: src/error-handling/panics.md +msgid "Panics are symptoms of bugs in the program." +msgstr "" + +#: src/error-handling/panics.md +msgid "Runtime failures like failed bounds checks can panic." +msgstr "" + +#: src/error-handling/panics.md +msgid "Assertions (such as `assert!`) panic on failure." +msgstr "" + +#: src/error-handling/panics.md +msgid "Purpose-specific panics can use the `panic!` macro." +msgstr "" + +#: src/error-handling/panics.md +msgid "" +"A panic will \"unwind\" the stack, dropping values just as if the functions " +"had returned." +msgstr "" + +#: src/error-handling/panics.md +msgid "" +"Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." +msgstr "" + +#: src/error-handling/panics.md +msgid "" +"By default, a panic will cause the stack to unwind. The unwinding can be " +"caught:" +msgstr "" + +#: src/error-handling/panics.md +msgid "\"No problem here!\"" +msgstr "" + +#: src/error-handling/panics.md +msgid "\"oh no!\"" +msgstr "" + +#: src/error-handling/panics.md +msgid "" +"Catching is unusual; do not attempt to implement exceptions with " +"`catch_unwind`!" +msgstr "" + +#: src/error-handling/panics.md +msgid "" +"This can be useful in servers which should keep running even if a single " +"request crashes." +msgstr "" + +#: src/error-handling/panics.md +msgid "This does not work if `panic = 'abort'` is set in your `Cargo.toml`." +msgstr "" + +#: src/error-handling/result.md +msgid "" +"Our primary mechanism for error handling in Rust is the [`Result`](https://" +"doc.rust-lang.org/stable/std/result/enum.Result.html) enum, which we briefly " +"saw when discussing standard library types." +msgstr "" + +#: src/error-handling/result.md +msgid "" +"`Result` has two variants: `Ok` which contains the success value, and `Err` " +"which contains an error value of some kind." +msgstr "" + +#: src/error-handling/result.md +msgid "" +"Whether or not a function can produce an error is encoded in the function's " +"type signature by having the function return a `Result` value." +msgstr "" + +#: src/error-handling/result.md +msgid "" +"Like with `Option`, there is no way to forget to handle an error: You cannot " +"access either the success value or the error value without first pattern " +"matching on the `Result` to check which variant you have. Methods like " +"`unwrap` make it easier to write quick-and-dirty code that doesn't do robust " +"error handling, but means that you can always see in your source code where " +"proper error handling is being skipped." +msgstr "" + +#: src/error-handling/result.md +msgid "" +"It may be helpful to compare error handling in Rust to error handling " +"conventions that students may be familiar with from other programming " +"languages." +msgstr "" + +#: src/error-handling/result.md +msgid "Many languages use exceptions, e.g. C++, Java, Python." +msgstr "" + +#: src/error-handling/result.md +msgid "" +"In most languages with exceptions, whether or not a function can throw an " +"exception is not visible as part of its type signature. This generally means " +"that you can't tell when calling a function if it may throw an exception or " +"not." +msgstr "" + +#: src/error-handling/result.md +msgid "" +"Exceptions generally unwind the call stack, propagating upward until a `try` " +"block is reached. An error originating deep in the call stack may impact an " +"unrelated function further up." +msgstr "" + +#: src/error-handling/result.md +msgid "Error Numbers" +msgstr "" + +#: src/error-handling/result.md +msgid "" +"Some languages have functions return an error number (or some other error " +"value) separately from the successful return value of the function. Examples " +"include C and Go." +msgstr "" + +#: src/error-handling/result.md +msgid "" +"Depending on the language it may be possible to forget to check the error " +"value, in which case you may be accessing an uninitialized or otherwise " +"invalid success value." +msgstr "" + +#: src/error-handling/try.md +msgid "" +"Runtime errors like connection-refused or file-not-found are handled with " +"the `Result` type, but matching this type on every call can be cumbersome. " +"The try-operator `?` is used to return errors to the caller. It lets you " +"turn the common" +msgstr "" + +#: src/error-handling/try.md +msgid "into the much simpler" +msgstr "" + +#: src/error-handling/try.md +msgid "We can use this to simplify our error handling code:" +msgstr "" + +#: src/error-handling/try.md +msgid "//fs::write(\"config.dat\", \"alice\").unwrap();\n" +msgstr "" + +#: src/error-handling/try.md src/error-handling/try-conversions.md +#: src/error-handling/thiserror.md src/error-handling/anyhow.md +msgid "\"config.dat\"" +msgstr "" + +#: src/error-handling/try.md src/error-handling/try-conversions.md +msgid "\"username or error: {username:?}\"" +msgstr "" + +#: src/error-handling/try.md +msgid "Simplify the `read_username` function to use `?`." +msgstr "" + +#: src/error-handling/try.md +msgid "The `username` variable can be either `Ok(string)` or `Err(error)`." +msgstr "" + +#: src/error-handling/try.md +msgid "" +"Use the `fs::write` call to test out the different scenarios: no file, empty " +"file, file with username." +msgstr "" + +#: src/error-handling/try.md +msgid "" +"Note that `main` can return a `Result<(), E>` as long as it implements `std::" +"process::Termination`. In practice, this means that `E` implements `Debug`. " +"The executable will print the `Err` variant and return a nonzero exit status " +"on error." +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "" +"The effective expansion of `?` is a little more complicated than previously " +"indicated:" +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "works the same as" +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "" +"The `From::from` call here means we attempt to convert the error type to the " +"type returned by the function. This makes it easy to encapsulate errors into " +"higher-level errors." +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "\"I/O error: {e}\"" +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "\"Found no username in {path}\"" +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "//std::fs::write(\"config.dat\", \"\").unwrap();\n" +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "" +"The `?` operator must return a value compatible with the return type of the " +"function. For `Result`, it means that the error types have to be compatible. " +"A function that returns `Result` can only use `?` on a value " +"of type `Result` if `ErrorOuter` and `ErrorInner` are the " +"same type or if `ErrorOuter` implements `From`." +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "" +"A common alternative to a `From` implementation is `Result::map_err`, " +"especially when the conversion only happens in one place." +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "" +"There is no compatibility requirement for `Option`. A function returning " +"`Option` can use the `?` operator on `Option` for arbitrary `T` and " +"`U` types." +msgstr "" + +#: src/error-handling/try-conversions.md +msgid "" +"A function that returns `Result` cannot use `?` on `Option` and vice versa. " +"However, `Option::ok_or` converts `Option` to `Result` whereas `Result::ok` " +"turns `Result` into `Option`." +msgstr "" + +#: src/error-handling/error.md +msgid "Dynamic Error Types" +msgstr "" + +#: src/error-handling/error.md +msgid "" +"Sometimes we want to allow any type of error to be returned without writing " +"our own enum covering all the different possibilities. The `std::error::" +"Error` trait makes it easy to create a trait object that can contain any " +"error." +msgstr "" + +#: src/error-handling/error.md +msgid "\"count.dat\"" +msgstr "" + +#: src/error-handling/error.md +msgid "\"1i3\"" +msgstr "" + +#: src/error-handling/error.md +msgid "\"Count: {count}\"" +msgstr "" + +#: src/error-handling/error.md src/error-handling/thiserror.md +msgid "\"Error: {err}\"" +msgstr "" + +#: src/error-handling/error.md +msgid "" +"The `read_count` function can return `std::io::Error` (from file operations) " +"or `std::num::ParseIntError` (from `String::parse`)." +msgstr "" + +#: src/error-handling/error.md +msgid "" +"Boxing errors saves on code, but gives up the ability to cleanly handle " +"different error cases differently in the program. As such it's generally not " +"a good idea to use `Box` in the public API of a library, but it " +"can be a good option in a program where you just want to display the error " +"message somewhere." +msgstr "" + +#: src/error-handling/error.md +msgid "" +"Make sure to implement the `std::error::Error` trait when defining a custom " +"error type so it can be boxed." +msgstr "" + +#: src/error-handling/thiserror.md +msgid "" +"The [`thiserror`](https://docs.rs/thiserror/) crate provides macros to help " +"avoid boilerplate when defining error types. It provides derive macros that " +"assist in implementing `From`, `Display`, and the `Error` trait." +msgstr "" + +#: src/error-handling/thiserror.md +msgid "\"I/O error: {0}\"" +msgstr "" + +#: src/error-handling/thiserror.md src/error-handling/anyhow.md +msgid "\"Found no username in {0}\"" +msgstr "" + +#: src/error-handling/thiserror.md src/error-handling/anyhow.md +msgid "//fs::write(\"config.dat\", \"\").unwrap();\n" +msgstr "" + +#: src/error-handling/thiserror.md src/error-handling/anyhow.md +msgid "\"Username: {username}\"" +msgstr "" + +#: src/error-handling/thiserror.md +msgid "" +"The `Error` derive macro is provided by `thiserror`, and has lots of useful " +"attributes to help define error types in a compact way." +msgstr "" + +#: src/error-handling/thiserror.md +msgid "The message from `#[error]` is used to derive the `Display` trait." +msgstr "" + +#: src/error-handling/thiserror.md +msgid "" +"Note that the (`thiserror::`)`Error` derive macro, while it has the effect " +"of implementing the (`std::error::`)`Error` trait, is not the same this; " +"traits and macros do not share a namespace." +msgstr "" + +#: src/error-handling/anyhow.md +msgid "" +"The [`anyhow`](https://docs.rs/anyhow/) crate provides a rich error type " +"with support for carrying additional contextual information, which can be " +"used to provide a semantic trace of what the program was doing leading up to " +"the error." +msgstr "" + +#: src/error-handling/anyhow.md +msgid "" +"This can be combined with the convenience macros from [`thiserror`](https://" +"docs.rs/thiserror/) to avoid writing out trait impls explicitly for custom " +"error types." +msgstr "" + +#: src/error-handling/anyhow.md +msgid "\"Failed to open {path}\"" +msgstr "" + +#: src/error-handling/anyhow.md +msgid "\"Failed to read\"" +msgstr "" + +#: src/error-handling/anyhow.md +msgid "\"Error: {err:?}\"" +msgstr "" + +#: src/error-handling/anyhow.md +msgid "" +"`anyhow::Error` is essentially a wrapper around `Box`. As such " +"it's again generally not a good choice for the public API of a library, but " +"is widely used in applications." +msgstr "" + +#: src/error-handling/anyhow.md +msgid "`anyhow::Result` is a type alias for `Result`." +msgstr "" + +#: src/error-handling/anyhow.md +msgid "" +"Functionality provided by `anyhow::Error` may be familiar to Go developers, " +"as it provides similar behavior to the Go `error` type and `Result` is much like a Go `(T, error)` (with the convention that " +"only one element of the pair is meaningful)." +msgstr "" + +#: src/error-handling/anyhow.md +msgid "" +"`anyhow::Context` is a trait implemented for the standard `Result` and " +"`Option` types. `use anyhow::Context` is necessary to enable `.context()` " +"and `.with_context()` on those types." +msgstr "" + +#: src/error-handling/anyhow.md +msgid "" +"`anyhow::Error` has support for downcasting, much like `std::any::Any`; the " +"specific error type stored inside can be extracted for examination if " +"desired with [`Error::downcast`](https://docs.rs/anyhow/latest/anyhow/struct." +"Error.html#method.downcast)." +msgstr "" + +#: src/error-handling/exercise.md +msgid "" +"In this exercise we're revisiting the expression evaluator exercise that we " +"did in day 2. Our initial solution ignores a possible error case: Dividing " +"by zero! Rewrite `eval` to instead use idiomatic error handling to handle " +"this error case and return an error when it occurs. We provide a simple " +"`DivideByZeroError` type to use as the error type for `eval`." +msgstr "" + +#: src/error-handling/exercise.md +msgid "" +"// The original implementation of the expression evaluator. Update this to\n" +"// return a `Result` and produce an error when dividing by 0.\n" +msgstr "" + +#: src/error-handling/exercise.md +msgid "\"Cannot divide by zero!\"" +msgstr "" + +#: src/error-handling/exercise.md +msgid "" +"The starting code here isn't exactly the same as the previous exercise's " +"solution: We've added in an explicit panic to show students where the error " +"case is. Point this out if students get confused." +msgstr "" + +#: src/error-handling/solution.md +msgid "" +"**`Result` Return Type:** The function signature changes to return " +"`Result`. This explicit type signature forces the " +"caller to handle the possibility of failure." +msgstr "" + +#: src/error-handling/solution.md +msgid "" +"**The `?` Operator:** We use `?` on the recursive calls: `eval(*left)?`. " +"This cleanly propagates errors. If `eval` returns `Err`, the function " +"immediately returns that `Err`. If it returns `Ok(v)`, `v` is assigned to " +"`left` (or `right`)." +msgstr "" + +#: src/error-handling/solution.md +msgid "**`Ok` Wrapping:** Successful results must be wrapped in `Ok(...)`." +msgstr "" + +#: src/error-handling/solution.md +msgid "" +"**Handling Division by Zero:** We explicitly check for `right == 0` and " +"return `Err(DivideByZeroError)`. This replaces the panic in the original " +"code." +msgstr "" + +#: src/error-handling/solution.md +msgid "" +"Mention that `DivideByZeroError` is a unit struct (no fields), which is " +"sufficient here since there's no extra context to provide about the error." +msgstr "" + +#: src/error-handling/solution.md +msgid "" +"Discuss how `?` makes error handling almost as concise as exceptions, but " +"with explicit control flow." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "The Rust language has two parts:" +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "**Safe Rust:** memory safe, no undefined behavior possible." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "" +"**Unsafe Rust:** can trigger undefined behavior if preconditions are " +"violated." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "" +"We saw mostly safe Rust in this course, but it's important to know what " +"Unsafe Rust is." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "" +"Unsafe code should be small and isolated, and its correctness should be " +"carefully documented. It should be wrapped in a safe abstraction layer." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "Unsafe Rust gives you access to five new capabilities:" +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "Dereference raw pointers." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "Access or modify mutable static variables." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "Access `union` fields." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "Call `unsafe` functions, including `extern` functions." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "Implement `unsafe` traits." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "" +"We will briefly cover unsafe capabilities next. For full details, please see " +"[Chapter 19.1 in the Rust Book](https://doc.rust-lang.org/book/ch19-01-" +"unsafe-rust.html) and the [Rustonomicon](https://doc.rust-lang.org/nomicon/)." +msgstr "" + +#: src/unsafe-rust/unsafe.md +msgid "" +"Unsafe Rust does not mean the code is incorrect. It means that developers " +"have turned off some compiler safety features and have to write correct code " +"by themselves. It means the compiler no longer enforces Rust's memory-safety " +"rules." +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "Creating pointers is safe, but dereferencing them requires `unsafe`:" +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "" +"// SAFETY: p1 and p2 were created by taking raw pointers to a local, so " +"they\n" +" // are guaranteed to be non-null, aligned, and point into a single " +"(stack-)\n" +" // allocated object.\n" +" //\n" +" // The object underlying the raw pointers lives for the entire function, " +"so\n" +" // it is not deallocated while the raw pointers still exist. It is not\n" +" // accessed through references while the raw pointers exist, nor is it\n" +" // accessed from other threads concurrently.\n" +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "// Mutation may soundly be observed through a raw pointer, like in C.\n" +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "" +"// UNSOUND. DO NOT DO THIS.\n" +" /*\n" +" let r: &i32 = unsafe { &*p1 };\n" +" dbg!(r);\n" +" x = 50;\n" +" dbg!(r); // Object underlying the reference has been mutated. This is " +"UB.\n" +" */" +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "" +"It is good practice (and required by the Android Rust style guide) to write " +"a comment for each `unsafe` block explaining how the code inside it " +"satisfies the safety requirements of the unsafe operations it is doing." +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "" +"In the case of pointer dereferences, this means that the pointers must be " +"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), i.e.:" +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "The pointer must be non-null." +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "" +"The pointer must be _dereferenceable_ (within the bounds of a single " +"allocated object)." +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "The object must not have been deallocated." +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "There must not be concurrent accesses to the same location." +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "" +"If the pointer was obtained by casting a reference, the underlying object " +"must be live and no reference may be used to access the memory." +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "In most cases the pointer must also be properly aligned." +msgstr "" + +#: src/unsafe-rust/dereferencing.md +msgid "" +"The \"UNSOUND\" section gives an example of a common kind of UB bug: naïvely " +"taking a reference to the dereference of a raw pointer sidesteps the " +"compiler's knowledge of what object the reference is actually pointing to. " +"As such, the borrow checker does not freeze `x` and so we are able to modify " +"it despite the existence of a reference to it. Creating a reference from a " +"pointer requires _great care_." +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "It is safe to read an immutable static variable:" +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "\"Hello, world!\"" +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "\"HELLO_WORLD: {HELLO_WORLD}\"" +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "" +"However, mutable static variables are unsafe to read and write because " +"multiple threads could do so concurrently without synchronization, " +"constituting a data race." +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "" +"Using mutable statics soundly requires reasoning about concurrency without " +"the compiler's help:" +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "" +"// SAFETY: There are no other threads which could be accessing `COUNTER`.\n" +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "" +"The program here is sound because it is single-threaded. However, the Rust " +"compiler reasons about functions individually so can't assume that. Try " +"removing the `unsafe` and see how the compiler explains that it is undefined " +"behavior to access a mutable static from multiple threads." +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "" +"The 2024 Rust edition goes further and makes accessing a mutable static by " +"reference an error by default." +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "" +"Using a mutable static is rarely a good idea, you should use interior " +"mutability instead." +msgstr "" + +#: src/unsafe-rust/mutable-static.md +msgid "" +"There are some cases where it might be necessary in low-level `no_std` code, " +"such as implementing a heap allocator or working with some C APIs. In this " +"case you should use pointers rather than references." +msgstr "" + +#: src/unsafe-rust/unions.md +msgid "Unions are like enums, but you need to track the active field yourself:" +msgstr "" + +#: src/unsafe-rust/unions.md +msgid "\"int: {}\"" +msgstr "" + +#: src/unsafe-rust/unions.md +msgid "\"bool: {}\"" +msgstr "" + +#: src/unsafe-rust/unions.md +msgid "// Undefined behavior!\n" +msgstr "" + +#: src/unsafe-rust/unions.md +msgid "" +"Unions are rarely needed in Rust as enums provide a superior alternative. " +"They are occasionally needed for interacting with C library APIs." +msgstr "" + +#: src/unsafe-rust/unions.md +msgid "" +"If you just want to reinterpret bytes as a different type, you probably want " +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn." +"transmute.html) or a safe wrapper such as the [`zerocopy`](https://crates.io/" +"crates/zerocopy) crate." +msgstr "" + +#: src/unsafe-rust/unsafe-functions.md +msgid "" +"A function or method can be marked `unsafe` if it has extra preconditions " +"you must uphold to avoid undefined behaviour." +msgstr "" + +#: src/unsafe-rust/unsafe-functions.md +msgid "Unsafe functions may come from two places:" +msgstr "" + +#: src/unsafe-rust/unsafe-functions.md +msgid "Rust functions declared unsafe." +msgstr "" + +#: src/unsafe-rust/unsafe-functions.md +msgid "Unsafe foreign functions in `extern \"C\"` blocks." +msgstr "" + +#: src/unsafe-rust/unsafe-functions.md +msgid "We will look at the two kinds of unsafe functions next." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/rust.md +msgid "" +"You can mark your own functions as `unsafe` if they require particular " +"preconditions to avoid undefined behaviour." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/rust.md +msgid "" +"/// Swaps the values pointed to by the given pointers.\n" +"///\n" +"/// # Safety\n" +"///\n" +"/// The pointers must be valid, properly aligned, and not otherwise accessed " +"for\n" +"/// the duration of the function call.\n" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/rust.md +msgid "" +"// SAFETY: Our caller promised that the pointers are valid, properly " +"aligned\n" +" // and have no other access.\n" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/rust.md +msgid "" +"// SAFETY: The pointers must be valid, aligned and unique because they came\n" +" // from references.\n" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/rust.md +msgid "\"a = {}, b = {}\"" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/rust.md +msgid "" +"We wouldn't actually use pointers for a `swap` function --- it can be done " +"safely with references." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/rust.md +msgid "" +"Note that Rust 2021 and earlier allow unsafe code within an unsafe function " +"without an `unsafe` block. This changed in the 2024 edition. We can prohibit " +"it in older editions with `#[deny(unsafe_op_in_unsafe_fn)]`. Try adding it " +"and see what happens." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "" +"You can declare foreign functions for access from Rust with `unsafe extern`. " +"This is unsafe because the compiler has no way to reason about their " +"behavior. Functions declared in an `extern` block must be marked as `safe` " +"or `unsafe`, depending on whether they have preconditions for safe use:" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md src/unsafe-rust/exercise.md +#: src/unsafe-rust/solution.md src/android/interoperability/with-c.md +#: src/android/interoperability/with-c/rust-library.md +#: src/android/interoperability/cpp/cpp-bridge.md +#: src/exercises/chromium/build-rules.md src/bare-metal/aps/inline-assembly.md +#: src/bare-metal/aps/uart/using.md src/bare-metal/aps/safemmio/using.md +#: src/bare-metal/aps/logging/using.md +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md +#: src/unsafe-deep-dive/ffi/abs.md +#: src/unsafe-deep-dive/ffi/c-library-example.md +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "\"C\"" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "" +"// `abs` doesn't deal with pointers and doesn't have any safety " +"requirements.\n" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "" +"/// # Safety\n" +" ///\n" +" /// `s` must be a pointer to a NUL-terminated C string which is valid " +"and\n" +" /// not modified for the duration of this function call.\n" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "\"Absolute value of -3 according to C: {}\"" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "" +"// SAFETY: We pass a pointer to a C string literal which is valid for\n" +" // the duration of the program.\n" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "\"String length: {}\"" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +msgid "\"String\"" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "" +"Rust used to consider all extern functions unsafe, but this changed in Rust " +"1.82 with `unsafe extern` blocks." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "" +"`abs` must be explicitly marked as `safe` because it is an external function " +"(FFI). Calling external functions is only a problem when those functions do " +"things with pointers which might violate Rust's memory model, but in general " +"any C function might have undefined behaviour under any arbitrary " +"circumstances." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "" +"The `\"C\"` in this example is the ABI; [other ABIs are available too]" +"(https://doc.rust-lang.org/reference/items/external-blocks.html)." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/extern-c.md +msgid "" +"Note that there is no verification that the Rust function signature matches " +"that of the function definition -- that's up to you!" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/calling.md +msgid "Failing to uphold the safety requirements breaks memory safety!" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/calling.md +msgid "// 8 bytes\n" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/calling.md +msgid "\"{pk:?}\"" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/calling.md +msgid "" +"Always include a safety comment for each `unsafe` block. It must explain why " +"the code is actually safe. This example is missing a safety comment and is " +"unsound." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/calling.md +msgid "" +"The second argument to `slice::from_raw_parts` is the number of _elements_, " +"not bytes! This example demonstrates unexpected behavior by reading past the " +"end of one array and into another." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/calling.md +msgid "" +"This is undefined behavior because we're reading past the end of the array " +"that the pointer was derived from." +msgstr "" + +#: src/unsafe-rust/unsafe-functions/calling.md +msgid "" +"`log_public_key` should be unsafe, because `pk_ptr` must meet certain " +"prerequisites to avoid undefined behaviour. A safe function which can cause " +"undefined behaviour is said to be `unsound`. What should its safety " +"documentation say?" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/calling.md +msgid "" +"The standard library contains a number of low-level unsafe functions. Prefer " +"the safe alternatives when possible!" +msgstr "" + +#: src/unsafe-rust/unsafe-functions/calling.md +msgid "" +"If you use an unsafe function as an optimization, make sure to add a " +"benchmark to demonstrate the gain." +msgstr "" + +#: src/unsafe-rust/unsafe-traits.md +msgid "Implementing Unsafe Traits" +msgstr "" + +#: src/unsafe-rust/unsafe-traits.md +msgid "" +"Like with functions, you can mark a trait as `unsafe` if the implementation " +"must guarantee particular conditions to avoid undefined behaviour." +msgstr "" + +#: src/unsafe-rust/unsafe-traits.md +msgid "" +"For example, the `zerocopy` crate has an unsafe trait that looks [something " +"like this](https://docs.rs/zerocopy/latest/zerocopy/trait.IntoBytes.html):" +msgstr "" + +#: src/unsafe-rust/unsafe-traits.md +msgid "" +"/// ...\n" +"/// # Safety\n" +"/// The type must have a defined representation and no padding.\n" +msgstr "" + +#: src/unsafe-rust/unsafe-traits.md +msgid "// SAFETY: `u32` has a defined representation and no padding.\n" +msgstr "" + +#: src/unsafe-rust/unsafe-traits.md +msgid "" +"There should be a `# Safety` section on the Rustdoc for the trait explaining " +"the requirements for the trait to be safely implemented." +msgstr "" + +#: src/unsafe-rust/unsafe-traits.md +msgid "" +"The actual safety section for `IntoBytes` is rather longer and more " +"complicated." +msgstr "" + +#: src/unsafe-rust/unsafe-traits.md +msgid "The built-in `Send` and `Sync` traits are unsafe." +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "Safe FFI Wrapper" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"Rust has great support for calling functions through a _foreign function " +"interface_ (FFI). We will use this to build a safe wrapper for the `libc` " +"functions you would use from C to read the names of files in a directory." +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "You will want to consult the manual pages:" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "[`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "[`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "[`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"You will also want to browse the [`std::ffi`](https://doc.rust-lang.org/std/" +"ffi/) module. There you find a number of string types which you need for the " +"exercise:" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "Encoding" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "Use" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"[`str`](https://doc.rust-lang.org/std/primitive.str.html) and [`String`]" +"(https://doc.rust-lang.org/std/string/struct.String.html)" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "UTF-8" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "Text processing in Rust" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"[`CStr`](https://doc.rust-lang.org/std/ffi/struct.CStr.html) and [`CString`]" +"(https://doc.rust-lang.org/std/ffi/struct.CString.html)" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "NUL-terminated" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "Communicating with C functions" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"[`OsStr`](https://doc.rust-lang.org/std/ffi/struct.OsStr.html) and " +"[`OsString`](https://doc.rust-lang.org/std/ffi/struct.OsString.html)" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "OS-specific" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "Communicating with the OS" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "You will convert between all these types:" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"`&str` to `CString`: you need to allocate space for a trailing `\\0` " +"character," +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "`CString` to `*const c_char`: you need a pointer to call C functions," +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"`*const c_char` to `&CStr`: you need something which can find the trailing " +"`\\0` character," +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"`&CStr` to `&[u8]`: a slice of bytes is the universal interface for \"some " +"unknown data\"," +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"`&[u8]` to `&OsStr`: `&OsStr` is a step towards `OsString`, use [`OsStrExt`]" +"(https://doc.rust-lang.org/std/os/unix/ffi/trait.OsStrExt.html) to create it," +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"`&OsStr` to `OsString`: you need to clone the data in `&OsStr` to be able to " +"return it and call `readdir` again." +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"The [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html) also has a very " +"useful chapter about FFI." +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"Copy the code below to and fill in the missing " +"functions and methods:" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "// TODO: remove this when you're done with your implementation.\n" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +msgid "\"macos\"" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +msgid "// Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +msgid "" +"// Layout according to the Linux man page for readdir(3), where ino_t and\n" +" // off_t are resolved according to the definitions in\n" +" // /usr/include/x86_64-linux-gnu/{sys/types.h, bits/typesizes.h}.\n" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +msgid "// Layout according to the macOS man page for dir(5).\n" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +msgid "\"x86_64\"" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +msgid "" +"// See https://github.com/rust-lang/libc/issues/414 and the section on\n" +" // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2).\n" +" //\n" +" // \"Platforms that existed before these updates were available\" " +"refers\n" +" // to macOS (as opposed to iOS / wearOS / etc.) on Intel and " +"PowerPC.\n" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +msgid "\"readdir$INODE64\"" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +msgid "" +"// Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "// Keep calling readdir until we get a NULL pointer back.\n" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "// Call closedir as needed.\n" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +#: src/android/interoperability/with-c/rust-library.md +msgid "\".\"" +msgstr "" + +#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +msgid "\"files: {:#?}\"" +msgstr "" + +#: src/unsafe-rust/exercise.md +msgid "" +"FFI binding code is typically generated by tools like [bindgen](https://" +"github.com/rust-lang/rust-bindgen), rather than being written manually as we " +"are doing here. However, bindgen can't run in an online playground." +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"Invalid path: {err}\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "// SAFETY: path.as_ptr() cannot be NULL.\n" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"Could not open {path:?}\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"// Keep calling readdir until we get a NULL pointer back.\n" +" // SAFETY: self.dir is never NULL.\n" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "// We have reached the end of the directory.\n" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"// SAFETY: dirent is not NULL and dirent.d_name is NUL\n" +" // terminated.\n" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"// Call closedir as needed.\n" +" // SAFETY: self.dir is never NULL.\n" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"Could not close {:?}\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"no-such-directory\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"Non UTF-8 character in path\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"..\"" +msgstr "" + +#: src/unsafe-rust/solution.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "\"foo.txt\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"The Foo Diaries\\n\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"bar.png\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"\\n\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"crab.rs\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "\"//! Crab\\n\"" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"**Safety Comments:** Each `unsafe` block is preceded by a `// SAFETY:` " +"comment explaining why the operation is safe. This is standard practice in " +"Rust to aid auditing." +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"**String conversions:** The code demonstrates the conversions required for " +"FFI:" +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "`&str` -> `CString`: To create a null-terminated string for C." +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "`CString` -> `*const c_char`: To pass the pointer to C." +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "`*const c_char` -> `&CStr`: To wrap the returned C string." +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"`&CStr` -> `&[u8]` -> `&OsStr` -> `OsString`: To convert the bytes back to a " +"Rust OS string." +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"**RAII (`Drop`):** We implement `Drop` to call `closedir` automatically when " +"the iterator goes out of scope. This ensures we don't leak file descriptors." +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"**Iterator Interface:** We wrap the C API in a Rust `Iterator`, providing a " +"safe and idiomatic interface (`next` returns `Option`) to the " +"underlying unsafe C functions." +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"Explain that `CString` owns the data (like `String`), while `CStr` is a " +"borrowed reference (like `&str`)." +msgstr "" + +#: src/unsafe-rust/solution.md +msgid "" +"The `OsStrExt` trait is needed on Unix systems to convert bytes directly to " +"`OsStr`." +msgstr "" + +#: src/android.md +msgid "Welcome to Rust in Android" +msgstr "" + +#: src/android.md +msgid "" +"Rust is supported for system software on Android. This means that you can " +"write new services, libraries, drivers or even firmware in Rust (or improve " +"existing code as needed)." +msgstr "" + +#: src/android.md +msgid "" +"The speaker may mention any of the following given the increased use of Rust " +"in Android:" +msgstr "" + +#: src/android.md +msgid "" +"Service example: [DNS over HTTP](https://security.googleblog.com/2022/07/dns-" +"over-http3-in-android.html)." +msgstr "" + +#: src/android.md +msgid "" +"Libraries: [Rutabaga Virtual Graphics Interface](https://crosvm.dev/book/" +"appendix/rutabaga_gfx.html)." +msgstr "" + +#: src/android.md +msgid "" +"Kernel Drivers: [Binder](https://lore.kernel.org/rust-for-linux/20231101-" +"rust-binder-v1-0-08ba9197f637@google.com/)." +msgstr "" + +#: src/android.md +msgid "" +"Firmware: [pKVM firmware](https://security.googleblog.com/2023/10/bare-metal-" +"rust-in-android.html)." +msgstr "" + +#: src/android/setup.md +msgid "" +"We will be using a Cuttlefish Android Virtual Device to test our code. Make " +"sure you have access to one or create a new one with:" +msgstr "" + +#: src/android/setup.md +msgid "" +"Please see the [Android Developer Codelab](https://source.android.com/docs/" +"setup/start) for details." +msgstr "" + +#: src/android/setup.md +msgid "" +"The code on the following pages can be found in the [`src/android/` " +"directory](https://github.com/google/comprehensive-rust/tree/main/src/" +"android) of the course material. Please `git clone` the repository to follow " +"along." +msgstr "" + +#: src/android/setup.md +msgid "" +"Cuttlefish is a reference Android device designed to work on generic Linux " +"desktops. MacOS support is also planned." +msgstr "" + +#: src/android/setup.md +msgid "" +"The Cuttlefish system image maintains high fidelity to real devices, and is " +"the ideal emulator to run many Rust use cases." +msgstr "" + +#: src/android/build-rules.md +msgid "The Android build system (Soong) supports Rust through several modules:" +msgstr "" + +#: src/android/build-rules.md +msgid "Module Type" +msgstr "" + +#: src/android/build-rules.md +msgid "Description" +msgstr "" + +#: src/android/build-rules.md +msgid "`rust_binary`" +msgstr "" + +#: src/android/build-rules.md +msgid "Produces a Rust binary." +msgstr "" + +#: src/android/build-rules.md +msgid "`rust_library`" +msgstr "" + +#: src/android/build-rules.md +msgid "Produces a Rust library, and provides both `rlib` and `dylib` variants." +msgstr "" + +#: src/android/build-rules.md +msgid "`rust_ffi`" +msgstr "" + +#: src/android/build-rules.md +msgid "" +"Produces a Rust C library usable by `cc` modules, and provides both static " +"and shared variants." +msgstr "" + +#: src/android/build-rules.md +msgid "`rust_proc_macro`" +msgstr "" + +#: src/android/build-rules.md +msgid "" +"Produces a `proc-macro` Rust library. These are analogous to compiler " +"plugins." +msgstr "" + +#: src/android/build-rules.md +msgid "`rust_test`" +msgstr "" + +#: src/android/build-rules.md +msgid "Produces a Rust test binary that uses the standard Rust test harness." +msgstr "" + +#: src/android/build-rules.md +msgid "`rust_fuzz`" +msgstr "" + +#: src/android/build-rules.md +msgid "Produces a Rust fuzz binary leveraging `libfuzzer`." +msgstr "" + +#: src/android/build-rules.md +msgid "`rust_protobuf`" +msgstr "" + +#: src/android/build-rules.md +msgid "" +"Generates source and produces a Rust library that provides an interface for " +"a particular protobuf." +msgstr "" + +#: src/android/build-rules.md +msgid "`rust_bindgen`" +msgstr "" + +#: src/android/build-rules.md +msgid "" +"Generates source and produces a Rust library containing Rust bindings to C " +"libraries." +msgstr "" + +#: src/android/build-rules.md +msgid "We will look at `rust_binary` and `rust_library` next." +msgstr "" + +#: src/android/build-rules.md +msgid "Additional items the speaker may mention:" +msgstr "" + +#: src/android/build-rules.md +msgid "" +"Cargo is not optimized for multi-language repositories, and also downloads " +"packages from the internet." +msgstr "" + +#: src/android/build-rules.md +msgid "" +"For compliance and performance, Android must have crates in-tree. It must " +"also interoperate with C/C++/Java code. Soong fills that gap." +msgstr "" + +#: src/android/build-rules.md +msgid "" +"Soong has many similarities to [Bazel](https://bazel.build/), which is the " +"open-source variant of Blaze (used in google3)." +msgstr "" + +#: src/android/build-rules.md +msgid "Fun fact: Data from Star Trek is a Soong-type Android." +msgstr "" + +#: src/android/build-rules/binary.md +msgid "Rust Binaries" +msgstr "" + +#: src/android/build-rules/binary.md +msgid "" +"Let's start with a simple application. At the root of an AOSP checkout, " +"create the following files:" +msgstr "" + +#: src/android/build-rules/binary.md src/android/build-rules/library.md +msgid "_hello_rust/Android.bp_:" +msgstr "" + +#: src/android/build-rules/binary.md +msgid "\"hello_rust\"" +msgstr "" + +#: src/android/build-rules/binary.md src/android/build-rules/library.md +#: src/android/logging.md +msgid "\"src/main.rs\"" +msgstr "" + +#: src/android/build-rules/binary.md src/android/build-rules/library.md +msgid "_hello_rust/src/main.rs_:" +msgstr "" + +#: src/android/build-rules/binary.md src/android/build-rules/library.md +msgid "//! Rust demo.\n" +msgstr "" + +#: src/android/build-rules/binary.md src/android/build-rules/library.md +msgid "/// Prints a greeting to standard output.\n" +msgstr "" + +#: src/android/build-rules/binary.md src/exercises/chromium/build-rules.md +msgid "\"Hello from Rust!\"" +msgstr "" + +#: src/android/build-rules/binary.md +msgid "You can now build, push, and run the binary:" +msgstr "" + +#: src/android/build-rules/binary.md +msgid "" +"```shell\n" +"m hello_rust\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust\" /data/local/tmp\n" +"adb shell /data/local/tmp/hello_rust\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md src/android/build-rules/library.md +msgid "" +"Go through the build steps and demonstrate them running in your emulator." +msgstr "" + +#: src/android/build-rules/binary.md +msgid "" +"Notice the extensive documentation comments? The Android build rules enforce " +"that all modules have documentation. Try removing it and see what error you " +"get." +msgstr "" + +#: src/android/build-rules/binary.md +msgid "" +"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." +msgstr "" + +#: src/android/build-rules/library.md +msgid "Rust Libraries" +msgstr "" + +#: src/android/build-rules/library.md +msgid "You use `rust_library` to create a new Rust library for Android." +msgstr "" + +#: src/android/build-rules/library.md +msgid "Here we declare a dependency on two libraries:" +msgstr "" + +#: src/android/build-rules/library.md +msgid "`libgreeting`, which we define below," +msgstr "" + +#: src/android/build-rules/library.md +msgid "" +"`libtextwrap`, which is a crate already vendored in [`external/rust/android-" +"crates-io/crates/`](https://cs.android.com/android/platform/superproject/" +"main/+/main:external/rust/android-crates-io/crates/)." +msgstr "" + +#: src/android/build-rules/library.md +msgid "\"hello_rust_with_dep\"" +msgstr "" + +#: src/android/build-rules/library.md +msgid "\"libgreetings\"" +msgstr "" + +#: src/android/build-rules/library.md +msgid "\"libtextwrap\"" +msgstr "" + +#: src/android/build-rules/library.md +msgid "// Need this to avoid dynamic link error.\n" +msgstr "" + +#: src/android/build-rules/library.md +msgid "\"greetings\"" +msgstr "" + +#: src/android/build-rules/library.md +#: src/android/aidl/example-service/service.md src/android/testing.md +#: src/android/interoperability/java.md +msgid "\"src/lib.rs\"" +msgstr "" + +#: src/android/build-rules/library.md +#: src/android/aidl/example-service/client.md +msgid "\"Bob\"" +msgstr "" + +#: src/android/build-rules/library.md +msgid "_hello_rust/src/lib.rs_:" +msgstr "" + +#: src/android/build-rules/library.md +msgid "//! Greeting library.\n" +msgstr "" + +#: src/android/build-rules/library.md +msgid "/// Greet `name`.\n" +msgstr "" + +#: src/android/build-rules/library.md +msgid "\"Hello {name}, it is very nice to meet you!\"" +msgstr "" + +#: src/android/build-rules/library.md +msgid "You build, push, and run the binary like before:" +msgstr "" + +#: src/android/build-rules/library.md +msgid "" +"```shell\n" +"m hello_rust_with_dep\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep\" /data/local/" +"tmp\n" +"adb shell /data/local/tmp/hello_rust_with_dep\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md +msgid "" +"A Rust crate named `greetings` must be built by a rule called " +"`libgreetings`. Note how the Rust code uses the crate name, as is normal in " +"Rust." +msgstr "" + +#: src/android/build-rules/library.md +msgid "" +"Again, the build rules enforce that we add documentation comments to all " +"public items." +msgstr "" + +#: src/android/aidl.md +msgid "" +"Rust supports the [Android Interface Definition Language (AIDL)](https://" +"developer.android.com/guide/components/aidl):" +msgstr "" + +#: src/android/aidl.md +msgid "Rust code can call existing AIDL servers." +msgstr "" + +#: src/android/aidl.md +msgid "You can create new AIDL servers in Rust." +msgstr "" + +#: src/android/aidl.md +msgid "AIDL enables Android apps to interact with each other." +msgstr "" + +#: src/android/aidl.md +msgid "" +"Since Rust is a first-class citizen in this ecosystem, other processes on " +"the device can call Rust services." +msgstr "" + +#: src/android/aidl/birthday-service.md +msgid "" +"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." +msgstr "" + +#: src/android/aidl/example-service/interface.md +msgid "AIDL Interfaces" +msgstr "" + +#: src/android/aidl/example-service/interface.md +msgid "You declare the API of your service using an AIDL interface:" +msgstr "" + +#: src/android/aidl/example-service/interface.md +#: src/android/aidl/example-service/service-bindings.md +#: src/android/aidl/types/objects.md src/android/aidl/types/parcelables.md +#: src/android/aidl/types/file-descriptor.md +msgid "" +"_birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl_:" +msgstr "" + +#: src/android/aidl/example-service/interface.md +#: src/android/aidl/example-service/service-bindings.md +#: src/android/aidl/example-service/changing-definition.md +msgid "/** Birthday service interface. */" +msgstr "" + +#: src/android/aidl/example-service/interface.md +#: src/android/aidl/example-service/service-bindings.md +#: src/android/aidl/example-service/changing-definition.md +msgid "/** Generate a Happy Birthday message. */" +msgstr "" + +#: src/android/aidl/example-service/interface.md +msgid "_birthday_service/aidl/Android.bp_:" +msgstr "" + +#: src/android/aidl/example-service/interface.md +msgid "\"com.example.birthdayservice\"" +msgstr "" + +#: src/android/aidl/example-service/interface.md +msgid "\"com/example/birthdayservice/*.aidl\"" +msgstr "" + +#: src/android/aidl/example-service/interface.md +msgid "// Rust is not enabled by default\n" +msgstr "" + +#: src/android/aidl/example-service/interface.md +msgid "" +"Note that the directory structure under the `aidl/` directory needs to match " +"the package name used in the AIDL file, i.e. the package is `com.example." +"birthdayservice` and the file is at `aidl/com/example/IBirthdayService.aidl`." +msgstr "" + +#: src/android/aidl/example-service/service-bindings.md +msgid "Generated Service API" +msgstr "" + +#: src/android/aidl/example-service/service-bindings.md +msgid "Binder generates a trait for each interface definition." +msgstr "" + +#: src/android/aidl/example-service/service-bindings.md +msgid "_out/soong/.intermediates/.../com_example_birthdayservice.rs_:" +msgstr "" + +#: src/android/aidl/example-service/service-bindings.md +msgid "" +"Your service will need to implement this trait, and your client will use " +"this trait to talk to the service." +msgstr "" + +#: src/android/aidl/example-service/service-bindings.md +msgid "" +"Point out how the generated function signature, specifically the argument " +"and return types, correspond to the interface definition." +msgstr "" + +#: src/android/aidl/example-service/service-bindings.md +msgid "" +"`String` for an argument results in a different Rust type than `String` as a " +"return type." +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "Service Implementation" +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "We can now implement the AIDL service:" +msgstr "" + +#: src/android/aidl/example-service/service.md +#: src/android/aidl/example-service/changing-implementation.md +#: src/android/aidl/types/file-descriptor.md +msgid "_birthday_service/src/lib.rs_:" +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "//! Implementation of the `IBirthdayService` AIDL interface.\n" +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "/// The `IBirthdayService` implementation.\n" +msgstr "" + +#: src/android/aidl/example-service/service.md +#: src/android/aidl/example-service/changing-implementation.md +#: src/android/aidl/types/file-descriptor.md +msgid "\"Happy Birthday {name}, congratulations with the {years} years!\"" +msgstr "" + +#: src/android/aidl/example-service/service.md +#: src/android/aidl/example-service/server.md +#: src/android/aidl/example-service/client.md +msgid "_birthday_service/Android.bp_:" +msgstr "" + +#: src/android/aidl/example-service/service.md +#: src/android/aidl/example-service/server.md +msgid "\"libbirthdayservice\"" +msgstr "" + +#: src/android/aidl/example-service/service.md +#: src/android/aidl/example-service/server.md +#: src/android/aidl/example-service/client.md +msgid "\"birthdayservice\"" +msgstr "" + +#: src/android/aidl/example-service/service.md +#: src/android/aidl/example-service/server.md +#: src/android/aidl/example-service/client.md +msgid "\"com.example.birthdayservice-rust\"" +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "" +"Point out the path to the generated `IBirthdayService` trait, and explain " +"why each of the segments is necessary." +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "" +"Note that `wishHappyBirthday` and other AIDL IPC methods take `&self` " +"(instead of `&mut self`)." +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "" +"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`." +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "" +"Any state that needs to be modified by the service will have to be put in " +"something like a `Mutex` to allow for safe mutation." +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "" +"The correct approach for managing service state depends heavily on the " +"details of your service." +msgstr "" + +#: src/android/aidl/example-service/service.md +msgid "" +"TODO: What does the `binder::Interface` trait do? Are there methods to " +"override? Where is the source?" +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "AIDL Server" +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "Finally, we can create a server which exposes the service:" +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "_birthday_service/src/server.rs_:" +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "//! Birthday service.\n" +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "/// Entry point for birthday service.\n" +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "\"Failed to register service\"" +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "\"birthday_server\"" +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "\"src/server.rs\"" +msgstr "" + +#: src/android/aidl/example-service/server.md +#: src/android/aidl/example-service/client.md +msgid "// To avoid dynamic link error.\n" +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "" +"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. 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." +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "Create an instance of your service type (`BirthdayService`)." +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "" +"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`." +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "" +"Call `add_service`, giving it a service identifier and your service object " +"(the `BnBirthdayService` object in the example)." +msgstr "" + +#: src/android/aidl/example-service/server.md +msgid "" +"Call `join_thread_pool` to add the current thread to Binder's thread pool " +"and start listening for connections." +msgstr "" + +#: src/android/aidl/example-service/deploy.md +msgid "We can now build, push, and start the service:" +msgstr "" + +#: src/android/aidl/example-service/deploy.md +msgid "" +"```shell\n" +"m birthday_server\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_server\" /data/local/" +"tmp\n" +"adb root\n" +"adb shell /data/local/tmp/birthday_server\n" +"```" +msgstr "" + +#: src/android/aidl/example-service/deploy.md +msgid "In another terminal, check that the service runs:" +msgstr "" + +#: src/android/aidl/example-service/deploy.md +msgid "You can also call the service with `service call`:" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "AIDL Client" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "Finally, we can create a Rust client for our new service." +msgstr "" + +#: src/android/aidl/example-service/client.md +#: src/android/aidl/example-service/changing-implementation.md +#: src/android/aidl/types/objects.md src/android/aidl/types/parcelables.md +#: src/android/aidl/types/file-descriptor.md +msgid "_birthday_service/src/client.rs_:" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "/// Call the birthday service.\n" +msgstr "" + +#: src/android/aidl/example-service/client.md src/android/aidl/types/objects.md +#: src/android/aidl/types/parcelables.md +#: src/android/aidl/types/file-descriptor.md +msgid "\"Failed to connect to BirthdayService\"" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "// Call the service.\n" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "\"{msg}\"" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "\"birthday_client\"" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "\"src/client.rs\"" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "Notice that the client does not depend on `libbirthdayservice`." +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "Build, push, and run the client on your device:" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "" +"```shell\n" +"m birthday_client\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_client\" /data/local/" +"tmp\n" +"adb shell /data/local/tmp/birthday_client Charlie 60\n" +"```" +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "" +"`Strong` is the trait object representing the service " +"that the client has connected to." +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "" +"`Strong` is a custom smart pointer type for Binder. It handles both an in-" +"process ref count for the service trait object, and the global Binder ref " +"count that tracks how many processes have a reference to the object." +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "" +"Note that the trait object that the client uses to talk to the service uses " +"the exact same trait that the server implements. For a given Binder " +"interface, there is a single Rust trait generated that both client and " +"server use." +msgstr "" + +#: src/android/aidl/example-service/client.md +msgid "" +"Use the same service identifier used when registering the service. This " +"should ideally be defined in a common crate that both the client and server " +"can depend on." +msgstr "" + +#: src/android/aidl/example-service/changing-definition.md +msgid "" +"Let's extend the API: we'll let clients specify a list of lines for the " +"birthday card:" +msgstr "" + +#: src/android/aidl/example-service/changing-definition.md +msgid "This results in an updated trait definition for `IBirthdayService`:" +msgstr "" + +#: src/android/aidl/example-service/changing-definition.md +msgid "" +"Note how the `String[]` in the AIDL definition is translated as a " +"`&[String]` in Rust, i.e. that idiomatic Rust types are used in the " +"generated bindings wherever possible:" +msgstr "" + +#: src/android/aidl/example-service/changing-definition.md +msgid "`in` array arguments are translated to slices." +msgstr "" + +#: src/android/aidl/example-service/changing-definition.md +msgid "`out` and `inout` args are translated to `&mut Vec`." +msgstr "" + +#: src/android/aidl/example-service/changing-definition.md +msgid "Return values are translated to returning a `Vec`." +msgstr "" + +#: src/android/aidl/example-service/changing-implementation.md +msgid "Updating Client and Service" +msgstr "" + +#: src/android/aidl/example-service/changing-implementation.md +msgid "Update the client and server code to account for the new API." +msgstr "" + +#: src/android/aidl/example-service/changing-implementation.md +msgid "'\\n'" +msgstr "" + +#: src/android/aidl/example-service/changing-implementation.md +msgid "\"Habby birfday to yuuuuu\"" +msgstr "" + +#: src/android/aidl/example-service/changing-implementation.md +msgid "\"And also: many more\"" +msgstr "" + +#: src/android/aidl/example-service/changing-implementation.md +msgid "" +"TODO: Move code snippets into project files where they'll actually be built?" +msgstr "" + +#: src/android/aidl/types.md +msgid "Working With AIDL Types" +msgstr "" + +#: src/android/aidl/types.md +msgid "AIDL types translate into the appropriate idiomatic Rust type:" +msgstr "" + +#: src/android/aidl/types.md +msgid "Primitive types map (mostly) to idiomatic Rust types." +msgstr "" + +#: src/android/aidl/types.md +msgid "Collection types like slices, `Vec`s and string types are supported." +msgstr "" + +#: src/android/aidl/types.md +msgid "" +"References to AIDL objects and file handles can be sent between clients and " +"services." +msgstr "" + +#: src/android/aidl/types.md +msgid "File handles and parcelables are fully supported." +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "Primitive types map (mostly) idiomatically:" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "AIDL Type" +msgstr "" + +#: src/android/aidl/types/primitives.md src/android/aidl/types/arrays.md +#: src/android/interoperability/cpp/type-mapping.md +msgid "Rust Type" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "Note" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`boolean`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`byte`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`i8`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "Note that bytes are signed." +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`u16`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "Note the usage of `u16`, NOT `u32`." +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`int`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`i32`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`long`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`i64`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`float`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`f32`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`double`" +msgstr "" + +#: src/android/aidl/types/primitives.md +msgid "`f64`" +msgstr "" + +#: src/android/aidl/types/arrays.md +msgid "" +"The array types (`T[]`, `byte[]`, and `List`) are translated to the " +"appropriate Rust array type depending on how they are used in the function " +"signature:" +msgstr "" + +#: src/android/aidl/types/arrays.md +msgid "Position" +msgstr "" + +#: src/android/aidl/types/arrays.md +msgid "`in` argument" +msgstr "" + +#: src/android/aidl/types/arrays.md +msgid "`&[T]`" +msgstr "" + +#: src/android/aidl/types/arrays.md +msgid "`out`/`inout` argument" +msgstr "" + +#: src/android/aidl/types/arrays.md +msgid "`&mut Vec`" +msgstr "" + +#: src/android/aidl/types/arrays.md +msgid "Return" +msgstr "" + +#: src/android/aidl/types/arrays.md +#: src/android/interoperability/cpp/type-mapping.md +msgid "`Vec`" +msgstr "" + +#: src/android/aidl/types/arrays.md +msgid "" +"In Android 13 or higher, fixed-size arrays are supported, i.e. `T[N]` " +"becomes `[T; N]`. Fixed-size arrays can have multiple dimensions (e.g. " +"`int[3][4]`). In the Java backend, fixed-size arrays are represented as " +"array types." +msgstr "" + +#: src/android/aidl/types/arrays.md +msgid "Arrays in parcelable fields always get translated to `Vec`." +msgstr "" + +#: src/android/aidl/types/objects.md +msgid "" +"AIDL objects can be sent either as a concrete AIDL type or as the type-" +"erased `IBinder` interface:" +msgstr "" + +#: src/android/aidl/types/objects.md +msgid "" +"_birthday_service/aidl/com/example/birthdayservice/IBirthdayInfoProvider." +"aidl_:" +msgstr "" + +#: src/android/aidl/types/objects.md +msgid "/** The same thing, but using a binder object. */" +msgstr "" + +#: src/android/aidl/types/objects.md +msgid "/** The same thing, but using `IBinder`. */" +msgstr "" + +#: src/android/aidl/types/objects.md +msgid "/// Rust struct implementing the `IBirthdayInfoProvider` interface.\n" +msgstr "" + +#: src/android/aidl/types/objects.md +msgid "// Create a binder object for the `IBirthdayInfoProvider` interface.\n" +msgstr "" + +#: src/android/aidl/types/objects.md +msgid "// Send the binder object to the service.\n" +msgstr "" + +#: src/android/aidl/types/objects.md +msgid "" +"// Perform the same operation but passing the provider as an `SpIBinder`.\n" +msgstr "" + +#: src/android/aidl/types/objects.md +msgid "" +"Note the usage of `BnBirthdayInfoProvider`. This serves the same purpose as " +"`BnBirthdayService` that we saw previously." +msgstr "" + +#: src/android/aidl/types/parcelables.md +msgid "Binder for Rust supports sending parcelables directly:" +msgstr "" + +#: src/android/aidl/types/parcelables.md +msgid "_birthday_service/aidl/com/example/birthdayservice/BirthdayInfo.aidl_:" +msgstr "" + +#: src/android/aidl/types/parcelables.md +msgid "/** The same thing, but with a parcelable. */" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "" +"Files can be sent between Binder clients/servers using the " +"`ParcelFileDescriptor` type:" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "/** The same thing, but loads info from a file. */" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "// Open a file and put the birthday info in it.\n" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "\"/data/local/tmp/birthday.info\"" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "\"{name}\"" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "\"{years}\"" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "// Create a `ParcelFileDescriptor` from the file and send it.\n" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "" +"// Convert the file descriptor to a `File`. `ParcelFileDescriptor` wraps\n" +" // an `OwnedFd`, which can be cloned and then used to create a " +"`File`\n" +" // object.\n" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "\"Invalid file handle\"" +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "" +"`ParcelFileDescriptor` wraps an `OwnedFd`, and so can be created from a " +"`File` (or any other type that wraps an `OwnedFd`), and can be used to " +"create a new `File` handle on the other side." +msgstr "" + +#: src/android/aidl/types/file-descriptor.md +msgid "" +"Other types of file descriptors can be wrapped and sent, e.g. TCP, UDP, and " +"UNIX sockets." +msgstr "" + +#: src/android/testing.md +msgid "Testing in Android" +msgstr "" + +#: 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 "" + +#: src/android/testing.md +msgid "_testing/Android.bp_:" +msgstr "" + +#: src/android/testing.md +msgid "\"libleftpad\"" +msgstr "" + +#: src/android/testing.md +msgid "\"leftpad\"" +msgstr "" + +#: src/android/testing.md +msgid "\"libleftpad_test\"" +msgstr "" + +#: src/android/testing.md +msgid "\"leftpad_test\"" +msgstr "" + +#: src/android/testing.md src/android/interoperability/with-c/run-our-binary.md +msgid "\"general-tests\"" +msgstr "" + +#: src/android/testing.md +msgid "\"libgoogletest_example\"" +msgstr "" + +#: src/android/testing.md +msgid "\"googletest_example\"" +msgstr "" + +#: src/android/testing.md +msgid "\"googletest.rs\"" +msgstr "" + +#: src/android/testing.md +msgid "\"libgoogletest_rust\"" +msgstr "" + +#: src/android/testing.md +msgid "\"libmockall_example\"" +msgstr "" + +#: src/android/testing.md +msgid "\"mockall_example\"" +msgstr "" + +#: src/android/testing.md +msgid "\"mockall.rs\"" +msgstr "" + +#: src/android/testing.md +msgid "\"libmockall\"" +msgstr "" + +#: src/android/testing.md +msgid "_testing/src/lib.rs_:" +msgstr "" + +#: src/android/testing.md +msgid "//! Left-padding library.\n" +msgstr "" + +#: src/android/testing.md +msgid "/// Left-pad `s` to `width`.\n" +msgstr "" + +#: src/android/testing.md +msgid "\"{s:>width$}\"" +msgstr "" + +#: src/android/testing.md +msgid "\" foo\"" +msgstr "" + +#: src/android/testing.md +msgid "\"foobar\"" +msgstr "" + +#: src/android/testing.md +msgid "You can now run the test with" +msgstr "" + +#: src/android/testing.md +msgid "The output looks like this:" +msgstr "" + +#: src/android/testing.md +msgid "" +"```text\n" +"INFO: Elapsed time: 2.666s, Critical Path: 2.40s\n" +"INFO: 3 processes: 2 internal, 1 linux-sandbox.\n" +"INFO: Build completed successfully, 3 total actions\n" +"//comprehensive-rust-android/testing:libleftpad_test_host PASSED " +"in 2.3s\n" +" PASSED libleftpad_test.tests::long_string (0.0s)\n" +" PASSED libleftpad_test.tests::short_string (0.0s)\n" +"Test cases: finished with 2 passing and 0 failing out of 2 test cases\n" +"```" +msgstr "" + +#: src/android/testing.md +msgid "" +"Notice how you only mention the root of the library crate. Tests are found " +"recursively in nested modules." +msgstr "" + +#: src/android/testing/googletest.md +msgid "" +"The [GoogleTest](https://docs.rs/googletest/) crate allows for flexible test " +"assertions using _matchers_:" +msgstr "" + +#: src/android/testing/googletest.md +msgid "\"bar\"" +msgstr "" + +#: src/android/testing/googletest.md +msgid "\"baz\"" +msgstr "" + +#: src/android/testing/googletest.md +msgid "\"xyz\"" +msgstr "" + +#: src/android/testing/googletest.md +msgid "" +"If we change the last element to `\"!\"`, the test fails with a structured " +"error message pin-pointing the error:" +msgstr "" + +#: src/android/testing/googletest.md +msgid "" +"GoogleTest is not part of the Rust Playground, so you need to run this " +"example in a local environment. Use `cargo add googletest` to quickly add it " +"to an existing Cargo project." +msgstr "" + +#: src/android/testing/googletest.md +msgid "" +"The `use googletest::prelude::*;` line imports a number of [commonly used " +"macros and types](https://docs.rs/googletest/latest/googletest/prelude/index." +"html)." +msgstr "" + +#: src/android/testing/googletest.md +msgid "" +"This just scratches the surface, there are many builtin matchers. Consider " +"going through the first chapter of [\"Advanced testing for Rust " +"applications\"](https://rust-exercises.com/advanced-testing/), a self-guided " +"Rust course: it provides a guided introduction to the library, with " +"exercises to help you get comfortable with `googletest` macros, its matchers " +"and its overall philosophy." +msgstr "" + +#: src/android/testing/googletest.md +msgid "" +"A particularly nice feature is that mismatches in multi-line strings are " +"shown as a diff:" +msgstr "" + +#: src/android/testing/googletest.md +msgid "" +"\"Memory safety found,\\n\\\n" +" Rust's strong typing guides the way,\\n\\\n" +" Secure code you'll write.\"" +msgstr "" + +#: src/android/testing/googletest.md +msgid "" +"\"Memory safety found,\\n\\\n" +" Rust's silly humor guides the way,\\n\\\n" +" Secure code you'll write.\"" +msgstr "" + +#: src/android/testing/googletest.md +msgid "shows a color-coded diff (colors not shown here):" +msgstr "" + +#: src/android/testing/googletest.md +msgid "" +"The crate is a Rust port of [GoogleTest for C++](https://google.github.io/" +"googletest/)." +msgstr "" + +#: src/android/testing/mocking.md +msgid "" +"For mocking, [Mockall](https://docs.rs/mockall/) is a widely used library. " +"You need to refactor your code to use traits, which you can then quickly " +"mock:" +msgstr "" + +#: src/android/testing/mocking.md +msgid "" +"Mockall is the recommended mocking library in Android (AOSP). There are " +"other [mocking libraries available on crates.io](https://crates.io/keywords/" +"mock), in particular in the area of mocking HTTP services. The other mocking " +"libraries work in a similar fashion as Mockall, meaning that they make it " +"easy to get a mock implementation of a given trait." +msgstr "" + +#: src/android/testing/mocking.md +msgid "" +"Note that mocking is somewhat _controversial_: mocks allow you to completely " +"isolate a test from its dependencies. The immediate result is faster and " +"more stable test execution. On the other hand, the mocks can be configured " +"wrongly and return output different from what the real dependencies would do." +msgstr "" + +#: src/android/testing/mocking.md +msgid "" +"If at all possible, it is recommended that you use the real dependencies. As " +"an example, many databases allow you to configure an in-memory backend. This " +"means that you get the correct behavior in your tests, plus they are fast " +"and will automatically clean up after themselves." +msgstr "" + +#: src/android/testing/mocking.md +msgid "" +"Similarly, many web frameworks allow you to start an in-process server which " +"binds to a random port on `localhost`. Always prefer this over mocking away " +"the framework since it helps you test your code in the real environment." +msgstr "" + +#: src/android/testing/mocking.md +msgid "" +"Mockall is not part of the Rust Playground, so you need to run this example " +"in a local environment. Use `cargo add mockall` to quickly add Mockall to an " +"existing Cargo project." +msgstr "" + +#: src/android/testing/mocking.md +msgid "" +"Mockall has extensive functionality. In particular, you can set up " +"expectations which depend on the arguments passed. Here we use this to mock " +"a cat which becomes hungry 3 hours after the last time it was fed:" +msgstr "" + +#: src/android/testing/mocking.md +msgid "" +"You can use `.times(n)` to limit the number of times a mock method can be " +"called to `n` --- the mock will automatically panic when dropped if this " +"isn't satisfied." +msgstr "" + +#: src/android/logging.md +msgid "" +"You should use the `log` crate to automatically log to `logcat` (on-device) " +"or `stdout` (on-host):" +msgstr "" + +#: src/android/logging.md +msgid "_hello_rust_logs/Android.bp_:" +msgstr "" + +#: src/android/logging.md +msgid "\"hello_rust_logs\"" +msgstr "" + +#: src/android/logging.md +msgid "\"liblog_rust\"" +msgstr "" + +#: src/android/logging.md +msgid "\"liblogger\"" +msgstr "" + +#: src/android/logging.md +msgid "_hello_rust_logs/src/main.rs_:" +msgstr "" + +#: src/android/logging.md +msgid "//! Rust logging demo.\n" +msgstr "" + +#: src/android/logging.md +msgid "/// Logs a greeting.\n" +msgstr "" + +#: src/android/logging.md +msgid "\"rust\"" +msgstr "" + +#: src/android/logging.md +msgid "\"Starting program.\"" +msgstr "" + +#: src/android/logging.md +msgid "\"Things are going fine.\"" +msgstr "" + +#: src/android/logging.md +msgid "\"Something went wrong!\"" +msgstr "" + +#: src/android/logging.md src/android/interoperability/with-c/run-our-binary.md +#: src/android/interoperability/with-c/rust.md +msgid "Build, push, and run the binary on your device:" +msgstr "" + +#: src/android/logging.md +msgid "" +"```shell\n" +"m hello_rust_logs\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs\" /data/local/" +"tmp\n" +"adb shell /data/local/tmp/hello_rust_logs\n" +"```" +msgstr "" + +#: src/android/logging.md +msgid "The logs show up in `adb logcat`:" +msgstr "" + +#: src/android/logging.md +msgid "" +"The logger implementation in `liblogger` is only needed in the final binary, " +"if you're logging from a library you only need the `log` facade crate." +msgstr "" + +#: src/android/interoperability.md +msgid "" +"Rust has excellent support for interoperability with other languages. This " +"means that you can:" +msgstr "" + +#: src/android/interoperability.md +msgid "Call Rust functions from other languages." +msgstr "" + +#: src/android/interoperability.md +msgid "Call functions written in other languages from Rust." +msgstr "" + +#: src/android/interoperability.md +msgid "" +"When you call functions in a foreign language, you're using a _foreign " +"function interface_, also known as FFI." +msgstr "" + +#: src/android/interoperability.md +msgid "" +"This is a key ability of Rust: compiled code becomes indistinguishable from " +"compiled C or C++ code." +msgstr "" + +#: src/android/interoperability.md +msgid "" +"Technically, we say that Rust can be compiled to the same [ABI](https://en." +"wikipedia.org/wiki/Application_binary_interface) (application binary " +"interface) as C code." +msgstr "" + +#: src/android/interoperability/with-c.md +msgid "Interoperability with C" +msgstr "" + +#: src/android/interoperability/with-c.md +msgid "" +"Rust has full support for linking object files with a C calling convention. " +"Similarly, you can export Rust functions and call them from C." +msgstr "" + +#: src/android/interoperability/with-c.md +msgid "You can do it by hand if you want:" +msgstr "" + +#: src/android/interoperability/with-c.md src/unsafe-deep-dive/ffi/abs.md +msgid "\"{x}, {abs_x}\"" +msgstr "" + +#: src/android/interoperability/with-c.md +msgid "" +"We already saw this in the [Safe FFI Wrapper exercise](../../unsafe-rust/" +"exercise.md)." +msgstr "" + +#: src/android/interoperability/with-c.md +msgid "" +"This assumes full knowledge of the target platform. Not recommended for " +"production." +msgstr "" + +#: src/android/interoperability/with-c.md +msgid "We will look at better options next." +msgstr "" + +#: src/android/interoperability/with-c.md +msgid "" +"The [`\"C\"` part](https://doc.rust-lang.org/reference/items/external-blocks." +"html#abi) of the `extern` block tells Rust that `abs` can be called using " +"the C [ABI](https://en.wikipedia.org/wiki/Application_binary_interface) " +"(application binary interface)." +msgstr "" + +#: src/android/interoperability/with-c.md +msgid "" +"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." +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +msgid "Let's first create a small C library:" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +msgid "_interoperability/bindgen/libbirthday.h_:" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +msgid "_interoperability/bindgen/libbirthday.c_:" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +msgid "" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +#: src/android/interoperability/with-c/bindgen.md +msgid "\"libbirthday.h\"" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +msgid "\"+--------------\\n\"" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +msgid "\"| Happy Birthday %s!\\n\"" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +msgid "\"| Congratulations with the %i years!\\n\"" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +msgid "Add this to your `Android.bp` file:" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +#: src/android/interoperability/with-c/bindgen.md +#: src/android/interoperability/with-c/run-our-binary.md +msgid "_interoperability/bindgen/Android.bp_:" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +#: src/android/interoperability/with-c/bindgen.md +msgid "\"libbirthday\"" +msgstr "" + +#: src/android/interoperability/with-c/c-library.md +msgid "\"libbirthday.c\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "Using Bindgen" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "" +"The [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html) " +"tool can auto-generate bindings from a C header file." +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "" +"Create a wrapper header file for the library (not strictly needed in this " +"example):" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "\"libbirthday_bindgen\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "\"birthday_bindgen\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "\"libbirthday_wrapper.h\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "\"bindings\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "Finally, we can use the bindings in our Rust program:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "\"print_birthday_card\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "\"main.rs\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "_interoperability/bindgen/main.rs_:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "//! Bindgen demo.\n" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "" +"// SAFETY: The pointer we pass is valid because it came from a Rust\n" +" // reference, and the `name` it contains refers to `name` above which " +"also\n" +" // remains valid. `print_card` doesn't store either pointer to use " +"later\n" +" // after it returns.\n" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "" +"The Android build rules will automatically call `bindgen` for you behind the " +"scenes." +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md +msgid "" +"Notice that the Rust code in `main` is still hard to write. It is good " +"practice to encapsulate the output of `bindgen` in a Rust library which " +"exposes a safe interface to caller." +msgstr "" + +#: src/android/interoperability/with-c/run-our-binary.md +msgid "" +"```shell\n" +"m print_birthday_card\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/print_birthday_card\" /data/local/" +"tmp\n" +"adb shell /data/local/tmp/print_birthday_card\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/run-our-binary.md +msgid "Finally, we can run auto-generated tests to ensure the bindings work:" +msgstr "" + +#: src/android/interoperability/with-c/run-our-binary.md +msgid "\"libbirthday_bindgen_test\"" +msgstr "" + +#: src/android/interoperability/with-c/run-our-binary.md +msgid "\":libbirthday_bindgen\"" +msgstr "" + +#: src/android/interoperability/with-c/run-our-binary.md +msgid "\"none\"" +msgstr "" + +#: src/android/interoperability/with-c/run-our-binary.md +msgid "// Generated file, skip linting\n" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "" +"Exporting Rust functions and types to C is easy. Here's a simple Rust " +"library:" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "_interoperability/rust/libanalyze/analyze.rs_" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "//! Rust FFI demo.\n" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "" +"/// Analyze the numbers.\n" +"// SAFETY: There is no other global function of this name.\n" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "\"x ({x}) is smallest!\"" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "\"y ({y}) is probably larger than x ({x})\"" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "_interoperability/rust/libanalyze/Android.bp_" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +#: src/android/interoperability/with-c/rust.md +msgid "\"libanalyze_ffi\"" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "\"analyze_ffi\"" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "\"analyze.rs\"" +msgstr "" + +#: src/android/interoperability/with-c/rust-library.md +msgid "" +"`#[unsafe(no_mangle)]` disables Rust's usual name mangling, so the exported " +"symbol will just be the name of the function. You can also use " +"`#[unsafe(export_name = \"some_name\")]` to specify whatever name you want." +msgstr "" + +#: src/android/interoperability/with-c/rust.md +msgid "Calling Rust" +msgstr "" + +#: src/android/interoperability/with-c/rust.md +msgid "We can now call this from a C binary:" +msgstr "" + +#: src/android/interoperability/with-c/rust.md +msgid "_interoperability/rust/libanalyze/analyze.h_" +msgstr "" + +#: src/android/interoperability/with-c/rust.md +msgid "_interoperability/rust/analyze/main.c_" +msgstr "" + +#: src/android/interoperability/with-c/rust.md +msgid "\"analyze.h\"" +msgstr "" + +#: src/android/interoperability/with-c/rust.md +msgid "_interoperability/rust/analyze/Android.bp_" +msgstr "" + +#: src/android/interoperability/with-c/rust.md +msgid "\"analyze_numbers\"" +msgstr "" + +#: src/android/interoperability/with-c/rust.md +msgid "\"main.c\"" +msgstr "" + +#: src/android/interoperability/with-c/rust.md +msgid "" +"```shell\n" +"m analyze_numbers\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/analyze_numbers\" /data/local/" +"tmp\n" +"adb shell /data/local/tmp/analyze_numbers\n" +"```" +msgstr "" + +#: src/android/interoperability/cpp.md +msgid "" +"The [CXX crate](https://cxx.rs/) enables safe interoperability between Rust " +"and C++." +msgstr "" + +#: src/android/interoperability/cpp.md +msgid "The overall approach looks like this:" +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +msgid "" +"CXX relies on a description of the function signatures that will be exposed " +"from each language to the other. You provide this description using extern " +"blocks in a Rust module annotated with the `#[cxx::bridge]` attribute macro." +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +msgid "\"org::blobstore\"" +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +msgid "// Shared structs with fields visible to both languages.\n" +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +#: src/android/interoperability/cpp/generated-cpp.md +msgid "// Rust types and signatures exposed to C++.\n" +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +#: src/android/interoperability/cpp/rust-bridge.md +#: src/android/interoperability/cpp/generated-cpp.md +#: src/android/interoperability/cpp/rust-result.md +#: src/chromium/interoperability-with-cpp/example-bindings.md +#: src/chromium/interoperability-with-cpp/error-handling-qr.md +#: src/chromium/interoperability-with-cpp/error-handling-png.md +msgid "\"Rust\"" +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +#: src/android/interoperability/cpp/cpp-bridge.md +msgid "// C++ types and signatures exposed to Rust.\n" +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +#: src/android/interoperability/cpp/cpp-bridge.md +#: src/android/interoperability/cpp/cpp-exception.md +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "\"C++\"" +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +#: src/android/interoperability/cpp/cpp-bridge.md +msgid "\"include/blobstore.h\"" +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +msgid "The bridge is generally declared in an `ffi` module within your crate." +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +msgid "" +"From the declarations made in the bridge module, CXX will generate matching " +"Rust and C++ type/function definitions in order to expose those items to " +"both languages." +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +msgid "" +"To view the generated Rust code, use [cargo-expand](https://github.com/" +"dtolnay/cargo-expand) to view the expanded proc macro. For most of the " +"examples you would use `cargo expand ::ffi` to expand just the `ffi` module " +"(though this doesn't apply for Android projects)." +msgstr "" + +#: src/android/interoperability/cpp/bridge.md +msgid "To view the generated C++ code, look in `target/cxxbridge`." +msgstr "" + +#: src/android/interoperability/cpp/rust-bridge.md +msgid "Rust Bridge Declarations" +msgstr "" + +#: src/android/interoperability/cpp/rust-bridge.md +msgid "// Opaque type\n" +msgstr "" + +#: src/android/interoperability/cpp/rust-bridge.md +msgid "// Method on `MyType`\n" +msgstr "" + +#: src/android/interoperability/cpp/rust-bridge.md +msgid "// Free function\n" +msgstr "" + +#: src/android/interoperability/cpp/rust-bridge.md +msgid "" +"Items declared in the `extern \"Rust\"` reference items that are in scope in " +"the parent module." +msgstr "" + +#: src/android/interoperability/cpp/rust-bridge.md +msgid "" +"The CXX code generator uses your `extern \"Rust\"` section(s) to produce a C+" +"+ header file containing the corresponding C++ declarations. The generated " +"header has the same path as the Rust source file containing the bridge, " +"except with a .rs.h file extension." +msgstr "" + +#: src/android/interoperability/cpp/generated-cpp.md +msgid "Results in (roughly) the following C++:" +msgstr "" + +#: src/android/interoperability/cpp/cpp-bridge.md +msgid "C++ Bridge Declarations" +msgstr "" + +#: src/android/interoperability/cpp/cpp-bridge.md +msgid "Results in (roughly) the following Rust:" +msgstr "" + +#: src/android/interoperability/cpp/cpp-bridge.md +msgid "\"org$blobstore$cxxbridge1$new_blobstore_client\"" +msgstr "" + +#: src/android/interoperability/cpp/cpp-bridge.md +msgid "\"org$blobstore$cxxbridge1$BlobstoreClient$put\"" +msgstr "" + +#: src/android/interoperability/cpp/cpp-bridge.md +msgid "" +"The programmer does not need to promise that the signatures they have typed " +"in are accurate. CXX performs static assertions that the signatures exactly " +"correspond with what is declared in C++." +msgstr "" + +#: src/android/interoperability/cpp/cpp-bridge.md +msgid "" +"`unsafe extern` blocks allow you to declare C++ functions that are safe to " +"call from Rust." +msgstr "" + +#: src/android/interoperability/cpp/shared-types.md +msgid "// A=1, J=11, Q=12, K=13\n" +msgstr "" + +#: src/android/interoperability/cpp/shared-types.md +msgid "Only C-like (unit) enums are supported." +msgstr "" + +#: src/android/interoperability/cpp/shared-types.md +msgid "" +"A limited number of traits are supported for `#[derive()]` on shared types. " +"Corresponding functionality is also generated for the C++ code, e.g. if you " +"derive `Hash` also generates an implementation of `std::hash` for the " +"corresponding C++ type." +msgstr "" + +#: src/android/interoperability/cpp/shared-enums.md +msgid "Generated Rust:" +msgstr "" + +#: src/android/interoperability/cpp/shared-enums.md +msgid "Generated C++:" +msgstr "" + +#: src/android/interoperability/cpp/shared-enums.md +msgid "" +"On the Rust side, the code generated for shared enums is actually a struct " +"wrapping a numeric value. This is because it is not UB in C++ for an enum " +"class to hold a value different from all of the listed variants, and our " +"Rust representation needs to have the same behavior." +msgstr "" + +#: src/android/interoperability/cpp/rust-result.md +msgid "\"fallible1 requires depth > 0\"" +msgstr "" + +#: src/android/interoperability/cpp/rust-result.md +msgid "\"Success!\"" +msgstr "" + +#: src/android/interoperability/cpp/rust-result.md +msgid "" +"Rust functions that return `Result` are translated to exceptions on the C++ " +"side." +msgstr "" + +#: src/android/interoperability/cpp/rust-result.md +msgid "" +"The exception thrown will always be of type `rust::Error`, which primarily " +"exposes a way to get the error message string. The error message will come " +"from the error type's `Display` impl." +msgstr "" + +#: src/android/interoperability/cpp/rust-result.md +msgid "" +"A panic unwinding from Rust to C++ will always cause the process to " +"immediately terminate." +msgstr "" + +#: src/android/interoperability/cpp/cpp-exception.md +msgid "\"example/include/example.h\"" +msgstr "" + +#: src/android/interoperability/cpp/cpp-exception.md +msgid "\"Error: {}\"" +msgstr "" + +#: src/android/interoperability/cpp/cpp-exception.md +msgid "" +"C++ functions declared to return a `Result` will catch any thrown exception " +"on the C++ side and return it as an `Err` value to the calling Rust function." +msgstr "" + +#: src/android/interoperability/cpp/cpp-exception.md +msgid "" +"If an exception is thrown from an extern \"C++\" function that is not " +"declared by the CXX bridge to return `Result`, the program calls C++'s `std::" +"terminate`. The behavior is equivalent to the same exception being thrown " +"through a `noexcept` C++ function." +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "C++ Type" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`rust::String`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`&str`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`rust::Str`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`CxxString`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`std::string`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`&[T]`/`&mut [T]`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`rust::Slice`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`rust::Box`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`UniquePtr`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`std::unique_ptr`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`rust::Vec`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`CxxVector`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "`std::vector`" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "" +"These types can be used in the fields of shared structs and the arguments " +"and returns of extern functions." +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "" +"Note that Rust's `String` does not map directly to `std::string`. There are " +"a few reasons for this:" +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "" +"`std::string` does not uphold the UTF-8 invariant that `String` requires." +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "" +"The two types have different layouts in memory and so can't be passed " +"directly between languages." +msgstr "" + +#: src/android/interoperability/cpp/type-mapping.md +msgid "" +"`std::string` requires move constructors that don't match Rust's move " +"semantics, so a `std::string` can't be passed by value to Rust." +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +#: src/android/interoperability/cpp/android-build-cpp.md +#: src/android/interoperability/cpp/android-build-rust.md +msgid "Building in Android" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "" +"Create two genrules: One to generate the CXX header, and one to generate the " +"CXX source file. These are then used as inputs to the `cc_library_static`." +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "" +"// Generate a C++ header containing the C++ bindings\n" +"// to the Rust exported functions in lib.rs.\n" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +#: src/android/interoperability/cpp/android-build-cpp.md +msgid "\"libcxx_test_bridge_header\"" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "\"cxxbridge\"" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "\"$(location cxxbridge) $(in) --header > $(out)\"" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +#: src/android/interoperability/cpp/android-build-rust.md +msgid "\"lib.rs\"" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "\"lib.rs.h\"" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "// Generate the C++ code that Rust calls into.\n" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +#: src/android/interoperability/cpp/android-build-cpp.md +msgid "\"libcxx_test_bridge_code\"" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "\"$(location cxxbridge) $(in) > $(out)\"" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "\"lib.rs.cc\"" +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "" +"The `cxxbridge` tool is a standalone tool that generates the C++ side of the " +"bridge module. It is included in Android and available as a Soong tool." +msgstr "" + +#: src/android/interoperability/cpp/android-cpp-genrules.md +msgid "" +"By convention, if your Rust source file is `lib.rs` your header file will be " +"named `lib.rs.h` and your source file will be named `lib.rs.cc`. This naming " +"convention isn't enforced, though." +msgstr "" + +#: src/android/interoperability/cpp/android-build-cpp.md +msgid "" +"Create a `cc_library_static` to build the C++ library, including the CXX " +"generated header and source file." +msgstr "" + +#: src/android/interoperability/cpp/android-build-cpp.md +#: src/android/interoperability/cpp/android-build-rust.md +msgid "\"libcxx_test_cpp\"" +msgstr "" + +#: src/android/interoperability/cpp/android-build-cpp.md +msgid "\"cxx_test.cpp\"" +msgstr "" + +#: src/android/interoperability/cpp/android-build-cpp.md +msgid "\"cxx-bridge-header\"" +msgstr "" + +#: src/android/interoperability/cpp/android-build-cpp.md +msgid "" +"Point out that `libcxx_test_bridge_header` and `libcxx_test_bridge_code` are " +"the dependencies for the CXX-generated C++ bindings. We'll show how these " +"are setup on the next slide." +msgstr "" + +#: src/android/interoperability/cpp/android-build-cpp.md +msgid "" +"Note that you also need to depend on the `cxx-bridge-header` library in " +"order to pull in common CXX definitions." +msgstr "" + +#: src/android/interoperability/cpp/android-build-cpp.md +msgid "" +"Full docs for using CXX in Android can be found in [the Android docs]" +"(https://source.android.com/docs/setup/build/rust/building-rust-modules/" +"android-rust-patterns#rust-cpp-interop-using-cxx). You may want to share " +"that link with the class so that students know where they can find these " +"instructions again in the future." +msgstr "" + +#: src/android/interoperability/cpp/android-build-rust.md +msgid "" +"Create a `rust_binary` that depends on `libcxx` and your `cc_library_static`." +msgstr "" + +#: src/android/interoperability/cpp/android-build-rust.md +msgid "\"cxx_test\"" +msgstr "" + +#: src/android/interoperability/cpp/android-build-rust.md +msgid "\"libcxx\"" +msgstr "" + +#: src/android/interoperability/java.md +msgid "Interoperability with Java" +msgstr "" + +#: src/android/interoperability/java.md +msgid "" +"Java can load shared objects via [Java Native Interface (JNI)](https://en." +"wikipedia.org/wiki/Java_Native_Interface). The [`jni` crate](https://docs.rs/" +"jni/) allows you to create a compatible library." +msgstr "" + +#: src/android/interoperability/java.md +msgid "First, we create a Rust function to export to Java:" +msgstr "" + +#: src/android/interoperability/java.md +msgid "_interoperability/java/src/lib.rs_:" +msgstr "" + +#: src/android/interoperability/java.md +msgid "//! Rust <-> Java FFI demo.\n" +msgstr "" + +#: src/android/interoperability/java.md +msgid "" +"/// HelloWorld::hello method implementation.\n" +"// SAFETY: There is no other global function of this name.\n" +msgstr "" + +#: src/android/interoperability/java.md +msgid "\"system\"" +msgstr "" + +#: src/android/interoperability/java.md +msgid "\"Hello, {input}!\"" +msgstr "" + +#: src/android/interoperability/java.md +msgid "_interoperability/java/Android.bp_:" +msgstr "" + +#: src/android/interoperability/java.md +msgid "\"libhello_jni\"" +msgstr "" + +#: src/android/interoperability/java.md +msgid "\"hello_jni\"" +msgstr "" + +#: src/android/interoperability/java.md +msgid "\"libjni\"" +msgstr "" + +#: src/android/interoperability/java.md +msgid "We then call this function from Java:" +msgstr "" + +#: src/android/interoperability/java.md +msgid "_interoperability/java/HelloWorld.java_:" +msgstr "" + +#: src/android/interoperability/java.md +msgid "\"helloworld_jni\"" +msgstr "" + +#: src/android/interoperability/java.md +msgid "\"HelloWorld.java\"" +msgstr "" + +#: src/android/interoperability/java.md +msgid "\"HelloWorld\"" +msgstr "" + +#: src/android/interoperability/java.md +msgid "Finally, you can build, sync, and run the binary:" +msgstr "" + +#: src/android/interoperability/java.md +msgid "" +"The `unsafe(no_mangle)` attribute instructs Rust to emit the " +"`Java_HelloWorld_hello` symbol exactly as written. This is important so that " +"Java can recognize the symbol as a `hello` method on the `HelloWorld` class." +msgstr "" + +#: src/android/interoperability/java.md +msgid "" +"By default, Rust will mangle (rename) symbols so that a binary can link in " +"two versions of the same Rust crate." +msgstr "" + +#: src/chromium.md +msgid "Welcome to Rust in Chromium" +msgstr "" + +#: src/chromium.md +msgid "" +"Rust is supported for third-party libraries in Chromium, with first-party " +"glue code to connect between Rust and existing Chromium C++ code." +msgstr "" + +#: src/chromium.md +msgid "" +"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 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." +msgstr "" + +#: src/chromium/setup.md +msgid "" +"Make sure you can build and run Chromium. Any platform and set of build " +"flags is OK, so long as your code is relatively recent (commit position " +"1223636 onwards, corresponding to November 2023):" +msgstr "" + +#: src/chromium/setup.md +msgid "" +"(A component, debug build is recommended for quickest iteration time. This " +"is the default!)" +msgstr "" + +#: src/chromium/setup.md +msgid "" +"See [How to build Chromium](https://www.chromium.org/developers/how-tos/get-" +"the-code/) if you aren't already at that point. Be warned: setting up to " +"build Chromium takes time." +msgstr "" + +#: src/chromium/setup.md +msgid "It's also recommended that you have Visual Studio code installed." +msgstr "" + +#: src/chromium/setup.md +msgid "About the exercises" +msgstr "" + +#: src/chromium/setup.md +msgid "" +"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." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"The Rust community typically uses `cargo` and libraries from [crates.io]" +"(https://crates.io/). Chromium is built using `gn` and `ninja` and a curated " +"set of dependencies." +msgstr "" + +#: src/chromium/cargo.md +msgid "When writing code in Rust, your choices are:" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Use `gn` and `ninja` with the help of the templates from `//build/rust/*." +"gni` (e.g. `rust_static_library` that we'll meet later). This uses " +"Chromium's audited toolchain and crates." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Use `cargo`, but [restrict yourself to Chromium's audited toolchain and " +"crates](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/" +"docs/rust.md#Using-cargo)" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Use `cargo`, trusting a [toolchain](https://rustup.rs/) and/or [crates " +"downloaded from the internet](https://crates.io/)" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"From here on we'll be focusing on `gn` and `ninja`, because this is how Rust " +"code can be built into the Chromium browser. At the same time, Cargo is an " +"important part of the Rust ecosystem and you should keep it in your toolbox." +msgstr "" + +#: src/chromium/cargo.md +msgid "Mini exercise" +msgstr "" + +#: src/chromium/cargo.md +msgid "Split into small groups and:" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Brainstorm scenarios where `cargo` may offer an advantage and assess the " +"risk profile of these scenarios." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Discuss which tools, libraries, and groups of people need to be trusted when " +"using `gn` and `ninja`, offline `cargo`, etc." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Ask students to avoid peeking at the speaker notes before completing the " +"exercise. Assuming folks taking the course are physically together, ask them " +"to discuss in small groups of 3-4 people." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Notes/hints related to the first part of the exercise (\"scenarios where " +"Cargo may offer an advantage\"):" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"It's fantastic that when writing a tool, or prototyping a part of Chromium, " +"one has access to the rich ecosystem of crates.io libraries. There is a " +"crate for almost anything and they are typically quite pleasant to use. " +"(`clap` for command-line parsing, `serde` for serializing/deserializing to/" +"from various formats, `itertools` for working with iterators, etc.)." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"`cargo` makes it easy to try a library (just add a single line to `Cargo." +"toml` and start writing code)" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"It may be worth comparing how CPAN helped make `perl` a popular choice. Or " +"comparing with `python` + `pip`." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Development experience is made really nice not only by core Rust tools (e.g. " +"using `rustup` to switch to a different `rustc` version when testing a crate " +"that needs to work on nightly, current stable, and older stable) but also by " +"an ecosystem of third-party tools (e.g. Mozilla provides `cargo vet` for " +"streamlining and sharing security audits; `criterion` crate gives a " +"streamlined way to run benchmarks)." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"`cargo` makes it easy to add a tool via `cargo install --locked cargo-vet`." +msgstr "" + +#: src/chromium/cargo.md +msgid "It may be worth comparing with Chrome Extensions or VScode extensions." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Broad, generic examples of projects where `cargo` may be the right choice:" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"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 type " +"system) and running faster (as a compiled, rather than interpreted language)." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Participating in the Rust ecosystem requires using standard Rust tools like " +"Cargo. Libraries that want to get external contributions, and want to be " +"used outside of Chromium (e.g. in Bazel or Android/Soong build environments) " +"should use Cargo." +msgstr "" + +#: src/chromium/cargo.md +msgid "Examples of Chromium-related projects that are `cargo`\\-based:" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"`serde_json_lenient` (experimented with in other parts of Google which " +"resulted in PRs with performance improvements)" +msgstr "" + +#: src/chromium/cargo.md +msgid "Fontations libraries like `font-types`" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"`gnrt` tool (we will meet it later in the course) which depends on `clap` " +"for command-line parsing and on `toml` for configuration files." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Disclaimer: a unique reason for using `cargo` was unavailability of `gn` " +"when building and bootstrapping Rust standard library when building Rust " +"toolchain." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"`run_gnrt.py` uses Chromium's copy of `cargo` and `rustc`. `gnrt` depends on " +"third-party libraries downloaded from the internet, but `run_gnrt.py` asks " +"`cargo` that only `--locked` content is allowed via `Cargo.lock`.)" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Students may identify the following items as being implicitly or explicitly " +"trusted:" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"`rustc` (the Rust compiler) which in turn depends on the LLVM libraries, the " +"Clang compiler, the `rustc` sources (fetched from GitHub, reviewed by Rust " +"compiler team), binary Rust compiler downloaded for bootstrapping" +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"`rustup` (it may be worth pointing out that `rustup` is developed under the " +"umbrella of the https://github.com/rust-lang/ organization - same as `rustc`)" +msgstr "" + +#: src/chromium/cargo.md +msgid "`cargo`, `rustfmt`, etc." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Various internal infrastructure (bots that build `rustc`, system for " +"distributing the prebuilt toolchain to Chromium engineers, etc.)" +msgstr "" + +#: src/chromium/cargo.md +msgid "Cargo tools like `cargo audit`, `cargo vet`, etc." +msgstr "" + +#: src/chromium/cargo.md +msgid "" +"Rust libraries vendored into `//third_party/rust` (audited by " +"security@chromium.org)" +msgstr "" + +#: src/chromium/cargo.md +msgid "Other Rust libraries (some niche, some quite popular and commonly used)" +msgstr "" + +#: src/chromium/policy.md +msgid "Chromium Rust policy" +msgstr "" + +#: src/chromium/policy.md +msgid "" +"Chromium's Rust policy can be found [here](https://source.chromium.org/" +"chromium/chromium/src/+/main:docs/rust.md;l=22). Rust can be used for both " +"first-party and third-party code." +msgstr "" + +#: src/chromium/policy.md +msgid "Using Rust for pure first-party code looks like this:" +msgstr "" + +#: src/chromium/policy.md +msgid "" +"```bob\n" +"\"C++\" Rust\n" +".- - - - - - - - - -. .- - - - - - - - - - -.\n" +": : : :\n" +": Existing Chromium : : Chromium Rust :\n" +": \"C++\" : : code :\n" +": +---------------+ : : +----------------+ :\n" +": | | : : | | :\n" +": | o-----+-+-----------+-+-> | :\n" +": | | : Language : | | :\n" +": +---------------+ : boundary : +----------------+ :\n" +": : : :\n" +"`- - - - - - - - - -' `- - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/chromium/policy.md +msgid "" +"The third-party case is also common. You will typically also need a small " +"amount of first-party glue code, because very few Rust libraries directly " +"expose a C/C++ API." +msgstr "" + +#: src/chromium/policy.md +msgid "" +"```bob\n" +"\"C++\" Rust\n" +".- - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - " +"-.\n" +": : : :\n" +": Existing Chromium : : Chromium Rust Existing " +"Rust :\n" +": \"C++\" : : \"wrapper\" " +"crate :\n" +": +---------------+ : : +----------------+ +-------------" +"+ :\n" +": | | : : | | | " +"| :\n" +": | o-----+-+-----------+-+-> o-+----------+--> " +"| :\n" +": | | : Language : | | Crate | " +"| :\n" +": +---------------+ : boundary : +----------------+ API +-------------" +"+ :\n" +": : : :\n" +"`- - - - - - - - - -' `- - - - - - - - - - - - - - - - - - - - - - " +"-'\n" +"```" +msgstr "" + +#: src/chromium/policy.md +msgid "" +"The scenario of using a third-party crate is the more complex one, so " +"today's course will focus on:" +msgstr "" + +#: src/chromium/policy.md +msgid "Bringing in third-party Rust libraries (\"crates\")" +msgstr "" + +#: src/chromium/policy.md +msgid "" +"Writing glue code to be able to use those crates from Chromium C++. (The " +"same techniques are used when working with first-party Rust code)." +msgstr "" + +#: src/chromium/build-rules.md +msgid "Build rules" +msgstr "" + +#: src/chromium/build-rules.md +msgid "" +"Rust code is typically built using `cargo`. Chromium builds with `gn` and " +"`ninja` for efficiency --- its static rules allow maximum parallelism. Rust " +"is no exception." +msgstr "" + +#: src/chromium/build-rules.md +msgid "Adding Rust code to Chromium" +msgstr "" + +#: src/chromium/build-rules.md +msgid "" +"In some existing Chromium `BUILD.gn` file, declare a `rust_static_library`:" +msgstr "" + +#: src/chromium/build-rules.md +msgid "" +"```gn\n" +"import(\"//build/rust/rust_static_library.gni\")\n" +"\n" +"rust_static_library(\"my_rust_lib\") {\n" +" crate_root = \"lib.rs\"\n" +" sources = [ \"lib.rs\" ]\n" +"}\n" +"```" +msgstr "" + +#: src/chromium/build-rules.md +msgid "" +"You can also add `deps` on other Rust targets. Later we'll use this to " +"depend upon third party code." +msgstr "" + +#: src/chromium/build-rules.md +msgid "" +"You must specify _both_ the crate root, _and_ a full list of sources. The " +"`crate_root` is the file given to the Rust compiler representing the root " +"file of the compilation unit --- typically `lib.rs`. `sources` is a complete " +"list of all source files which `ninja` needs in order to determine when " +"rebuilds are necessary." +msgstr "" + +#: src/chromium/build-rules.md +msgid "" +"(There's no such thing as a Rust `source_set`, because in Rust, an entire " +"crate is a compilation unit. A `static_library` is the smallest unit.)" +msgstr "" + +#: src/chromium/build-rules.md +msgid "" +"Students might be wondering why we need a gn template, rather than using " +"[gn's built-in support for Rust static libraries](https://gn.googlesource." +"com/gn/+/main/docs/reference.md#func_static_library). The answer is that " +"this template provides support for CXX interop, Rust features, and unit " +"tests, some of which we'll use later." +msgstr "" + +#: src/chromium/build-rules/unsafe.md +msgid "Including `unsafe` Rust Code" +msgstr "" + +#: src/chromium/build-rules/unsafe.md +msgid "" +"Unsafe Rust code is forbidden in `rust_static_library` by default --- it " +"won't compile. If you need unsafe Rust code, add `allow_unsafe = true` to " +"the gn target. (Later in the course we'll see circumstances where this is " +"necessary.)" +msgstr "" + +#: src/chromium/build-rules/unsafe.md +msgid "" +"```gn\n" +"import(\"//build/rust/rust_static_library.gni\")\n" +"\n" +"rust_static_library(\"my_rust_lib\") {\n" +" crate_root = \"lib.rs\"\n" +" sources = [\n" +" \"lib.rs\",\n" +" \"hippopotamus.rs\"\n" +" ]\n" +" allow_unsafe = true\n" +"}\n" +"```" +msgstr "" + +#: src/chromium/build-rules/depending.md +msgid "Simply add the above target to the `deps` of some Chromium C++ target." +msgstr "" + +#: src/chromium/build-rules/depending.md +msgid "" +"```gn\n" +"import(\"//build/rust/rust_static_library.gni\")\n" +"\n" +"rust_static_library(\"my_rust_lib\") {\n" +" crate_root = \"lib.rs\"\n" +" sources = [ \"lib.rs\" ]\n" +"}\n" +"\n" +"# or source_set, static_library etc.\n" +"component(\"preexisting_cpp\") {\n" +" deps = [ \":my_rust_lib\" ]\n" +"}\n" +"```" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"Types are elided in Rust code, which makes a good IDE even more useful than " +"for C++. Visual Studio code works well for Rust in Chromium. To use it," +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"Ensure your VSCode has the `rust-analyzer` extension, not earlier forms of " +"Rust support" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"`gn gen out/Debug --export-rust-project` (or equivalent for your output " +"directory)" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "`ln -s out/Debug/rust-project.json rust-project.json`" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"A demo of some of the code annotation and exploration features of rust-" +"analyzer might be beneficial if the audience are naturally skeptical of IDEs." +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"The following steps may help with the demo (but feel free to instead use a " +"piece of Chromium-related Rust that you are most familiar with):" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "Open `components/qr_code_generator/qr_code_generator_ffi_glue.rs`" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"Place the cursor over the `QrCode::new` call (around line 26) in " +"\\`qr_code_generator_ffi_glue.rs" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"Demo **show documentation** (typical bindings: vscode = ctrl k i; vim/CoC = " +"K)." +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"Demo **go to definition** (typical bindings: vscode = F12; vim/CoC = g d). " +"(This will take you to `//third_party/rust/.../qr_code-.../src/lib.rs`.)" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"Demo **outline** and navigate to the `QrCode::with_bits` method (around line " +"164; the outline is in the file explorer pane in vscode; typical vim/CoC " +"bindings = space o)" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"Demo **type annotations** (there are quite a few nice examples in the " +"`QrCode::with_bits` method)" +msgstr "" + +#: src/chromium/build-rules/vscode.md +msgid "" +"It may be worth pointing out that `gn gen ... --export-rust-project` will " +"need to be rerun after editing `BUILD.gn` files (which we will do a few " +"times throughout the exercises in this session)." +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "Build rules exercise" +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"In your Chromium build, add a new Rust target to `//ui/base/BUILD.gn` " +"containing:" +msgstr "" + +#: src/exercises/chromium/build-rules.md src/bare-metal/aps/inline-assembly.md +#: src/bare-metal/aps/uart/using.md src/bare-metal/aps/safemmio/using.md +#: src/bare-metal/aps/logging/using.md +msgid "// SAFETY: There is no other global function of this name.\n" +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"**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." +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"Add this new Rust target as a dependency of `//ui/base:base`. Declare this " +"function at the top of `ui/base/resource/resource_bundle.cc` (later, we'll " +"see how this can be automated by bindings generation tools):" +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"Call this function from somewhere in `ui/base/resource/resource_bundle.cc` - " +"we suggest the top of `ResourceBundle::MaybeMangleLocalizedString`. Build " +"and run Chromium, and ensure that \"Hello from Rust!\" is printed lots of " +"times." +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"If you use VSCode, now set up Rust to work well in VSCode. It will be useful " +"in subsequent exercises. If you've succeeded, you will be able to use right-" +"click \"Go to definition\" on `println!`." +msgstr "" + +#: src/exercises/chromium/build-rules.md +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Where to find help" +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"The options available to the [`rust_static_library` gn template](https://" +"source.chromium.org/chromium/chromium/src/+/main:build/rust/" +"rust_static_library.gni;l=16)" +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"Information about [`#[unsafe(no_mangle)]`](https://doc.rust-lang.org/beta/" +"reference/abi.html#the-no_mangle-attribute)" +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"Information about [`extern \"C\"`](https://doc.rust-lang.org/std/keyword." +"extern.html)" +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"Information about gn's [`--export-rust-project`](https://gn.googlesource.com/" +"gn/+/main/docs/reference.md#compilation-database) switch" +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"[How to install rust-analyzer in VSCode](https://code.visualstudio.com/docs/" +"languages/rust)" +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"This example is unusual because it boils down to the lowest-common-" +"denominator interop language, C. Both C++ and Rust can natively declare and " +"call C ABI functions. Later in the course, we'll connect C++ directly to " +"Rust." +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"`allow_unsafe = true` is required here because `#[unsafe(no_mangle)]` might " +"allow Rust to generate two functions with the same name, and Rust can no " +"longer guarantee that the right one is called." +msgstr "" + +#: src/exercises/chromium/build-rules.md +msgid "" +"If you need a pure Rust executable, you can also do that using the " +"`rust_executable` gn template." +msgstr "" + +#: src/chromium/testing.md +msgid "" +"Rust community typically authors unit tests in a module placed in the same " +"source file as the code being tested. This was covered [earlier](../testing." +"md) in the course and looks like this:" +msgstr "" + +#: src/chromium/testing.md +msgid "" +"In Chromium we place unit tests in a separate source file and we continue to " +"follow this practice for Rust --- this makes tests consistently discoverable " +"and helps to avoid rebuilding `.rs` files a second time (in the `test` " +"configuration)." +msgstr "" + +#: src/chromium/testing.md +msgid "" +"This results in the following options for testing Rust code in Chromium:" +msgstr "" + +#: src/chromium/testing.md +msgid "" +"Native Rust tests (i.e. `#[test]`). Discouraged outside of `//third_party/" +"rust`." +msgstr "" + +#: src/chromium/testing.md +msgid "" +"`gtest` tests authored in C++ and exercising Rust via FFI calls. Sufficient " +"when Rust code is just a thin FFI layer and the existing unit tests provide " +"sufficient coverage for the feature." +msgstr "" + +#: src/chromium/testing.md +msgid "" +"`gtest` tests authored in Rust and using the crate under test through its " +"public API (using `pub mod for_testing { ... }` if needed). This is the " +"subject of the next few slides." +msgstr "" + +#: src/chromium/testing.md +msgid "" +"Mention that native Rust tests of third-party crates should eventually be " +"exercised by Chromium bots. (Such testing is needed rarely --- only after " +"adding or updating third-party crates.)" +msgstr "" + +#: src/chromium/testing.md +msgid "" +"Some examples may help illustrate when C++ `gtest` vs Rust `gtest` should be " +"used:" +msgstr "" + +#: src/chromium/testing.md +msgid "" +"QR has very little functionality in the first-party Rust layer (it's just a " +"thin FFI glue) and therefore uses the existing C++ unit tests for testing " +"both the C++ and the Rust implementation (parameterizing the tests so they " +"enable or disable Rust using a `ScopedFeatureList`)." +msgstr "" + +#: src/chromium/testing.md +msgid "" +"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." +msgstr "" + +#: src/chromium/testing/rust-gtest-interop.md +msgid "" +"The [`rust_gtest_interop`](https://chromium.googlesource.com/chromium/src/+/" +"main/testing/rust_gtest_interop/README.md) library provides a way to:" +msgstr "" + +#: src/chromium/testing/rust-gtest-interop.md +msgid "" +"Use a Rust function as a `gtest` testcase (using the `#[gtest(...)]` " +"attribute)" +msgstr "" + +#: src/chromium/testing/rust-gtest-interop.md +msgid "" +"Use `expect_eq!` and similar macros (similar to `assert_eq!` but not " +"panicking and not terminating the test when the assertion fails)." +msgstr "" + +#: src/chromium/testing/rust-gtest-interop.md +msgid "Example:" +msgstr "" + +#: src/chromium/testing/build-gn.md +msgid "" +"The simplest way to build Rust `gtest` tests is to add them to an existing " +"test binary that already contains tests authored in C++. For example:" +msgstr "" + +#: src/chromium/testing/build-gn.md +msgid "" +"```gn\n" +"test(\"ui_base_unittests\") {\n" +" ...\n" +" sources += [ \"my_rust_lib_unittest.rs\" ]\n" +" deps += [ \":my_rust_lib\" ]\n" +"}\n" +"```" +msgstr "" + +#: src/chromium/testing/build-gn.md +msgid "" +"Authoring Rust tests in a separate `static_library` also works, but requires " +"manually declaring the dependency on the support libraries:" +msgstr "" + +#: src/chromium/testing/build-gn.md +msgid "" +"```gn\n" +"rust_static_library(\"my_rust_lib_unittests\") {\n" +" testonly = true\n" +" is_gtest_unittests = true\n" +" crate_root = \"my_rust_lib_unittest.rs\"\n" +" sources = [ \"my_rust_lib_unittest.rs\" ]\n" +" deps = [\n" +" \":my_rust_lib\",\n" +" \"//testing/rust_gtest_interop\",\n" +" ]\n" +"}\n" +"\n" +"test(\"ui_base_unittests\") {\n" +" ...\n" +" deps += [ \":my_rust_lib_unittests\" ]\n" +"}\n" +"```" +msgstr "" + +#: src/chromium/testing/chromium-import-macro.md +msgid "" +"After adding `:my_rust_lib` to GN `deps`, we still need to learn how to " +"import and use `my_rust_lib` from `my_rust_lib_unittest.rs`. We haven't " +"provided an explicit `crate_name` for `my_rust_lib` so its crate name is " +"computed based on the full target path and name. Fortunately we can avoid " +"working with such an unwieldy name by using the `chromium::import!` macro " +"from the automatically-imported `chromium` crate:" +msgstr "" + +#: src/chromium/testing/chromium-import-macro.md +msgid "\"//ui/base:my_rust_lib\"" +msgstr "" + +#: src/chromium/testing/chromium-import-macro.md +msgid "Under the covers the macro expands to something similar to:" +msgstr "" + +#: src/chromium/testing/chromium-import-macro.md +msgid "" +"More information can be found in [the doc comment](https://source.chromium." +"org/chromium/chromium/src/+/main:build/rust/chromium_prelude/" +"chromium_prelude.rs?q=f:chromium_prelude.rs%20pub.use.*%5Cbimport%5Cb;%20-f:" +"third_party&ss=chromium%2Fchromium%2Fsrc) of the `chromium::import` macro." +msgstr "" + +#: src/chromium/testing/chromium-import-macro.md +msgid "" +"`rust_static_library` supports specifying an explicit name via `crate_name` " +"property, but doing this is discouraged. And it is discouraged because the " +"crate name has to be globally unique. crates.io guarantees uniqueness of its " +"crate names so `cargo_crate` GN targets (generated by the `gnrt` tool " +"covered in a later section) use short crate names." +msgstr "" + +#: src/exercises/chromium/testing.md +msgid "Testing exercise" +msgstr "" + +#: src/exercises/chromium/testing.md +msgid "Time for another exercise!" +msgstr "" + +#: src/exercises/chromium/testing.md +msgid "In your Chromium build:" +msgstr "" + +#: src/exercises/chromium/testing.md +msgid "" +"Add a testable function next to `hello_from_rust`. Some suggestions: adding " +"two integers received as arguments, computing the nth Fibonacci number, " +"summing integers in a slice, etc." +msgstr "" + +#: src/exercises/chromium/testing.md +msgid "Add a separate `..._unittest.rs` file with a test for the new function." +msgstr "" + +#: src/exercises/chromium/testing.md +msgid "Add the new tests to `BUILD.gn`." +msgstr "" + +#: src/exercises/chromium/testing.md +msgid "Build the tests, run them, and verify that the new test works." +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "" +"The Rust community offers multiple options for C++/Rust interop, with new " +"tools being developed all the time. At the moment, Chromium uses a tool " +"called CXX." +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "" +"You describe your whole language boundary in an interface definition " +"language (which closely resembles Rust) and then CXX tools generate " +"declarations for functions and types in both Rust and C++." +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "" +"See the [CXX tutorial](https://cxx.rs/tutorial.html) for a full example of " +"using this." +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "" +"Talk through the diagram. Explain that behind the scenes, this is doing just " +"the same as you previously did. Point out that automating the process has " +"the following benefits:" +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "" +"The tool guarantees that the C++ and Rust sides match (e.g. you get compile " +"errors if the `#[cxx::bridge]` doesn't match the actual C++ or Rust " +"definitions, but with out-of-sync manual bindings you'd get Undefined " +"Behavior)" +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "" +"The tool automates generation of FFI thunks (small, C-ABI-compatible, free " +"functions) for non-C features (e.g. enabling FFI calls into Rust or C++ " +"methods; manual bindings would require authoring such top-level, free " +"functions manually)" +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "The tool and the library can handle a set of core types - for example:" +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "" +"`&[T]` can be passed across the FFI boundary, even though it doesn't " +"guarantee any particular ABI or memory layout. With manual bindings `std::" +"span` / `&[T]` have to be manually destructured and rebuilt out of a " +"pointer and length - this is error-prone given that each language represents " +"empty slices slightly differently)" +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "" +"Smart pointers like `std::unique_ptr`, `std::shared_ptr`, and/or `Box` " +"are natively supported. With manual bindings, one would have to pass C-ABI-" +"compatible raw pointers, which would increase lifetime and memory-safety " +"risks." +msgstr "" + +#: src/chromium/interoperability-with-cpp.md +msgid "" +"`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-UTF-8 input and `rust::String::c_str` can NUL-" +"terminate a string)." +msgstr "" + +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "" +"CXX requires that the whole C++/Rust boundary is declared in `cxx::bridge` " +"modules inside `.rs` source code." +msgstr "" + +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "\"example/include/blobstore.h\"" +msgstr "" + +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "// Definitions of Rust types and functions go here\n" +msgstr "" + +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "Point out:" +msgstr "" + +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "" +"Although this looks like a regular Rust `mod`, the `#[cxx::bridge]` " +"procedural macro does complex things to it. The generated code is quite a " +"bit more sophisticated - though this does still result in a `mod` called " +"`ffi` in your code." +msgstr "" + +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "Native support for C++'s `std::unique_ptr` in Rust" +msgstr "" + +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "Native support for Rust slices in C++" +msgstr "" + +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "Calls from C++ to Rust, and Rust types (in the top part)" +msgstr "" -#: src/hello-world/benefits.md -msgid "No overhead FFI." -msgstr "No overhead FFI." +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "Calls from Rust to C++, and C++ types (in the bottom part)" +msgstr "" -#: src/hello-world/benefits.md -msgid "Zero-cost abstractions." -msgstr "Zero-cost abstractions." +#: src/chromium/interoperability-with-cpp/example-bindings.md +msgid "" +"**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." +msgstr "" -#: src/hello-world/benefits.md -msgid "Great compiler errors." -msgstr "āĻŽāĻšāĻžāύ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āĻ¤ā§āϰ⧁āϟāĻŋāĨ¤" +#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +msgid "" +"By far the most useful page when using CXX is the [type reference](https://" +"cxx.rs/bindings.html)." +msgstr "" -#: src/hello-world/benefits.md -msgid "Built-in dependency manager." -msgstr "āĻ…āĻ¨ā§āϤāĻ°ā§āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āĻĄāĻŋāĻĒ⧇āĻ¨ā§āĻĄā§‡āĻ¨ā§āϏāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāĻ•āĨ¤" +#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +msgid "CXX fundamentally suits cases where:" +msgstr "" -#: src/hello-world/benefits.md -msgid "Built-in support for testing." -msgstr "āĻĒāϰ⧀āĻ•ā§āώāĻž-āύāĻŋāϰ⧀āĻ•ā§āώāĻžāϰ āϜāĻ¨ā§āϝ⧇ āĻ…āĻ¨ā§āϤāĻ°ā§āύāĻŋāĻ°ā§āĻŽāĻŋāϤāĻ­āĻžāĻŦ⧇ āϏāĻŽāĻ°ā§āĻĨāύāĨ¤" +#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +msgid "" +"Your Rust-C++ interface is sufficiently simple that you can declare all of " +"it." +msgstr "" -#: src/hello-world/benefits.md -msgid "Excellent Language Server Protocol support." -msgstr "āϖ⧁āĻŦāχ āĻ­āĻžāϞ⧋ āϏāĻŽāĻ°ā§āĻĨāύ āĻ°ā§Ÿā§‡āϛ⧇ āĻ­āĻžāώāĻžāϰ āϏāĻžāĻ°ā§āĻ­āĻžāϰ āĻŽā§āϏāĻžāĻŦāĻŋāĻĻāĻžāϰāĨ¤" +#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +msgid "" +"You're using only the types natively supported by CXX already, for example " +"`std::unique_ptr`, `std::string`, `&[u8]` etc." +msgstr "" -#: src/hello-world/benefits.md +#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md msgid "" -"Do not spend much time here. All of these points will be covered in more " -"depth later." +"It has many limitations --- for example lack of support for Rust's `Option` " +"type." msgstr "" -"āĻāĻ–āĻžāύ⧇ āĻŦ⧇āĻļāĻŋ āϏāĻŽāϝāĻŧ āĻŦā§āϝāϝāĻŧ āĻ•āϰāĻŦ⧇āύ āύāĻžāĨ¤ āĻāχ āϏāĻŽāĻ¸ā§āϤ āĻŦāĻŋāώ⧟āϗ⧁āϞāĻŋ āĻĒāϰ⧇ āφāϰāĻ“ āĻ—āĻ­ā§€āϰāϤāĻžāϝāĻŧ āϚāĻ°ā§āϚāĻž āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤" -#: src/hello-world/benefits.md +#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md msgid "" -"Make sure to ask the class which languages they have experience with. " -"Depending on the answer you can highlight different features of Rust:" +"These limitations constrain us to using Rust in Chromium only for well " +"isolated \"leaf nodes\" rather than for arbitrary Rust-C++ interop. When " +"considering a use-case for Rust in Chromium, a good starting point is to " +"draft the CXX bindings for the language boundary to see if it appears simple " +"enough." msgstr "" -"āĻ•ā§āϞāĻžāϏ⧇ āϤāĻžāĻĻ⧇āϰ āϕ⧋āύ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāĻŋāĻ‚ āĻ­āĻžāώāĻžāϰ āĻ…āĻ­āĻŋāĻœā§āĻžāϤāĻž āφāϛ⧇ āϤāĻž āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻ•āϰāϤ⧇ āϭ⧁āϞāĻŦ⧇āύ āύāĻžāĨ¤ āωāĻ¤ā§āϤāϰ⧇āϰ " -"āωāĻĒāϰ āύāĻŋāĻ°ā§āĻ­āϰ āĻ•āϰ⧇ āφāĻĒāύāĻŋ āϰāĻžāĻ¸ā§āϟ āĻāϰ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ:" -#: src/hello-world/benefits.md +#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md msgid "" -"Experience with C or C++: Rust eliminates a whole class of _runtime errors_ " -"via the borrow checker. You get performance like in C and C++, but you don't " -"have the memory unsafety issues. In addition, you get a modern language with " -"constructs like pattern matching and built-in dependency management." +"You should also discuss some of the other sticky points with CXX, for " +"example:" msgstr "" -"āϏāĻŋ āĻŦāĻž āϏāĻŋ++ āĻāϰ āĻ…āĻ­āĻŋāĻœā§āĻžāϤāĻž: āϰāĻžāĻ¸ā§āϟ āϧāĻžāϰ āĻĒāϰ⧀āĻ•ā§āώāϕ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ _āϰāĻžāύāϟāĻžāχāĻŽ āĻ¤ā§āϰ⧁āϟāĻŋāϰ_ āĻāĻ•āϟāĻŋ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ " -"āĻ­āĻžāĻŦ⧇ āĻĻā§‚āϰ āĻ•āϰ⧇āĨ¤ āĻāĻŦāĻ‚ āφāĻĒāύāĻŋ āϏāĻŋ āĻāĻŦāĻ‚ āϏāĻŋ++ āĻāϰ āĻŽāϤ āĻ•āĻ°ā§āĻŽāĻ•ā§āώāĻŽāϤāĻž āĻĒāĻžāύ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āφāĻĒāύāĻžāϰ āĻŽā§‡āĻŽāϰāĻŋāϰ " -"āύāĻŋāϰāĻžāĻĒāĻ¤ā§āϤāĻž āϏāĻ‚āĻ•ā§āϰāĻžāĻ¨ā§āϤ āϏāĻŽāĻ¸ā§āϝāĻž āĻĨāĻžāϕ⧇ āύāĻžāĨ¤ āĻāĻ›āĻžāĻĄāĻŧāĻžāĻ“, āφāĻĒāύāĻŋ āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āĻŽā§āϝāĻžāϚāĻŋāĻ‚ āĻāĻŦāĻ‚ " -"āĻ…āĻ¨ā§āϤāĻ°ā§āύāĻŋāĻšāĻŋāϤāĻ­āĻžāĻŦ⧇ āĻĄāĻŋāĻĒ⧇āĻ¨ā§āĻĄā§‡āĻ¨ā§āϏāĻŋ āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻžāϰ āĻŽāϤ⧋ āĻŦ⧈āĻļāĻŋāĻˇā§āϟ āϏāĻš āĻāĻ•āϟāĻŋ āφāϧ⧁āύāĻŋāĻ• āĻ­āĻžāώāĻž āĻĒāĻžāύāĨ¤" -#: src/hello-world/benefits.md +#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md msgid "" -"Experience with Java, Go, Python, JavaScript...: You get the same memory " -"safety as in those languages, plus a similar high-level language feeling. In " -"addition you get fast and predictable performance like C and C++ (no garbage " -"collector) as well as access to low-level hardware (should you need it)" +"Its error handling is based around C++ exceptions (given on the next slide)" msgstr "" -"āϜāĻžāĻ­āĻž, āĻ—ā§‹, āĻĒāĻžāχāĻĨāύ, āϜāĻžāĻ­āĻžāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āĻŸā§‡āϰ āϏāĻžāĻĨ⧇ āĻ…āĻ­āĻŋāĻœā§āĻžāϤāĻž...: āφāĻĒāύāĻŋ āϏ⧇āχ āĻ­āĻžāώāĻžāϗ⧁āϞāĻŋāϰ āĻŽāϤ⧋ āĻāĻ•āχ " -"āĻŽā§‡āĻŽāϰāĻŋ āϏ⧁āϰāĻ•ā§āώāĻž āĻāĻŦāĻ‚ āĻāĻ•āχ āϰāĻ•āĻŽ āωāĻšā§āϚ-āĻ¸ā§āϤāϰ⧇āϰ āĻ­āĻžāώāĻž āĻ…āύ⧁āĻ­ā§‚āϤāĻŋ āĻĒā§‡ā§Ÿā§‡ āĻĨāĻžāϕ⧇āύāĨ¤ āĻāĻ›āĻžāĻĄāĻŧāĻžāĻ“ āφāĻĒāύāĻŋ āϏāĻŋ āĻāĻŦāĻ‚ " -"āϏāĻŋ++ āĻāϰ āĻŽāϤ āĻĻā§āϰ⧁āϤ āĻāĻŦāĻ‚ āĻ…āύ⧁āĻŽāĻžāύāϝ⧋āĻ—ā§āϝ āĻ•āĻ°ā§āĻŽāĻ•ā§āώāĻŽāϤāĻž āĻĒāĻžāĻŦ⧇āύ (āϕ⧋āύ⧋ āĻ—āĻžāĻ°ā§āĻŦ⧇āϜ āĻ•āĻžāϞ⧇āĻ•ā§āϟāϰ āĻ›āĻžā§œāĻžāχ) " -"āĻĒāĻžāĻļāĻžāĻĒāĻžāĻļāĻŋ āĻĻāϰāĻ•āĻžāϰāĻŽāϤāύ āύāĻŋāĻŽā§āύ-āĻ¸ā§āϤāϰ⧇āϰ āĻšāĻžāĻ°ā§āĻĄāĻ“āϝāĻŧā§āϝāĻžāϰ⧇ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏāĨ¤" -#: src/hello-world/playground.md +#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +msgid "Function pointers are awkward to use." +msgstr "" + +#: src/chromium/interoperability-with-cpp/error-handling.md msgid "" -"The [Rust Playground](https://play.rust-lang.org/) provides an easy way to " -"run short Rust programs, and is the basis for the examples and exercises in " -"this course. Try running the \"hello-world\" program it starts with. It " -"comes with a few handy features:" +"CXX's [support for `Result`](https://cxx.rs/binding/result.html) relies " +"on C++ exceptions, so we can't use that in Chromium. Alternatives:" msgstr "" -"[āϰāĻžāĻ¸ā§āϟ āĻĒā§āϞ⧇āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄ](https://play.rust-lang.org/) āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤ āϰāĻžāĻ¸ā§āϟ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āϚāĻžāϞāĻžāύ⧋āϰ " -"āĻāĻ•āϟāĻŋ āϏāĻšāϜ āωāĻĒāĻžāϝāĻŧ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇, āĻāĻŦāĻ‚ āĻāχ āϕ⧋āĻ°ā§āϏ⧇āϰ āωāĻĻāĻžāĻšāϰāĻŖ āĻāĻŦāĻ‚ āĻ…āύ⧁āĻļā§€āϞāύ⧇āϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋāĨ¤ āĻāϟāĻŋ āĻĻāĻŋāϝāĻŧ⧇ " -"āĻļ⧁āϰ⧁ āĻšāĻ“āϝāĻŧāĻž \"āĻšā§āϝāĻžāϞ⧋-āĻ“āϝāĻŧāĻžāĻ°ā§āĻ˛ā§āĻĄ\" āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāϟāĻŋ āϚāĻžāϞāĻžāύ⧋āϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰ⧁āύāĨ¤ āĻāϟāĻŋ āĻ•āϝāĻŧ⧇āĻ•āϟāĻŋ āϏ⧁āĻŦāĻŋāϧāĻžāϜāύāĻ• " -"āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āϏāĻš āφāϏ⧇:" -#: src/hello-world/playground.md +#: src/chromium/interoperability-with-cpp/error-handling.md +msgid "The `T` part of `Result` can be:" +msgstr "" + +#: src/chromium/interoperability-with-cpp/error-handling.md msgid "" -"Under \"Tools\", use the `rustfmt` option to format your code in the " -"\"standard\" way." +"Returned via out parameters (e.g. via `&mut T`). This requires that `T` can " +"be passed across the FFI boundary - for example `T` has to be:" msgstr "" -"\"Tools\" āĻāϰ āύāĻŋāĻšā§‡, \"āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ\" āωāĻĒāĻžāϝāĻŧ⧇ āφāĻĒāύāĻžāϰ āϕ⧋āĻĄ āĻĢāĻ°ā§āĻŽā§āϝāĻžāϟ āĻ•āϰāϤ⧇ `rustfmt` " -"āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤" -#: src/hello-world/playground.md +#: src/chromium/interoperability-with-cpp/error-handling.md +msgid "A primitive type (like `u32` or `usize`)" +msgstr "" + +#: src/chromium/interoperability-with-cpp/error-handling.md msgid "" -"Rust has two main \"profiles\" for generating code: Debug (extra runtime " -"checks, less optimization) and Release (fewer runtime checks, lots of " -"optimization). These are accessible under \"Debug\" at the top." +"A type natively supported by `cxx` (like `UniquePtr`) that has a suitable " +"default value to use in a failure case (_unlike_ `Box`)." msgstr "" -"āϕ⧋āĻĄ āϤ⧈āϰāĻŋ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻĻ⧁āϟāĻŋ āĻĒā§āϰāϧāĻžāύ \"āĻĒāϰāĻŋāϞ⧇āĻ–\" āφāϛ⧇: āĻĄāĻŋāĻŦāĻžāĻ— (āĻ…āϤāĻŋāϰāĻŋāĻ•ā§āϤ āϰāĻžāύāϟāĻžāχāĻŽ " -"āĻšā§‡āĻ•, āĻ•āĻŽ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāĻœā§‡āĻļāĻžāύ) āĻāĻŦāĻ‚ āϰāĻŋāϞāĻŋāϜ (āĻ•āĻŽ āϰāĻžāύāϟāĻžāχāĻŽ āĻšā§‡āĻ• āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻĒā§āϰāϚ⧁āϰ āĻĒāϰāĻŋāĻŽāĻžāϪ⧇ " -"āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāĻœā§‡āĻļāĻžāύ)āĨ¤ \"Debug\" āĻāϰ āύāĻŋāĻšā§‡ āĻāϗ⧁āϞāĻŋ āĻĒāĻžāĻ“ā§ŸāĻž āϝāĻžāĻŦ⧇āĨ¤" -#: src/hello-world/playground.md +#: src/chromium/interoperability-with-cpp/error-handling.md msgid "" -"If you're interested, use \"ASM\" under \"...\" to see the generated " -"assembly code." +"Retained on the Rust side, and exposed via reference. This may be needed " +"when `T` is a Rust type, which cannot be passed across the FFI boundary, and " +"cannot be stored in `UniquePtr`." msgstr "" -"āϤ⧈āϰ⧀ āĻ•āϰāĻž āϏāĻŽāĻžāĻŦ⧇āĻļ āϕ⧋āĻĄ āĻĻ⧇āĻ–āϤ⧇ āϝāĻĻāĻŋ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āφāĻ—ā§āϰāĻšā§€ āĻšāύ, āϤāĻžāĻšāϞ⧇ \"...\" āĻāϰ āĻ…āϧ⧀āύ⧇ " -"\"ASM\" āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤" -#: src/hello-world/playground.md +#: src/chromium/interoperability-with-cpp/error-handling.md +msgid "The `E` part of `Result` can be:" +msgstr "" + +#: src/chromium/interoperability-with-cpp/error-handling.md msgid "" -"As students head into the break, encourage them to open up the playground " -"and experiment a little. Encourage them to keep the tab open and try things " -"out during the rest of the course. This is particularly helpful for advanced " -"students who want to know more about Rust's optimizations or generated " -"assembly." +"Returned as a boolean (e.g. `true` representing success, and `false` " +"representing failure)" +msgstr "" + +#: src/chromium/interoperability-with-cpp/error-handling.md +msgid "" +"Preserving error details is in theory possible, but so far hasn't been " +"needed in practice." +msgstr "" + +#: src/chromium/interoperability-with-cpp/error-handling-qr.md +msgid "CXX Error Handling: QR Example" msgstr "" -"āĻļāĻŋāĻ•ā§āώāĻžāĻ°ā§āĻĨā§€āϰāĻž āϝāĻ–āύ āĻŦāĻŋāϰāϤāĻŋāϤ⧇ āϝāĻžāϝāĻŧ, āϤāĻ–āύ āϤāĻžāĻĻ⧇āϰ āĻĒā§āϞ⧇āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄ āϖ⧁āϞāϤ⧇ āĻāĻŦāĻ‚ āĻāĻ•āϟ⧁ āĻĒāϰ⧀āĻ•ā§āώāĻž-āύāĻŋāϰ⧀āĻ•ā§āώāĻž " -"āĻ•āϰāϤ⧇ āĻ‰ā§ŽāϏāĻžāĻšāĻŋāϤ āĻ•āϰ⧁āύāĨ¤ āϤāĻžāĻĻ⧇āϰ āĻŸā§āϝāĻžāĻŦ āĻ–ā§‹āϞāĻž āϰāĻžāĻ–āϤ⧇ āωāĻ¤ā§āϏāĻžāĻšāĻŋāϤ āĻ•āϰ⧁āύ āĻāĻŦāĻ‚ āĻŦāĻžāĻ•āĻŋ āϕ⧋āĻ°ā§āϏ⧇āϰ āϏāĻŽāϝāĻŧ āĻ•āĻŋāϛ⧁ " -"āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰ⧇ āĻĻ⧇āĻ–āϤ⧇ āĻŦāϞ⧁āύāĨ¤ āĻāϟāĻŋ āĻŦāĻŋāĻļ⧇āώāϤ āωāĻ¨ā§āύāϤ āĻ›āĻžāĻ¤ā§āϰāĻĻ⧇āϰ āϜāĻ¨ā§āϝ āϏāĻšāĻžāϝāĻŧāĻ• āϝāĻžāϰāĻž āϰāĻžāĻ¸ā§āĻŸā§‡āϰ " -"āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāĻœā§‡āĻļāύ āĻŦāĻž āĻœā§‡āύāĻžāϰ⧇āϟ āĻ•āϰāĻž āĻ…ā§āϝāĻžāϏ⧇āĻŽā§āĻŦāϞāĻŋ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āφāϰāĻ“ āϜāĻžāύāϤ⧇ āϚāĻžāύāĨ¤" -#: src/types-and-values.md -msgid "[Hello, World](./types-and-values/hello-world.md) (5 minutes)" -msgstr "[āĻšā§āϝāĻžāϞ⧋, āĻ“ā§ŸāĻžāĻ°ā§āĻ˛ā§āĻĄ](./types-and-values/hello-world.md) (ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/chromium/interoperability-with-cpp/error-handling-qr.md +msgid "" +"The QR code generator is [an example](https://source.chromium.org/chromium/" +"chromium/src/+/main:components/qr_code_generator/qr_code_generator_ffi_glue." +"rs;l=13-18;drc=7bf1b75b910ca430501b9c6a74c1d18a0223ecca) where a boolean is " +"used to communicate success vs failure, and where the successful result can " +"be passed across the FFI boundary:" +msgstr "" -#: src/types-and-values.md -msgid "[Variables](./types-and-values/variables.md) (5 minutes)" -msgstr "[āϭ⧇āϰāĻŋāĻāĻŦāϞ⧇āϏ](./types-and-values/variables.md) (ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/chromium/interoperability-with-cpp/error-handling-qr.md +msgid "\"qr_code_generator\"" +msgstr "" -#: src/types-and-values.md -msgid "[Values](./types-and-values/values.md) (5 minutes)" -msgstr "[āĻŽāĻžāύ](./types-and-values/values.md) (ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/chromium/interoperability-with-cpp/error-handling-qr.md +msgid "" +"Students may be curious about the semantics of the `out_qr_size` output. " +"This is not the size of the vector, but the size of the QR code (and " +"admittedly it is a bit redundant - this is the square root of the size of " +"the vector)." +msgstr "" -#: src/types-and-values.md -msgid "[Arithmetic](./types-and-values/arithmetic.md) (3 minutes)" -msgstr "[āĻ—āĻŖāĻŋāϤ](./types-and-values/arithmetic.md) (ā§Š āĻŽāĻŋāύāĻŋāϟ)" +#: src/chromium/interoperability-with-cpp/error-handling-qr.md +msgid "" +"It may be worth pointing out the importance of initializing `out_qr_size` " +"before calling into the Rust function. Creation of a Rust reference that " +"points to uninitialized memory results in Undefined Behavior (unlike in C++, " +"when only the act of dereferencing such memory results in UB)." +msgstr "" -#: src/types-and-values.md -msgid "[Strings](./types-and-values/strings.md) (5 minutes)" -msgstr "[āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚](./types-and-values/strings.md) (ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/chromium/interoperability-with-cpp/error-handling-qr.md +msgid "" +"If students ask about `Pin`, then explain why CXX needs it for mutable " +"references to C++ data: the answer is that C++ data can’t be moved around " +"like Rust data, because it may contain self-referential pointers." +msgstr "" -#: src/types-and-values.md -msgid "[Type Inference](./types-and-values/inference.md) (3 minutes)" -msgstr "[āϟāĻžāχāĻĒ⧇āϰ āĻ…āύ⧁āĻŽāĻŋāϤāĻŋ](./types-and-values/inference.md) (ā§Š āĻŽāĻŋāύāĻŋāϟ)" +#: src/chromium/interoperability-with-cpp/error-handling-png.md +msgid "CXX Error Handling: PNG Example" +msgstr "" -#: src/types-and-values.md -msgid "[Exercise: Fibonacci](./types-and-values/exercise.md) (15 minutes)" -msgstr "[āĻ…āύ⧁āĻļā§€āϞāύ⧀: : āĻĢāĻŋāĻŦā§‹āύāĻžāϚāĻŋ](./types-and-values/exercise.md) (ā§§ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/chromium/interoperability-with-cpp/error-handling-png.md +msgid "" +"A prototype of a PNG decoder illustrates what can be done when the " +"successful result cannot be passed across the FFI boundary:" +msgstr "" -#: src/types-and-values.md src/methods-and-traits.md src/iterators.md -msgid "This segment should take about 45 minutes" -msgstr "āĻāχ āĻ…āĻ‚āĻļāϟāĻŋ āĻĒā§āϰāĻžāϝāĻŧ ā§Ēā§Ģ āĻŽāĻŋāύāĻŋāϟ āϏāĻŽāϝāĻŧ āύ⧇āĻŦ⧇" +#: src/chromium/interoperability-with-cpp/error-handling-png.md +msgid "\"gfx::rust_bindings\"" +msgstr "" -#: src/types-and-values/hello-world.md +#: src/chromium/interoperability-with-cpp/error-handling-png.md msgid "" -"Let us jump into the simplest possible Rust program, a classic Hello World " -"program:" +"/// This returns an FFI-friendly equivalent of `Result,\n" +" /// ()>`.\n" msgstr "" -"āφāϏ⧁āύ āϏāĻšāϜāϤāĻŽ āϏāĻŽā§āĻ­āĻžāĻŦā§āϝ āϰāĻžāĻ¸ā§āϟ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§‡ āĻāĻžāρāĻĒ āĻĻ⧇āĻ“āϝāĻŧāĻž āϝāĻžāĻ•, āĻāĻ•āϟāĻŋ āĻ•ā§āϞāĻžāϏāĻŋāĻ• āĻšā§āϝāĻžāϞ⧋ āĻ“āϝāĻŧāĻžāĻ°ā§āĻ˛ā§āĻĄ " -"āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ:" -#: src/types-and-values/hello-world.md -msgid "\"Hello 🌍!\"" -msgstr "\"Hello 🌍!\"" +#: src/chromium/interoperability-with-cpp/error-handling-png.md +msgid "/// C++ bindings for the `crate::png::ResultOfPngReader` type.\n" +msgstr "" -#: src/types-and-values/hello-world.md -msgid "What you see:" -msgstr "āϝāĻž āϤ⧁āĻŽāĻŋ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻ“āσ" +#: src/chromium/interoperability-with-cpp/error-handling-png.md +msgid "/// C++ bindings for the `crate::png::PngReader` type.\n" +msgstr "" -#: src/types-and-values/hello-world.md -msgid "Functions are introduced with `fn`." -msgstr "`fn` āĻĻāĻŋāϝāĻŧ⧇ āĻĢāĻžāĻ‚āĻļāύ āϚāĻžāϞ⧁ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤" +#: src/chromium/interoperability-with-cpp/error-handling-png.md +msgid "" +"`PngReader` and `ResultOfPngReader` are Rust types --- objects of these " +"types cannot cross the FFI boundary without indirection of a `Box`. We " +"can't have an `out_parameter: &mut PngReader`, because CXX doesn't allow C++ " +"to store Rust objects by value." +msgstr "" -#: src/types-and-values/hello-world.md -msgid "Blocks are delimited by curly braces like in C and C++." +#: src/chromium/interoperability-with-cpp/error-handling-png.md +msgid "" +"This example illustrates that even though CXX doesn't support arbitrary " +"generics nor templates, we can still pass them across the FFI boundary by " +"manually specializing / monomorphizing them into a non-generic type. In the " +"example `ResultOfPngReader` is a non-generic type that forwards into " +"appropriate methods of `Result` (e.g. into `is_err`, `unwrap`, and/or " +"`as_mut`)." +msgstr "" + +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "Using cxx in Chromium" +msgstr "" + +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "" +"In Chromium, we define an independent `#[cxx::bridge] mod` for each leaf-" +"node where we want to use Rust. You'd typically have one for each " +"`rust_static_library`. Just add" +msgstr "" + +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "" +"```gn\n" +"cxx_bindings = [ \"my_rust_file.rs\" ]\n" +" # list of files containing #[cxx::bridge], not all source files\n" +"allow_unsafe = true\n" +"```" +msgstr "" + +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "" +"to your existing `rust_static_library` target alongside `crate_root` and " +"`sources`." +msgstr "" + +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "C++ headers will be generated at a sensible location, so you can just" +msgstr "" + +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "\"ui/base/my_rust_file.rs.h\"" +msgstr "" + +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "" +"You will find some utility functions in `//base` to convert to/from Chromium " +"C++ types to CXX Rust types --- for example [`SpanToRustSlice`](https://" +"source.chromium.org/chromium/chromium/src/+/main:base/containers/span_rust.h;" +"l=21)." +msgstr "" + +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "Students may ask --- why do we still need `allow_unsafe = true`?" +msgstr "" + +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "" +"The broad answer is that no C/C++ code is \"safe\" by the normal Rust " +"standards. Calling back and forth to C/C++ from Rust may do arbitrary things " +"to memory, and compromise the safety of Rust's own data layouts. Presence of " +"_too many_ `unsafe` keywords in C/C++ interop can harm the signal-to-noise " +"ratio of such a keyword, and is [controversial](https://steveklabnik.com/" +"writing/the-cxx-debate), but strictly, bringing any foreign code into a Rust " +"binary can cause unexpected behavior from Rust's perspective." msgstr "" -"āĻŦā§āϞāĻ•āϗ⧁āϞāĻŋ āϏāĻŋ āĻāĻŦāĻ‚ āϏāĻŋ++ āĻāϰ āĻŽāϤ āϕ⧋āρāĻ•āĻĄāĻŧāĻž āϧāύ⧁āĻ°ā§āĻŦāĻ¨ā§āϧāύ⧀ (āĻ•āĻžāϰāϞāĻŋ āĻŦā§āϰ⧇āϏ⧇āϏ) āĻĻā§āĻŦāĻžāϰāĻž āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧ āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤" -#: src/types-and-values/hello-world.md -msgid "The `main` function is the entry point of the program." -msgstr "āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āϏāĻŦāϏāĻŽā§Ÿā§‡ `main` āĻĢāĻžāĻ‚āĻļāύ āĻĨ⧇āϕ⧇ āĻļ⧁āϰ⧁ āĻšā§ŸāĨ¤" +#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +msgid "" +"The narrow answer lies in the diagram at the top of [this page](../" +"interoperability-with-cpp.md) --- behind the scenes, CXX generates Rust " +"`unsafe` and `extern \"C\"` functions just like we did manually in the " +"previous section." +msgstr "" -#: src/types-and-values/hello-world.md -msgid "Rust has hygienic macros, `println!` is an example of this." -msgstr "āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āĻ¸ā§āĻŦāĻžāĻ¸ā§āĻĨāĻ•āϰ āĻŦāϞāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇, `println!` āĻāϰāχ āĻāĻ• āωāĻĻāĻžāĻšāϰāĻŖāĨ¤" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Exercise: Interoperability with C++" +msgstr "" -#: src/types-and-values/hello-world.md -msgid "Rust strings are UTF-8 encoded and can contain any Unicode character." +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Part one" msgstr "" -"āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚āϗ⧁āϞāĻŋ āχāω.āϟāĻŋ.āĻāĻĢ-ā§Ž āĻāύāϕ⧋āĻĄā§‡āĻĄ āĻāĻŦāĻ‚ āϝ⧇ āϕ⧋āύāĻ“ āχāωāύāĻŋāϕ⧋āĻĄ āĻ…āĻ•ā§āώāϰ āĻāϤ⧇ āĻĨāĻžāĻ•āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" -#: src/types-and-values/hello-world.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"This slide tries to make the students comfortable with Rust code. They will " -"see a ton of it over the next four days so we start small with something " -"familiar." +"In the Rust file you previously created, add a `#[cxx::bridge]` which " +"specifies a single function, to be called from C++, called " +"`hello_from_rust`, taking no parameters and returning no value." msgstr "" -"āĻāχ āĻ¸ā§āϞāĻžāχāĻĄāϟāĻŋ āĻļāĻŋāĻ•ā§āώāĻžāĻ°ā§āĻĨā§€āĻĻ⧇āϰ āϰāĻžāĻ¸ā§āϟ āϕ⧋āĻĄā§‡āϰ āϏāĻžāĻĨ⧇ āϏ⧁āĻĒāϰāĻŋāϚāĻŋāϤ āĻ•āϰāĻžāϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰ⧇āĨ¤ āϤāĻžāϰāĻž āĻĒāϰ⧇āϰ āϚāĻžāϰ " -"āĻĻāĻŋāύ⧇ āĻāϟāĻŋ āĻ…āύ⧇āĻ•āĻŦāĻžāϰ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇ āϤāĻžāχ āφāĻŽāϰāĻž āĻĒāϰāĻŋāϚāĻŋāϤ āĻ•āĻŋāϛ⧁ āϛ⧋āϟ āĻĻāĻŋāϝāĻŧ⧇ āĻļ⧁āϰ⧁ āĻ•āϰāĻŋāĨ¤" -#: src/types-and-values/hello-world.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"Rust is very much like other languages in the C/C++/Java tradition. It is " -"imperative and it doesn't try to reinvent things unless absolutely necessary." +"Modify your previous `hello_from_rust` function to remove `extern \"C\"` and " +"`#[unsafe(no_mangle)]`. This is now just a standard Rust function." msgstr "" -"āϰāĻžāĻ¸ā§āϟ āϏāĻŋ/āϏāĻŋ++/āϜāĻžāĻ­āĻž āϐāϤāĻŋāĻšā§āϝ⧇āϰ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻ­āĻžāώāĻžāϰ āĻŽāϤ⧋āχāĨ¤ āĻāϟāĻž āĻ…āύ⧁āĻœā§āĻžāĻžāϏ⧂āϚāĻ• āĻāĻŦāĻ‚ āĻāϟāĻŋ āĻāϕ⧇āĻŦāĻžāϰ⧇ " -"āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ āύāĻž āĻšāϞ⧇ āϜāĻŋāύāĻŋāϏāϗ⧁āϞāĻŋāϕ⧇ āĻĒ⧁āύāϰāĻžāϝāĻŧ āωāĻĻā§āĻ­āĻžāĻŦāύ⧇āϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰ⧇ āύāĻžāĨ¤" -#: src/types-and-values/hello-world.md -msgid "Rust is modern with full support for things like Unicode." -msgstr "āχāωāύāĻŋāϕ⧋āĻĄā§‡āϰ āĻŽāϤ⧋ āϜāĻŋāύāĻŋāϏāϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āϏāĻŽāĻ°ā§āĻĨāύ āϏāĻš āϰāĻžāĻ¸ā§āϟ āĻāĻ•āϟāĻŋ āφāϧ⧁āύāĻŋāĻ• āĻ­āĻžāώāĻžāĨ¤" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Modify your `gn` target to build these bindings." +msgstr "" -#: src/types-and-values/hello-world.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"Rust uses macros for situations where you want to have a variable number of " -"arguments (no function [overloading](../control-flow-basics/functions.md))." +"In your C++ code, remove the forward-declaration of `hello_from_rust`. " +"Instead, include the generated header file." msgstr "" -"āϰāĻžāĻ¸ā§āĻŸā§‡ āĻĢāĻžāĻ‚āĻļāύ [āĻ“āĻ­āĻžāϰāϞ⧋āĻĄāĻŋāĻ‚](../control-flow-basics/functions.md) āύ⧇āχ āϤāĻžāχ āĻāĻŽāύ " -"āĻĒāϰāĻŋāĻ¸ā§āĻĨāĻŋāϤāĻŋāϤ⧇ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϝ⧇āĻ–āĻžāύ⧇ āφāĻĒāύāĻŋ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύāĻļā§€āϞ āϏāĻ‚āĻ–ā§āϝāĻ• āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āϰāĻžāĻ–āϤ⧇ āϚāĻžāύāĨ¤" -#: src/types-and-values/hello-world.md -msgid "" -"Macros being 'hygienic' means they don't accidentally capture identifiers " -"from the scope they are used in. Rust macros are actually only [partially " -"hygienic](https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene." -"html)." +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Build and run!" msgstr "" -"āĻŽā§āϝāĻžāĻ•ā§āϰ⧋āϗ⧁āϞāĻŋ 'āĻ¸ā§āĻŦāĻžāĻ¸ā§āĻĨā§āϝāĻ•āϰ' āĻšāĻ“āϝāĻŧāĻžāϰ āĻ…āĻ°ā§āĻĨ āĻšāϞ āϝ⧇ āϤāĻžāϰāĻž āĻĻ⧁āĻ°ā§āϘāϟāύāĻžāĻ•ā§āϰāĻŽā§‡ āϤāĻžāĻĻ⧇āϰ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻ¸ā§āϕ⧋āĻĒ⧇āϰ āĻŽāĻ§ā§āϝ⧇ " -"āĻĨ⧇āϕ⧇ āĻ­ā§āϝāĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ āϤ⧁āϞ⧇ āύāĻžāĨ¤ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āφāϏāϞ⧇ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ [āφāĻ‚āĻļāĻŋāĻ•āĻ­āĻžāĻŦ⧇ āĻ¸ā§āĻŦāĻžāĻ¸ā§āĻĨā§āϝāĻ•āϰ]" -"(https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene.html)āĨ¤" -#: src/types-and-values/hello-world.md -msgid "" -"Rust is multi-paradigm. For example, it has powerful [object-oriented " -"programming features](https://doc.rust-lang.org/book/ch17-00-oop.html), and, " -"while it is not a functional language, it includes a range of [functional " -"concepts](https://doc.rust-lang.org/book/ch13-00-functional-features.html)." +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Part two" msgstr "" -"āϰāĻžāĻ¸ā§āϟ āĻŦāĻšā§-āĻĻ⧃āĻˇā§āϟāĻžāĻ¨ā§āϤ āĻāĻ•āϟāĻŋ āĻ­āĻžāώāĻžāĨ¤ āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āĻāϟāĻŋāϤ⧇ āĻļāĻ•ā§āϤāĻŋāĻļāĻžāϞ⧀ [āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ-āĻ“āϰāĻŋāϝāĻŧ⧇āĻ¨ā§āĻŸā§‡āĻĄ " -"āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāĻŋāĻ‚ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āϰāϝāĻŧ⧇āϛ⧇](https://doc.rust-lang.org/book/ch17-00-oop.html)," -"āĻāĻŦāĻ‚, āϝāĻĻāĻŋāĻ“ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻĢāĻžāĻ‚āĻļāύāĻžāϞ āĻ­āĻžāώāĻž āύāϝāĻŧ, āĻāϟāĻŋāϤ⧇ āĻ…āύ⧇āĻ• [āĻĢāĻžāĻ‚āĻļāύāĻžāϞ āĻ­āĻžāώāĻžāϰ āϧāĻžāϰāĻŖāĻž](https://" -"doc.rust-lang.org/book/ch13-00-functional-features.html) āĻ“ āĻ°ā§Ÿā§‡āϛ⧇āĨ¤" -#: src/types-and-values/variables.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"Rust provides type safety via static typing. Variable bindings are made with " -"`let`:" +"It's a good idea to play with CXX a little. It helps you think about how " +"flexible Rust in Chromium actually is." msgstr "" -"āϰāĻžāĻ¸ā§āϟ āĻ¸ā§āĻŸā§āϝāĻžāϟāĻŋāĻ• āϟāĻžāχāĻĒāĻŋāĻ‚āϝāĻŧ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āϟāĻžāχāĻĒ āύāĻŋāϰāĻžāĻĒāĻ¤ā§āϤāĻž āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇āĨ¤ āĻ­ā§āϝāĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ⧇āϰ āĻŦāĻžāχāĻ¨ā§āĻĄāĻŋāĻ‚ " -"`let` āĻĻāĻŋāϝāĻŧ⧇ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻšāϝāĻŧ:" - -#: src/types-and-values/variables.md src/control-flow-basics/loops/for.md -#: src/control-flow-basics/blocks-and-scopes.md -msgid "\"x: {x}\"" -msgstr "\"x: {x}\"" -#: src/types-and-values/variables.md -msgid "// x = 20;" -msgstr "// x = 20;" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Some things to try:" +msgstr "" -#: src/types-and-values/variables.md -msgid "// println!(\"x: {x}\");" -msgstr "// println!(\"x: {x}\");" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Call back into C++ from Rust. You will need:" +msgstr "" -#: src/types-and-values/variables.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"Uncomment the `x = 20` to demonstrate that variables are immutable by " -"default. Add the `mut` keyword to allow changes." +"An additional header file which you can `include!` from your `cxx::bridge`. " +"You'll need to declare your C++ function in that new header file." msgstr "" -"āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϗ⧁āϞāĻŋ āĻ—āϤāĻžāύ⧁āĻ—āϤāĻŋāĻ•āϰ⧂āĻĒ⧇ āĻ…āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ⧀āϝāĻŧ āϤāĻž āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰāϤ⧇ `x = 20` āϟāĻŋ āφāύāĻ•āĻŽā§‡āĻ¨ā§āϟ āĻ•āϰ⧁āύāĨ¤ " -"āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ⧇āϰ āĻ…āύ⧁āĻŽāϤāĻŋ āĻĻāĻŋāϤ⧇ `mut` āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āϝ⧋āĻ— āĻ•āϰ⧁āύāĨ¤" -#: src/types-and-values/variables.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"The `i32` here is the type of the variable. This must be known at compile " -"time, but type inference (covered later) allows the programmer to omit it in " -"many cases." +"An `unsafe` block to call such a function, or alternatively specify the " +"`unsafe` keyword in your `#[cxx::bridge]` [as described here](https://cxx.rs/" +"extern-c++.html#functions-and-member-functions)." msgstr "" -"āĻāĻ–āĻžāύ⧇ `i32` āĻšāϞ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ⧇āϰ āϧāϰāύāĨ¤ āĻ•āĻŽā§āĻĒāĻžāχāϞ⧇āϰ āϏāĻŽāϝāĻŧ āĻāϟāĻŋ āĻ…āĻŦāĻļā§āϝāχ āϜāĻžāύāĻž āĻĨāĻžāĻ•āĻž āĻĻāϰāĻ•āĻžāϰ, āϤāĻŦ⧇ " -"āϟāĻžāχāĻĒ āχāύāĻĢāĻžāϰ⧇āĻ¨ā§āϏ (āĻĒāϰ⧇ āφāĻšā§āĻ›āĻžāĻĻāĻŋāϤ) āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāĻžāϰāϕ⧇ āĻ…āύ⧇āĻ• āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇ āĻāϟāĻŋ āĻŦāĻžāĻĻ āĻĻ⧇āĻ“āϝāĻŧāĻžāϰ āĻ…āύ⧁āĻŽāϤāĻŋ āĻĻ⧇āϝāĻŧāĨ¤" -#: src/types-and-values/values.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"Here are some basic built-in types, and the syntax for literal values of " -"each type." +"You may also need to `#include \"third_party/rust/cxx/v1/crate/include/cxx." +"h\"`" msgstr "" -"āĻāĻ–āĻžāύ⧇ āĻ•āĻŋāϛ⧁ āĻŽā§ŒāϞāĻŋāĻ• āĻ…āĻ¨ā§āϤāĻ°ā§āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āϟāĻžāχāĻĒ āϰāϝāĻŧ⧇āϛ⧇, āĻāĻŦāĻ‚ āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻĒā§āϰāĻ•āĻžāϰ⧇āϰ āφāĻ•ā§āώāϰāĻŋāĻ• āĻŽāĻžāύāϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ " -"āĻŦāĻžāĻ•ā§āϝ āĻ—āĻ āύ āĻ“ āĻĻ⧇āĻ“ā§ŸāĻž āĻ°ā§Ÿā§‡āϛ⧇āĨ¤" - -#: src/types-and-values/values.md src/tuples-and-arrays/tuples-and-arrays.md -#: src/unsafe-rust/exercise.md -msgid "Types" -msgstr "Types" - -#: src/types-and-values/values.md src/tuples-and-arrays/tuples-and-arrays.md -msgid "Literals" -msgstr "Literals" - -#: src/types-and-values/values.md -msgid "Signed integers" -msgstr "Signed integers" - -#: src/types-and-values/values.md -msgid "`i8`, `i16`, `i32`, `i64`, `i128`, `isize`" -msgstr "`i8`, `i16`, `i32`, `i64`, `i128`, `isize`" - -#: src/types-and-values/values.md -msgid "`-10`, `0`, `1_000`, `123_i64`" -msgstr "`-10`, `0`, `1_000`, `123_i64`" - -#: src/types-and-values/values.md -msgid "Unsigned integers" -msgstr "Unsigned integers" - -#: src/types-and-values/values.md -msgid "`u8`, `u16`, `u32`, `u64`, `u128`, `usize`" -msgstr "`u8`, `u16`, `u32`, `u64`, `u128`, `usize`" - -#: src/types-and-values/values.md -msgid "`0`, `123`, `10_u16`" -msgstr "`0`, `123`, `10_u16`" - -#: src/types-and-values/values.md -msgid "Floating point numbers" -msgstr "Floating point numbers" - -#: src/types-and-values/values.md -msgid "`f32`, `f64`" -msgstr "`f32`, `f64`" - -#: src/types-and-values/values.md -msgid "`3.14`, `-10.0e20`, `2_f32`" -msgstr "`3.14`, `-10.0e20`, `2_f32`" - -#: src/types-and-values/values.md -msgid "Unicode scalar values" -msgstr "Unicode scalar values" - -#: src/types-and-values/values.md src/android/aidl/types/primitives.md -msgid "`char`" -msgstr "`char`" -#: src/types-and-values/values.md -msgid "`'a'`, `'Îą'`, `'∞'`" -msgstr "`'a'`, `'Îą'`, `'∞'`" - -#: src/types-and-values/values.md -msgid "Booleans" -msgstr "Booleans" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Pass a C++ string from C++ into Rust." +msgstr "" -#: src/types-and-values/values.md src/android/aidl/types/primitives.md -msgid "`bool`" -msgstr "`bool`" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Pass a reference to a C++ object into Rust." +msgstr "" -#: src/types-and-values/values.md -msgid "`true`, `false`" -msgstr "`true`, `false`" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "" +"Intentionally get the Rust function signatures mismatched from the `#[cxx::" +"bridge]`, and get used to the errors you see." +msgstr "" -#: src/types-and-values/values.md -msgid "The types have widths as follows:" -msgstr "āϟāĻžāχāĻĒāϗ⧁āϞ⧋āϰ āφāĻ•āĻžāϰ āĻ āϰāĻ•āĻŽ:" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "" +"Intentionally get the C++ function signatures mismatched from the `#[cxx::" +"bridge]`, and get used to the errors you see." +msgstr "" -#: src/types-and-values/values.md -msgid "`iN`, `uN`, and `fN` are _N_ bits wide," -msgstr "`iN`, `uN`, and `fN` are _N_ bits wide," +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "" +"Pass a `std::unique_ptr` of some type from C++ into Rust, so that Rust can " +"own some C++ object." +msgstr "" -#: src/types-and-values/values.md -msgid "`isize` and `usize` are the width of a pointer," -msgstr "`isize` and `usize` are the width of a pointer," +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "" +"Create a Rust object and pass it into C++, so that C++ owns it. (Hint: you " +"need a `Box`)." +msgstr "" -#: src/types-and-values/values.md -msgid "`char` is 32 bits wide," -msgstr "`char` āĻšāĻšā§āϛ⧇ ā§Šā§¨ āĻŦāĻŋāϟ āĻĒā§āϰāĻļāĻ¸ā§āϤ," +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Declare some methods on a C++ type. Call them from Rust." +msgstr "" -#: src/types-and-values/values.md -msgid "`bool` is 8 bits wide." -msgstr "`bool` āĻšāĻšā§āϛ⧇ ā§Ž āĻŦāĻŋāϟ āϚ⧌⧜āĻžāĨ¤" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Declare some methods on a Rust type. Call them from C++." +msgstr "" -#: src/types-and-values/values.md -msgid "There are a few syntaxes which are not shown above:" -msgstr "āĻ•āĻŋāϛ⧁ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āφāϛ⧇ āϝāĻž āωāĻĒāϰ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧāύāĻŋāσ" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Part three" +msgstr "" -#: src/types-and-values/values.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"All underscores in numbers can be left out, they are for legibility only. So " -"`1_000` can be written as `1000` (or `10_00`), and `123_i64` can be written " -"as `123i64`." +"Now you understand the strengths and limitations of CXX interop, think of a " +"couple of use-cases for Rust in Chromium where the interface would be " +"sufficiently simple. Sketch how you might define that interface." msgstr "" -"āϏāĻ‚āĻ–ā§āϝāĻžāϰ āϏāĻŽāĻ¸ā§āϤ āφāĻ¨ā§āĻĄāĻžāϰāĻ¸ā§āϕ⧋āϰ āĻŦāĻžāĻĻ āĻĻ⧇āĻ“āϝāĻŧāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇, āϏ⧇āϗ⧁āϞāĻŋ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āĻ¸ā§āĻĒāĻˇā§āϟāϤāĻžāϰ āϜāĻ¨ā§āϝ āĻĻ⧇āĻ“ā§ŸāĻžāĨ¤ " -"āϏ⧁āϤāϰāĻžāĻ‚ `1_000` āϕ⧇ `1000` (āĻŦāĻž `10_00`) āĻšāĻŋāϏāĻžāĻŦ⧇ āϞ⧇āĻ–āĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇ āĻāĻŦāĻ‚ `123_i64` āϕ⧇ " -"`123i64` āĻšāĻŋāϏāĻžāĻŦ⧇ āϞ⧇āĻ–āĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" -#: src/types-and-values/arithmetic.md -msgid "\"result: {}\"" -msgstr "\"result: {}\"" +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "The [`cxx` binding reference](https://cxx.rs/bindings.html)" +msgstr "" -#: src/types-and-values/arithmetic.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"This is the first time we've seen a function other than `main`, but the " -"meaning should be clear: it takes three integers, and returns an integer. " -"Functions will be covered in more detail later." +"The [`rust_static_library` gn template](https://source.chromium.org/chromium/" +"chromium/src/+/main:build/rust/rust_static_library.gni;l=16)" msgstr "" -"āĻāχ āĻĒā§āϰāĻĨāĻŽ āφāĻŽāϰāĻž āĻŦāĻžāĻĻ⧇ āĻ…āĻ¨ā§āϝ āϕ⧋āύ⧋ āĻĢāĻžāĻ‚āĻļāύ āĻĻ⧇āĻ–āĻ›āĻŋ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻāχ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻ…āĻ°ā§āĻĨāϟāĻŋ āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āĻšāĻ“āϝāĻŧāĻž " -"āωāϚāĻŋāϤ: āĻāϟāĻŋ āϤāĻŋāύāϟāĻŋ āĻĒā§‚āĻ°ā§āĻŖāϏāĻ‚āĻ–ā§āϝāĻž āĻŦāĻž āχāĻ¨ā§āϟāĻŋāϜāĻžāϰ āύ⧇āϝāĻŧ āĻāĻŦāĻ‚ āĻāĻ•āϟāĻŋ āχāĻ¨ā§āϟāĻŋāϜāĻžāϰ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇āĨ¤ āĻĢāĻžāĻ‚āĻļāύ " -"āĻĒāϰ⧇ āφāϰ⧋ āĻŦāĻŋāĻ¸ā§āϤāĻžāϰāĻŋāϤ āϚāĻ°ā§āϚāĻž āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤" - -#: src/types-and-values/arithmetic.md -msgid "Arithmetic is very similar to other languages, with similar precedence." -msgstr "āĻāĻ•āχ āĻ…āĻ—ā§āϰāĻžāϧāĻŋāĻ•āĻžāϰ āϰ⧇āϖ⧇ āĻāĻ–āĻžāύ⧇ āĻĒāĻžāϟāĻŋāĻ—āĻŖāĻŋāϤ⧇āϰ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻ­āĻžāώāĻžāϰ āϏāĻžāĻĨ⧇ āϖ⧁āĻŦ āĻŽāĻŋāϞāĨ¤" -#: src/types-and-values/arithmetic.md -msgid "" -"What about integer overflow? In C and C++ overflow of _signed_ integers is " -"actually undefined, and might do different things on different platforms or " -"compilers. In Rust, it's defined." +#: src/exercises/chromium/interoperability-with-cpp.md +msgid "Some of the questions you may encounter:" msgstr "" -"āχāĻ¨ā§āϟāĻŋāϜāĻžāϰ āĻ“āĻ­āĻžāϰāĻĢā§āϞ⧋ āĻšāϞ⧇? āϏāĻŋ āĻŦāĻž āϏāĻŋ++ -āĻ āϚāĻŋāĻšā§āύāĻŋāϤ āχāĻ¨ā§āϟāĻŋāϜāĻžāϰ āĻ“āĻ­āĻžāϰāĻĢā§āϞ⧋ āĻšāϞ⧇ āϤāĻžāϰ āĻŽā§āϝāĻžāύ " -"āĻ…āύāĻŋāĻ°ā§āϧāĻžāϰāĻŋāϤ āĻšā§Ÿā§‡ āĻāĻŦāĻ‚ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻĒā§āĻ˛ā§āϝāĻžāϟāĻĢāĻ°ā§āĻŽ āĻŦāĻž āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ⧇ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āϜāĻŋāύāĻŋāϏ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĨ¤ āϰāĻžāĻ¸ā§āϟ āĻ " -"āϤāĻž āύāĻŋāĻ°ā§āϧāĻžāϰāĻŋāϤ āĻŽā§āϝāĻžāύ āύāĻŋā§Ÿā§‡ āĻĨāĻžāϕ⧇āĨ¤" -#: src/types-and-values/arithmetic.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"Change the `i32`'s to `i16` to see an integer overflow, which panics " -"(checked) in a debug build and wraps in a release build. There are other " -"options, such as overflowing, saturating, and carrying. These are accessed " -"with method syntax, e.g., `(a * b).saturating_add(b * c).saturating_add(c * " -"a)`." +"I'm seeing a problem initializing a variable of type X with type Y, where X " +"and Y are both function types. This is because your C++ function doesn't " +"quite match the declaration in your `cxx::bridge`." msgstr "" -"āχāĻ¨ā§āϟāĻŋāϜāĻžāϰ āĻ“āĻ­āĻžāϰāĻĢā§āϞ⧋ āϏāϰāĻžāϏāϰāĻŋ āĻĻ⧇āĻ–āĻŦāĻžāϰ āϜāĻ¨ā§āϝ⧇ āϕ⧇ āĻ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰ⧇ āĻĻ⧇āϖ⧁āύāĨ¤ āĻĄāĻŋāĻŦāĻžāĻ— āĻ…āĻŦāĻ¸ā§āĻĨāĻžā§Ÿ " -"āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āĻšāϞ⧇ āĻāϟāĻŋ āφāϤāĻ‚āĻ•āĻŋāϤ (āĻĒā§āϝāĻžāύāĻŋāĻ•) āĻšā§Ÿā§‡ āĻĒāϰ⧇ āĻāĻŦāĻ‚ āĻŽā§āĻ•ā§āϤāĻŋāĻ—āĻžāĻŽā§€ āύāĻŋāĻ°ā§āĻŽāĻžāĻŖ āĻšāϞ⧇ āϏ⧇āϟāĻŋ āĻŽā§ā§œāĻŋā§Ÿā§‡ " -"āĻĻ⧇āĻ“ā§ŸāĻž āĻšā§Ÿā§‡ āύāĻŋāĻœā§‡ āύāĻŋāĻœā§‡āχāĨ¤ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāĻ“ āφāϛ⧇ āϝ⧇āĻŽāύ āĻ“āĻ­āĻžāϰāĻĢā§āϞ⧋ (āĻŽā§āϝāĻžāύ āωāĻĒāĻšā§‡ āĻĒ⧜āĻž), " -"āĻ¸ā§āϝāĻžāϚ⧁āϰ⧇āϟāĻŋāĻ‚ (āĻŦāĻž āĻĒāϰāĻŋāĻĒ⧃āĻ•ā§āϤ āĻ•āϰāĻž) āĻāĻŦāĻ‚ āĻ•ā§āϝāĻžāϰāĻŋāĻ‚ (āĻŦāĻž āĻŦāĻšāύ āĻ•āϰāĻž)āĨ¤ āĻāϗ⧁āϞāĻŋ āĻ…āĻ­āĻŋāĻ—āĻŽāύ āĻ•āϰāĻŦāĻžāϰ āϜāĻ¨ā§āϝ⧇ " -"āĻāϰāĻ–āĻŽ āϕ⧋āύ⧋ āĻŽā§‡āĻĨāĻĄ āϏāĻŋāύāĻŸā§‡āĻ•ā§āϏ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇ `(a * b).saturating_add(b * c)." -"saturating_add(c * a)`āĨ¤" -#: src/types-and-values/arithmetic.md +#: src/exercises/chromium/interoperability-with-cpp.md msgid "" -"In fact, the compiler will detect overflow of constant expressions, which is " -"why the example requires a separate function." +"I seem to be able to freely convert C++ references into Rust references. " +"Doesn't that risk UB? For CXX's _opaque_ types, no, because they are zero-" +"sized. For CXX trivial types yes, it's _possible_ to cause UB, although " +"CXX's design makes it quite difficult to craft such an example." msgstr "" -"āĻĒā§āϰāĻ•ā§ƒāϤāĻĒāĻ•ā§āώ⧇, āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āĻ§ā§āϰ⧁āĻŦāĻ• āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϰ āĻ“āĻ­āĻžāϰāĻĢā§āϞ⧋ āϏāύāĻžāĻ•ā§āϤ āĻ•āϰāĻŦ⧇, āϝāĻžāϰ āĻ•āĻžāϰāϪ⧇ āωāĻĻāĻžāĻšāϰāĻŖāϟāĻŋāϰ " -"āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āφāϞāĻžāĻĻāĻž āĻĢāĻžāĻ‚āĻļāύ āĻĒā§āϰāϝāĻŧā§‹āϜāύāĨ¤" -#: src/types-and-values/strings.md +#: src/chromium/adding-third-party-crates.md msgid "" -"Rust has two types to represent strings, both of which will be covered in " -"more depth later. Both _always_ store UTF-8 encoded strings." +"Rust libraries are called \"crates\" and are found at [crates.io](https://" +"crates.io). It's _very easy_ for Rust crates to depend upon one another. So " +"they do!" msgstr "" -"āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚āϗ⧁āϞāĻŋāϕ⧇ āωāĻĒāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āϰāĻžāĻ¸ā§āϟ āĻ āĻĻ⧁āϟāĻŋ āωāĻĒāĻžā§Ÿā§‡ āφāϛ⧇, āωāĻ­āϝāĻŧāχ āĻĒāϰāĻŦāĻ°ā§āϤ⧀āϤ⧇ āφāϰāĻ“ āĻ—āĻ­ā§€āϰāϤāĻžāϝāĻŧ " -"āĻ•āĻ­āĻžāϰ āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤ āωāĻ­āϝāĻŧāχ _āϏāĻŦāϏāĻŽā§Ÿā§‡_ āχāω.āϟāĻŋ.āĻāĻĢ-ā§Ž āĻāύāϕ⧋āĻĄ āĻ•āϰ⧇ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰ⧇āĨ¤" - -#: src/types-and-values/strings.md -msgid "`String` - a modifiable, owned string." -msgstr "`String` - āĻāĻ•āϟāĻŋ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύāϝ⧋āĻ—ā§āϝ, āĻŽāĻžāϞāĻŋāĻ•āĻžāύāĻžāϧ⧀āύ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚āĨ¤" - -#: src/types-and-values/strings.md -msgid "`&str` - a read-only string. String literals have this type." -msgstr "`&str` - āĻāĻ•āϟāĻŋ āĻĒāĻ āύāϝ⧋āĻ—ā§āϝ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚āĨ¤ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āϞāĻŋāϟāĻžāϰ⧇āϞ⧇ āĻāχ āϧāϰāύ āφāϛ⧇āĨ¤" - -#: src/types-and-values/strings.md -msgid "\"Greetings\"" -msgstr "\"Greetings\"" - -#: src/types-and-values/strings.md -msgid "\"đŸĒ\"" -msgstr "\"đŸĒ\"" - -#: src/types-and-values/strings.md -msgid "\", \"" -msgstr "\", \"" - -#: src/types-and-values/strings.md -msgid "\"final sentence: {}\"" -msgstr "\"final sentence: {}\"" - -#: src/types-and-values/strings.md -#: src/methods-and-traits/traits/associated-types.md -#: src/async/control-flow/join.md -msgid "\"{:?}\"" -msgstr "\"{:?}\"" -#: src/types-and-values/strings.md -msgid "//println!(\"{:?}\", &sentence[12..13]);" -msgstr "//println!(\"{:?}\", &sentence[12..13]);" +#: src/chromium/adding-third-party-crates.md +msgid "Property" +msgstr "" -#: src/types-and-values/strings.md -msgid "" -"This slide introduces strings. Everything here will be covered in more depth " -"later, but this is enough for subsequent slides and exercises to use strings." +#: src/chromium/adding-third-party-crates.md +msgid "C++ library" msgstr "" -"āĻāχ āĻ¸ā§āϞāĻžāχāĻĄ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻ•āĻŋ āϜāĻŋāύāĻŋāϏ āĻāϟāĻž āĻĻ⧇āĻ–āĻžā§ŸāĨ¤ āĻāĻ–āĻžāύ⧇ āϏāĻŦāĻ•āĻŋāϛ⧁ āĻĒāϰ⧇ āφāϰāĻ“ āĻ—āĻ­ā§€āϰāϤāĻžāϝāĻŧ āĻ•āĻ­āĻžāϰ āĻ•āϰāĻž āĻšāĻŦ⧇, " -"āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ,āĻĒāϰāĻŦāĻ°ā§āϤ⧀ āĻ¸ā§āϞāĻžāχāĻĄā§‡āϰ āϜāĻ¨ā§āϝ⧇ āĻāĻŦāĻ‚ āĻ…āύ⧁āĻļā§€āϞāύ⧇āϰ āϜāĻ¨ā§āϝ āĻāϟāĻŋ āϝāĻĨ⧇āĻˇā§āϟāĨ¤" -#: src/types-and-values/strings.md -msgid "Invalid UTF-8 in a string is UB, and this not allowed in safe Rust." +#: src/chromium/adding-third-party-crates.md +msgid "Rust crate" msgstr "" -"UB āĻāĻ•āϟāĻŋ āχāω.āϟāĻŋ.āĻāĻĢ-ā§Ž āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚-āĻ āĻĨāĻžāĻ•āĻž āϭ⧁āϞ āĻāĻŦāĻ‚ āϏ⧇āχ āϜāĻ¨ā§āϝ⧇ āĻāϟāĻŋ āύāĻŋāϰāĻžāĻĒāĻĻ āϰāĻžāĻ¸ā§āϟ āĻāϰ āϭ⧇āϤāϰ⧇ " -"āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžā§Ÿ āύāĻžāĨ¤" -#: src/types-and-values/strings.md -msgid "" -"`String` is a user-defined type with a constructor (`::new()`) and methods " -"like `s.push_str(..)`." +#: src/chromium/adding-third-party-crates.md +msgid "Build system" msgstr "" -"`String` āĻšāĻšā§āϛ⧇ āĻ•āύāĻ¸ā§āĻŸā§āϰāĻžāĻ•ā§āϟāϰ (`::new()`) āϏāĻš āĻāĻ•āϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀-āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻĒā§āϰāĻ•āĻžāϰ āĻāĻŦāĻ‚ " -"āĻāϤ⧇ `s.push_str(..)` -āϰ āĻŽāϤāύ āĻŽā§‡āĻĨāĻĄ āĻ“ āĻ°ā§Ÿā§‡āϛ⧇āĨ¤" -#: src/types-and-values/strings.md -msgid "" -"The `&` in `&str` indicates that this is a reference. We will cover " -"references later, so for now just think of `&str` as a unit meaning \"a read-" -"only string\"." +#: src/chromium/adding-third-party-crates.md +msgid "Lots" msgstr "" -"`&str` āĻāϟāĻž āϝ⧇ āĻāĻ•āϟāĻž āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ āϏ⧇āϟāĻž āĻāϟāĻžāϤ⧇ āĻĨāĻžāĻ•āĻž `&` āĻĻāĻŋā§Ÿā§‡ āĻŦā§‹āĻāĻž āϝāĻžāĻšā§āϛ⧇āĨ¤ āφāĻŽāϰāĻž āĻĒāϰ⧇ " -"āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ āĻĻ⧇āĻ–āĻŦā§‹ , āϤāĻžāχ āφāĻĒāĻžāϤāϤ āĻļ⧁āϧ⧁ `&str` āϕ⧇ āĻāĻ•āϟāĻŋ āχāωāύāĻŋāϟ āĻšāĻŋāϏ⧇āĻŦ⧇ āĻ­āĻžāĻŦ⧁āύ āϝāĻžāϰ āĻ…āĻ°ā§āĻĨ \"āĻāĻŽāύ " -"āĻāĻ•āϟāĻŋ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āϝāĻž āĻļ⧁āϧ⧁ āĻĒāĻ āύāϝ⧋āĻ—ā§āϝ \"āĨ¤" -#: src/types-and-values/strings.md -msgid "" -"The commented-out line is indexing into the string by byte position. " -"`12..13` does not end on a character boundary, so the program panics. Adjust " -"it to a range that does, based on the error message." +#: src/chromium/adding-third-party-crates.md +msgid "Consistent: `Cargo.toml`" msgstr "" -"āĻ•āĻŽā§‡āĻ¨ā§āϟ āĻ•āϰāĻž āϞāĻžāχāύ āĻŦāĻžāχāϟ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ āĻĻā§āĻŦāĻžāϰāĻž āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻŽāĻ§ā§āϝ⧇ āχāύāĻĄā§‡āĻ•ā§āϏ āĻ•āϰāϛ⧇āĨ¤ `12..13` āϏ⧀āĻŽāĻžāύāĻžāϝāĻŧ " -"āĻĒā§œā§‡ āύāĻž, āϤāĻžāχ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āφāϤāĻ™ā§āĻ•āĻŋāϤ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰ⧇āĨ¤ āĻ¤ā§āϰ⧁āϟāĻŋ āĻŦāĻžāĻ°ā§āϤāĻžāϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇ " -"āĻāϟāĻŋāϕ⧇ āĻāĻ•āϟāĻŋ āϏāĻ āĻŋāĻ• āϏ⧀āĻŽāĻžāύāĻžāϰ āĻŽāĻ§ā§āϝ⧇ āύāĻŋā§Ÿā§‡ āφāϏ⧁āύāĨ¤" -#: src/types-and-values/strings.md -msgid "" -"Raw strings allow you to create a `&str` value with escapes disabled: " -"`r\"\\n\" == \"\\\\n\"`. You can embed double-quotes by using an equal " -"amount of `#` on either side of the quotes:" +#: src/chromium/adding-third-party-crates.md +msgid "Typical library size" msgstr "" -"Raw strings allow you to create a `&str` value with escapes disabled: " -"`r\"\\n\" == \"\\\\n\"`. You can embed double-quotes by using an equal " -"amount of `#` on either side of the quotes:" -#: src/types-and-values/strings.md -msgid "" -"Using `{:?}` is a convenient way to print array/vector/struct of values for " -"debugging purposes, and it's commonly used in code." +#: src/chromium/adding-third-party-crates.md +msgid "Large-ish" msgstr "" -"`{:?}` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻĄāĻŋāĻŦāĻžāĻ—āĻŋāĻ‚ āωāĻĻā§āĻĻ⧇āĻļā§āϝ⧇ āĻŽāĻžāύāϗ⧁āϞāĻŋāϰ āĻ…ā§āϝāĻžāϰ⧇/āϭ⧇āĻ•ā§āϟāϰ/āĻ¸ā§āĻŸā§āϰāĻžāĻ•āϟ āĻĒā§āϰāĻŋāĻ¨ā§āϟ āĻ•āϰāĻžāϰ āĻāĻ•āϟāĻŋ " -"āϏ⧁āĻŦāĻŋāϧāĻžāϜāύāĻ• āωāĻĒāĻžāϝāĻŧ āĻāĻŦāĻ‚ āĻāϟāĻŋ āϏāĻžāϧāĻžāϰāĻŖāϤ āĻ…āύ⧇āĻ• āϕ⧋āĻĄā§‡ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧāĨ¤" -#: src/types-and-values/inference.md -msgid "Rust will look at how the variable is _used_ to determine the type:" +#: src/chromium/adding-third-party-crates.md +msgid "Small" msgstr "" -"āĻāĻ•āϟāĻŋ āĻ­ā§āϝāĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇ āϤāĻž āĻĻ⧇āϖ⧇ āϰāĻžāĻ¸ā§āϟ āϏ⧇āϟāĻŋāϰ āϟāĻžāχāĻĒ āĻ āĻŋāĻ• āĻ•āϰāĻŦ⧇:" -#: src/types-and-values/inference.md -msgid "" -"This slide demonstrates how the Rust compiler infers types based on " -"constraints given by variable declarations and usages." +#: src/chromium/adding-third-party-crates.md +msgid "Transitive dependencies" msgstr "" -"āĻāχ āĻ¸ā§āϞāĻžāχāĻĄāϟāĻŋ āĻĻ⧇āĻ–āĻžāϝāĻŧ āϝ⧇ āϕ⧀āĻ­āĻžāĻŦ⧇ āϰāĻžāĻ¸ā§āĻŸā§‡āϰ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āĻāĻ•āϟāĻŋ āĻ­ā§āϝāĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ⧇āϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύāĻļā§€āϞ āĻ˜ā§‹āώāĻŖāĻž " -"āĻāĻŦāĻ‚ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻĻā§āĻŦāĻžāϰāĻž āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻžāϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇ āϏ⧇āϟāĻŋāϰ āϟāĻžāχāĻĒ āĻ…āύ⧁āĻŽāĻžāύ āĻ•āϰ⧇āĨ¤" -#: src/types-and-values/inference.md -msgid "" -"It is very important to emphasize that variables declared like this are not " -"of some sort of dynamic \"any type\" that can hold any data. The machine " -"code generated by such declaration is identical to the explicit declaration " -"of a type. The compiler does the job for us and helps us write more concise " -"code." +#: src/chromium/adding-third-party-crates.md +msgid "Few" msgstr "" -"āĻāϟāĻž āĻœā§‹āϰ āĻĻ⧇āĻ“āϝāĻŧāĻž āϖ⧁āĻŦāχ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ āϝ⧇ āĻāχāϰāĻ•āĻŽ āĻ˜ā§‹āώāĻŋāϤ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϗ⧁āϞāĻŋ āϕ⧋āύ āϧāϰāϪ⧇āϰ āĻĄāĻžāχāύāĻžāĻŽāĻŋāĻ• " -"\"āϝ⧇āϕ⧋āύ āϧāϰāϪ⧇āϰ\" āύāϝāĻŧ āϝāĻž āϕ⧋āύāĻ“ āĻĄā§‡āϟāĻž āϧāĻžāϰāĻŖ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āĻāχ āϧāϰāύ⧇āϰ āĻ˜ā§‹āώāĻŖāĻž āĻĻā§āĻŦāĻžāϰāĻž āωāĻ¤ā§āĻĒāĻ¨ā§āύ " -"āĻŽā§‡āĻļāĻŋāύ āϕ⧋āĻĄ āĻāĻ•āϟāĻŋ āϟāĻžāχāĻĒ-āĻāϰ āϏ⧁āĻ¸ā§āĻĒāĻˇā§āϟ āĻ˜ā§‹āώāĻŖāĻžāϰ āĻ…āύ⧁āϰ⧂āĻĒāĨ¤ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āφāĻŽāĻžāĻĻ⧇āϰ āϜāĻ¨ā§āϝ āĻāχ āĻ•āĻžāϜ āĻ•āϰ⧇ āĻāĻŦāĻ‚ " -"āφāĻŽāĻžāĻĻ⧇āϰ āφāϰāĻ“ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤ āϕ⧋āĻĄ āϞāĻŋāĻ–āϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇āĨ¤" -#: src/types-and-values/inference.md -msgid "" -"When nothing constrains the type of an integer literal, Rust defaults to " -"`i32`. This sometimes appears as `{integer}` in error messages. Similarly, " -"floating-point literals default to `f64`." +#: src/chromium/adding-third-party-crates.md +msgid "For a Chromium engineer, this has pros and cons:" msgstr "" -"āϝāĻ–āύ āϕ⧋āύ āĻ•āĻŋāϛ⧁āχ āĻĒā§‚āĻ°ā§āĻŖāϏāĻ‚āĻ–ā§āϝāĻžāϰ āφāĻ•ā§āώāϰāĻŋāϕ⧇āϰ āϧāϰāĻŖāϕ⧇ āĻŦāĻžāϧāĻž āĻĻ⧇āϝāĻŧ āύāĻž, āϤāĻ–āύ āϰāĻžāĻ¸ā§āϟ āϏ⧇āϟāĻžāϕ⧇ `i32` " -"āĻšāĻŋāϏāĻžāĻŦ⧇ āϭ⧇āĻŦ⧇ āύāĻŋā§Ÿā§‡ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤ āĻāϟāĻŋ āĻ•āĻ–āύāĻ“ āĻ•āĻ–āύāĻ“ āĻ¤ā§āϰ⧁āϟāĻŋ āĻŦāĻžāĻ°ā§āϤāĻžāϗ⧁āϞāĻŋāϤ⧇ `{integer}` āĻšāĻŋāϏāĻžāĻŦ⧇ " -"āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšāϝāĻŧāĨ¤ āĻāĻ•āχāĻ­āĻžāĻŦ⧇, āĻĢā§āϞ⧋āϟāĻŋāĻ‚-āĻĒāϝāĻŧ⧇āĻ¨ā§āϟ āϞāĻŋāϟāĻžāϰāĻžāϞ āϕ⧇ `f64` āĻ āϭ⧇āĻŦ⧇ āύ⧇āĻ“ā§ŸāĻž āĻšā§Ÿā§‡āĨ¤" - -#: src/types-and-values/inference.md -msgid "// ERROR: no implementation for `{float} == {integer}`" -msgstr "// ERROR: no implementation for `{float} == {integer}`" -#: src/types-and-values/exercise.md +#: src/chromium/adding-third-party-crates.md msgid "" -"The first and second Fibonacci numbers are both `1`. For n>2, the n'th " -"Fibonacci number is calculated recursively as the sum of the n-1'th and " -"n-2'th Fibonacci numbers." +"All crates use a common build system so we can automate their inclusion into " +"Chromium..." msgstr "" -"āĻĒā§āϰāĻĨāĻŽ āĻāĻŦāĻ‚ āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āĻĢāĻŋāĻŦā§‹āύāĻžāĻšā§āϚāĻŋ āϏāĻ‚āĻ–ā§āϝāĻž āωāĻ­āϝāĻŧāχ `1`āĨ¤ n>⧍ āĻāϰ āϜāĻ¨ā§āϝ, n'āϤāĻŽ āĻĢāĻŋāĻŦā§‹āύāĻžāĻšā§āϚāĻŋ āϏāĻ‚āĻ–ā§āϝāĻžāϟāĻŋ " -"n-ā§§ āĻāĻŦāĻ‚ n-⧍'āϤāĻŽ āĻĢāĻŋāĻŦā§‹āύāĻžāĻšā§āϚāĻŋ āϏāĻ‚āĻ–ā§āϝāĻžāϰ āϝ⧋āĻ—āĻĢāϞ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻ­āĻžāĻŦ⧇ āĻ—āĻŖāύāĻž āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤" -#: src/types-and-values/exercise.md +#: src/chromium/adding-third-party-crates.md msgid "" -"Write a function `fib(n)` that calculates the n'th Fibonacci number. When " -"will this function panic?" +"... but, crates typically have transitive dependencies, so you will likely " +"have to bring in multiple libraries." msgstr "" -"āĻāĻ•āϟāĻŋ āĻĢāĻžāĻ‚āĻļāύ āϞāĻŋāϖ⧁āύ `fib(n)` āϝāĻž n'th āĻĢāĻŋāĻŦā§‹āύāĻžāĻšā§āϚāĻŋ āϏāĻ‚āĻ–ā§āϝāĻž āĻ—āĻŖāύāĻž āĻ•āϰ⧇āĨ¤ āĻ•āĻ–āύ āĻāχ āĻĢāĻžāĻ‚āĻļāύ " -"āĻĒā§āϝāĻžāύāĻŋāĻ• āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇?" -#: src/types-and-values/exercise.md -msgid "// The base case." -msgstr "// The base case." - -#: src/types-and-values/exercise.md src/control-flow-basics/exercise.md -msgid "\"Implement this\"" -msgstr "\"Implement this\"" +#: src/chromium/adding-third-party-crates.md +msgid "We'll discuss:" +msgstr "" -#: src/types-and-values/exercise.md -msgid "// The recursive case." -msgstr "// The recursive case." +#: src/chromium/adding-third-party-crates.md +msgid "How to put a crate in the Chromium source code tree" +msgstr "" -#: src/types-and-values/exercise.md src/types-and-values/solution.md -msgid "\"fib(n) = {}\"" -msgstr "\"fib(n) = {}\"" +#: src/chromium/adding-third-party-crates.md +msgid "How to make `gn` build rules for it" +msgstr "" -#: src/control-flow-basics.md -msgid "[if Expressions](./control-flow-basics/if.md) (4 minutes)" -msgstr "[if āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ](./control-flow-basics/if.md) (ā§Ē āĻŽāĻŋāύāĻŋāϟ)" +#: src/chromium/adding-third-party-crates.md +msgid "How to audit its source code for sufficient safety." +msgstr "" -#: src/control-flow-basics.md -msgid "[Loops](./control-flow-basics/loops.md) (5 minutes)" -msgstr "[āϞ⧁āĻĒ](./control-flow-basics/loops.md) (ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" +#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md +msgid "Configuring the `Cargo.toml` file to add crates" +msgstr "" -#: src/control-flow-basics.md +#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md msgid "" -"[break and continue](./control-flow-basics/break-continue.md) (4 minutes)" +"Chromium has a single set of centrally-managed direct crate dependencies. " +"These are managed through a single [`Cargo.toml`](https://source.chromium." +"org/chromium/chromium/src/+/main:third_party/rust/chromium_crates_io/Cargo." +"toml):" msgstr "" -"[break āĻāĻŦāĻ‚ continue](./control-flow-basics/break-continue.md) (ā§Ē āĻŽāĻŋāύāĻŋāϟ)" -#: src/control-flow-basics.md +#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md msgid "" -"[Blocks and Scopes](./control-flow-basics/blocks-and-scopes.md) (5 minutes)" -msgstr "[āĻŦā§āϞāĻ• āĻāĻŦāĻ‚ āĻ¸ā§āϕ⧋āĻĒ](./control-flow-basics/blocks-and-scopes.md) (ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" - -#: src/control-flow-basics.md -msgid "[Functions](./control-flow-basics/functions.md) (3 minutes)" -msgstr "[āĻĢāĻžāĻ‚āĻļāύ](./control-flow-basics/functions.md) (ā§Š āĻŽāĻŋāύāĻŋāϟ)" - -#: src/control-flow-basics.md -msgid "[Macros](./control-flow-basics/macros.md) (2 minutes)" -msgstr "[āĻŽā§āϝāĻžāĻ•ā§āϰ⧋](./control-flow-basics/macros.md) (⧍ āĻŽāĻŋāύāĻŋāϟ)" +"```toml\n" +"[dependencies]\n" +"bitflags = \"1\"\n" +"cfg-if = \"1\"\n" +"cxx = \"1\"\n" +"# lots more...\n" +"```" +msgstr "" -#: src/control-flow-basics.md +#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md msgid "" -"[Exercise: Collatz Sequence](./control-flow-basics/exercise.md) (15 minutes)" -msgstr "[āĻ…āύ⧁āĻļā§€āϞāύ⧀: āĻ•āĻ˛ā§āϝāĻžāϟāϜ āĻāϰ āĻ•ā§āϰāĻŽ](./control-flow-basics/exercise.md) (ā§§ā§Ģ āĻŽāĻŋāύāĻŋāϟ)" - -#: src/control-flow-basics.md src/generics.md src/modules.md -msgid "This segment should take about 40 minutes" -msgstr "āĻāχ āĻ…āĻ‚āĻļāϟāĻŋ āĻĒā§āϰāĻžāϝāĻŧ ā§Ēā§Ļ āĻŽāĻŋāύāĻŋāϟ āϏāĻŽāϝāĻŧ āύ⧇āĻŦ⧇" - -#: src/control-flow-basics/if.md -msgid "`if` expressions" -msgstr "`if` āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ" +"As with any other `Cargo.toml`, you can specify [more details about the " +"dependencies](https://doc.rust-lang.org/cargo/reference/specifying-" +"dependencies.html) --- typically, you'll want to specify the `features` that " +"you wish to enable in the crate." +msgstr "" -#: src/control-flow-basics/if.md +#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md msgid "" -"You use [`if` expressions](https://doc.rust-lang.org/reference/expressions/" -"if-expr.html#if-expressions) exactly like `if` statements in other languages:" +"When adding a crate to Chromium, you'll frequently need to provide " +"additional information in an additional file, `gnrt_config.toml`, which " +"we'll meet next." msgstr "" -"[`if` āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ](https://doc.rust-lang.org/reference/expressions/if-expr." -"html#if-expressions) āϰāĻžāĻ¸ā§āϟ āĻ āĻ āĻŋāĻ• āĻ…āĻ¨ā§āϝ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāĻŋāĻ‚ āĻ­āĻžāώāĻžāϰ `if` āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϰ āĻŽāϤāύ āĻšā§Ÿ " -"āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšā§Ÿā§‡:" - -#: src/control-flow-basics/if.md -msgid "\"zero!\"" -msgstr "\"zero!\"" - -#: src/control-flow-basics/if.md -msgid "\"biggish\"" -msgstr "\"biggish\"" - -#: src/control-flow-basics/if.md -msgid "\"huge\"" -msgstr "\"huge\"" -#: src/control-flow-basics/if.md +#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md msgid "" -"In addition, you can use `if` as an expression. The last expression of each " -"block becomes the value of the `if` expression:" +"Alongside `Cargo.toml` is [`gnrt_config.toml`](https://source.chromium.org/" +"chromium/chromium/src/+/main:third_party/rust/chromium_crates_io/gnrt_config." +"toml). This contains Chromium-specific extensions to crate handling." msgstr "" -"āωāĻĒāϰāĻ¨ā§āϤ⧁, āφāĻĒāύāĻŋ `if` āϕ⧇āĻ“ āĻāĻ•āϟāĻŋ āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻŦā§āϞāϕ⧇āϰ " -"āĻļ⧇āώ āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ `if` āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϰ āĻŽāĻžāύ āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧ:" -#: src/control-flow-basics/if.md -msgid "\"small\"" -msgstr "\"small\"" - -#: src/control-flow-basics/if.md -msgid "\"large\"" -msgstr "\"large\"" +#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md +msgid "" +"If you add a new crate, you should specify at least the `group`. This is one " +"of:" +msgstr "" -#: src/control-flow-basics/if.md -msgid "\"number size: {}\"" -msgstr "\"number size: {}\"" +#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md +#: src/chromium/adding-third-party-crates/depending-on-a-crate.md +msgid "For instance," +msgstr "" -#: src/control-flow-basics/if.md +#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md msgid "" -"Because `if` is an expression and must have a particular type, both of its " -"branch blocks must have the same type. Show what happens if you add `;` " -"after `\"small\"` in the second example." +"Depending on the crate source code layout, you may also need to use this " +"file to specify where its `LICENSE` file(s) can be found." msgstr "" -"āϝ⧇āĻšā§‡āϤ⧁ `if` āĻāĻ•āϟāĻŋ āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ āĻāĻŦāĻ‚ āĻ…āĻŦāĻļā§āϝāχ āĻāϟāĻŋāϰ āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϟāĻžāχāĻĒ āĻĨāĻžāĻ•āϤ⧇ āĻšāĻŦ⧇, āϤāĻžāχ āωāĻ­āϝāĻŧ " -"āĻļāĻžāĻ–āĻž āĻŦā§āϞāϕ⧇āϰ āĻāĻ•āχ āϟāĻžāχāĻĒ āĻĨāĻžāĻ•āϤ⧇ āĻšāĻŦ⧇āĨ¤ āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āωāĻĻāĻžāĻšāϰāϪ⧇ `\"small\"` āĻāϰ āĻĒāϰ⧇ `;` āϝ⧋āĻ— " -"āĻ•āϰāϞ⧇ āĻ•āĻŋ āĻšāĻŦ⧇ āϤāĻž āĻĻ⧇āĻ–āĻžāύāĨ¤" -#: src/control-flow-basics/if.md +#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md msgid "" -"When `if` is used in an expression, the expression must have a `;` to " -"separate it from the next statement. Remove the `;` before `println!` to see " -"the compiler error." +"Later, we'll see some other things you will need to configure in this file " +"to resolve problems." msgstr "" -"āϝāĻ–āύ āĻāĻ•āϟāĻŋ āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϤ⧇ `if` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšāϝāĻŧ, āϤāĻ–āύ āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϟāĻŋāϰ āĻ…āĻŦāĻļā§āϝāχ āĻļ⧇āώ⧇ āĻāĻ•āϟāĻŋ `;` " -"āĻĨāĻžāĻ•āϤ⧇ āĻšāĻŦ⧇ āϝāĻž āĻĒāϰāĻŦāĻ°ā§āϤ⧀ āĻŦāĻŋāĻŦ⧃āϤāĻŋ āĻĨ⧇āϕ⧇ āϏ⧇āϟāĻŋāϕ⧇ āφāϞāĻžāĻĻāĻž āĻ•āϰāĻŦ⧇āĨ¤ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āĻ¤ā§āϰ⧁āϟāĻŋ āĻĻ⧇āĻ–āϤ⧇ " -"`println!` āĻāϰ āφāϗ⧇ `;` āϏāϰāĻŋā§Ÿā§‡ āĻĻ⧇āϖ⧁āύāĨ¤" -#: src/control-flow-basics/loops.md -msgid "There are three looping keywords in Rust: `while`, `loop`, and `for`:" -msgstr "āϰāĻžāĻ¸ā§āĻŸā§‡ āϤāĻŋāύāϟāĻŋ āϞ⧁āĻĒāĻŋāĻ‚ āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āϰāϝāĻŧ⧇āϛ⧇: `while`, `loop`, āĻ“ `for`:" +#: src/chromium/adding-third-party-crates/downloading-crates.md +msgid "" +"A tool called `gnrt` knows how to download crates and how to generate `BUILD." +"gn` rules." +msgstr "" -#: src/control-flow-basics/loops.md -msgid "`while`" -msgstr "`while`" +#: src/chromium/adding-third-party-crates/downloading-crates.md +msgid "To start, download the crate you want like this:" +msgstr "" -#: src/control-flow-basics/loops.md +#: src/chromium/adding-third-party-crates/downloading-crates.md msgid "" -"The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-" -"expr.html#predicate-loops) works much like in other languages, executing the " -"loop body as long as the condition is true." +"Although the `gnrt` tool is part of the Chromium source code, by running " +"this command you will be downloading and running its dependencies from " +"`crates.io`. See [the earlier section](../cargo.md) discussing this security " +"decision." msgstr "" -"[`while` āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ](https://doc.rust-lang.org/reference/expressions/loop-expr." -"html#predicate-loops) āϰāĻžāĻ¸ā§āϟ āĻ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻ­āĻžāώāĻžāϰ `while` āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ āĻāϰ āĻŽāϤ⧋āχ āĻ•āĻžāϜ āĻ•āϰ⧇, " -"āϝāϤāĻ•ā§āώāĻŖ āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻļāĻ°ā§āϤāϟāĻŋ āϏāĻ¤ā§āϝ āĻšāϝāĻŧ āϤāϤāĻ•ā§āώāĻŖ āϞ⧁āĻĒ āĻŦāĻĄāĻŋ āĻ•āĻžāĻ°ā§āϝāĻ•āϰ āĻ•āϰ⧇āĨ¤" -#: src/control-flow-basics/loops.md -msgid "\"Final x: {x}\"" -msgstr "\"Final x: {x}\"" +#: src/chromium/adding-third-party-crates/downloading-crates.md +msgid "This `vendor` command may download:" +msgstr "" -#: src/control-flow-basics/loops/for.md -msgid "" -"The [`for` loop](https://doc.rust-lang.org/std/keyword.for.html) iterates " -"over ranges of values or the items in a collection:" +#: src/chromium/adding-third-party-crates/downloading-crates.md +msgid "Your crate" msgstr "" -"[`for` āϞ⧁āĻĒ](https://doc.rust-lang.org/std/keyword.for.html) āĻāĻ•āϟāĻŋ āĻŽāĻžāύ⧇āϰ " -"āĻĒāϰāĻŋāϏ⧀āĻŽāĻž āĻŦāĻž āϏāĻ‚āĻ—ā§āϰāĻšā§‡āϰ āφāχāĻŸā§‡āĻŽāϗ⧁āϞāĻŋāϰ āωāĻĒāϰ āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ āĻ•āϰ⧇:" -#: src/control-flow-basics/loops/for.md -msgid "\"elem: {elem}\"" -msgstr "\"elem: {elem}\"" +#: src/chromium/adding-third-party-crates/downloading-crates.md +msgid "Direct and transitive dependencies" +msgstr "" -#: src/control-flow-basics/loops/for.md +#: src/chromium/adding-third-party-crates/downloading-crates.md msgid "" -"Under the hood `for` loops use a concept called \"iterators\" to handle " -"iterating over different kinds of ranges/collections. Iterators will be " -"discussed in more detail later." +"New versions of other crates, as required by `cargo` to resolve the complete " +"set of crates required by Chromium." msgstr "" -"`āĻĢāϰ` āϞ⧁āĻĒāϗ⧁āϞāĻŋ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āϧāϰāϪ⧇āϰ āϰ⧇āĻžā§āϜ/āϏāĻ‚āĻ—ā§āϰāĻšā§‡āϰ āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž āĻ•āϰāϤ⧇ \"āχāϟāĻžāϰ⧇āϟāϰ\" āύāĻžāĻŽāĻ• " -"āĻāĻ•āϟāĻŋ āϧāĻžāϰāĻŖāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇āĨ¤ āχāϟāĻžāϰ⧇āϟāϰ āĻĒāϰ⧇ āφāϰāĻ“ āĻŦāĻŋāĻļāĻĻ⧇ āφāϞ⧋āϚāύāĻž āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤" -#: src/control-flow-basics/loops/for.md +#: src/chromium/adding-third-party-crates/downloading-crates.md msgid "" -"Note that the `for` loop only iterates to `4`. Show the `1..=5` syntax for " -"an inclusive range." +"Chromium maintains patches for some crates, kept in `//third_party/rust/" +"chromium_crates_io/patches`. These will be reapplied automatically, but if " +"patching fails you may need to take manual action." msgstr "" -"āχāϟāĻž āϞāĻ•ā§āĻˇā§āϝ āĻ•āϰāĻž āĻĻāϰāĻ•āĻžāϰ āϝ⧇ `for` -āϟāĻŋ āϞ⧁āĻĒ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ `4` āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ āĻ•āϰ⧇āĨ¤ āĻāĻ–āĻžāύ⧇ `5` " -"āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ āĻ•āϰāĻŦāĻžāϰ āϜāĻ¨ā§āϝ⧇ `1..=5` āĻ—āĻ āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻĻāϰāĻ•āĻžāϰāĨ¤" -#: src/control-flow-basics/loops/loop.md +#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md msgid "" -"The [`loop` statement](https://doc.rust-lang.org/std/keyword.loop.html) just " -"loops forever, until a `break`." +"Once you've downloaded the crate, generate the `BUILD.gn` files like this:" msgstr "" -"`break` āύāĻž āĻĒāĻžāĻ“ā§ŸāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ āĻ•āϰāϤ⧇āχ āĻĨāĻžāϕ⧇ āĻāĻ•āϟāĻŋ [`loop` statement](https://" -"doc.rust-lang.org/std/keyword.loop.html)āĨ¤" -#: src/control-flow-basics/loops/loop.md -msgid "\"{i}\"" -msgstr "\"{i}\"" +#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md +msgid "Now run `git status`. You should find:" +msgstr "" -#: src/control-flow-basics/break-continue.md +#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md msgid "" -"If you want to immediately start the next iteration use [`continue`](https://" -"doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)." +"At least one new crate source code in `third_party/rust/chromium_crates_io/" +"vendor`" msgstr "" -"āφāĻĒāύāĻŋ āĻ…āĻŦāĻŋāϞāĻŽā§āĻŦ⧇ āĻĒāϰāĻŦāĻ°ā§āϤ⧀ āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻļ⧁āϰ⧁ āĻ•āϰāϤ⧇ āϝāĻĻāĻŋ āϚāĻžāύ āϤāĻžāĻšāϞ⧇ [`continue`]" -"(https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-" -"expressions) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤" -#: src/control-flow-basics/break-continue.md +#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md msgid "" -"If you want to exit any kind of loop early, use [`break`](https://doc.rust-" -"lang.org/reference/expressions/loop-expr.html#break-expressions). For " -"`loop`, this can take an optional expression that becomes the value of the " -"`loop` expression." +"At least one new `BUILD.gn` in `third_party/rust//v`" msgstr "" -"āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āϕ⧋āύ⧋ āϧāϰāύ⧇āϰ āϞ⧁āĻĒ āĻĨ⧇āϕ⧇ āϤāĻžāĻĄāĻŧāĻžāϤāĻžāĻĄāĻŧāĻŋ āĻĒā§āϰāĻ¸ā§āĻĨāĻžāύ āĻ•āϰāϤ⧇ āϚāĻžāύ āϤāĻŦ⧇ [`break`](https://" -"doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions) " -"āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤ `loop` āĻāϰ āϜāĻ¨ā§āϝ, āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āϐāĻšā§āĻ›āĻŋāĻ• āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ āύāĻŋāϤ⧇ āĻĒāĻžāϰ⧇ āϝāĻž `loop` " -"āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϰ āĻŽāĻžāύ āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧāĨ¤" -#: src/control-flow-basics/break-continue.md src/std-traits/exercise.md -#: src/std-traits/solution.md src/smart-pointers/trait-objects.md -#: src/modules/exercise.md src/modules/solution.md -#: src/android/build-rules/library.md -#: src/android/interoperability/cpp/rust-bridge.md -#: src/async/pitfalls/cancellation.md -msgid "\"{}\"" -msgstr "\"{}\"" +#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md +msgid "An appropriate `README.chromium`" +msgstr "" -#: src/control-flow-basics/break-continue/labels.md +#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md msgid "" -"Both `continue` and `break` can optionally take a label argument which is " -"used to break out of nested loops:" +"The \"major semver version\" is a [Rust \"semver\" version number](https://" +"doc.rust-lang.org/cargo/reference/semver.html)." msgstr "" -"'continue' āĻāĻŦāĻ‚ 'break' āωāĻ­āϝāĻŧāχ āϐāĻšā§āĻ›āĻŋāĻ•āĻ­āĻžāĻŦ⧇ āĻāĻ•āϟāĻŋ āϞ⧇āĻŦ⧇āϞ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āύāĻŋāϤ⧇ āĻĒāĻžāϰ⧇ āϝāĻž āύ⧇āĻ¸ā§āĻŸā§‡āĻĄ " -"āϞ⧁āĻĒāϗ⧁āϞāĻŋ āĻĨ⧇āϕ⧇ āĻŦ⧇āϰāĻŋāϝāĻŧ⧇ āφāϏāϤ⧇ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧ:" -#: src/control-flow-basics/break-continue/labels.md -msgid "\"elements searched: {elements_searched}\"" -msgstr "\"elements searched: {elements_searched}\"" - -#: src/control-flow-basics/break-continue/labels.md +#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md msgid "" -"Note that `loop` is the only looping construct which returns a non-trivial " -"value. This is because it's guaranteed to be entered at least once (unlike " -"`while` and `for` loops)." +"Take a close look, especially at the things generated in `third_party/rust`." msgstr "" -"`while` āĻāĻŦāĻ‚ `for` āĻāϰ āĻŦāĻŋāĻĒāϰ⧀āϤ `loop` āĻ…āĻ¨ā§āϤāϤ āĻāĻ•āĻŦāĻžāϰ āĻĒā§āϰāĻŦ⧇āĻļ āĻ•āϰāĻžāϰ āύāĻŋāĻļā§āϚāϝāĻŧāϤāĻž āĻĻ⧇āĻ“āϝāĻŧāĻžāϰ " -"āĻ•āĻžāϰāϪ⧇ āĻāĻ•āĻŽāĻžāĻ¤ā§āϰ āϞ⧁āĻĒāĻŋāĻ‚ āĻ—āĻ āύ āϝāĻž āĻāĻ•āϟāĻŋ āĻ…-āϤ⧁āĻšā§āĻ› āĻŽāĻžāύ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇āĨ¤" -#: src/control-flow-basics/blocks-and-scopes.md -msgid "Blocks" -msgstr "Blocks" +#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md +msgid "" +"Talk a little about semver --- and specifically the way that in Chromium " +"it's to allow multiple incompatible versions of a crate, which is " +"discouraged but sometimes necessary in the Cargo ecosystem." +msgstr "" -#: src/control-flow-basics/blocks-and-scopes.md +#: src/chromium/adding-third-party-crates/resolving-problems.md msgid "" -"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:" +"If your build fails, it may be because of a `build.rs`: programs which do " +"arbitrary things at build time. This is fundamentally at odds with the " +"design of `gn` and `ninja` which aim for static, deterministic, build rules " +"to maximize parallelism and repeatability of builds." msgstr "" -"āϰāĻžāĻ¸ā§āϟ āĻ āĻāĻ•āϟāĻŋ āĻŦā§āϞāϕ⧇ āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ⧇āϰ āĻāĻ•āϟāĻŋ āĻ•ā§āϰāĻŽ āϰāϝāĻŧ⧇āϛ⧇ āϝāĻž `{}` āĻŦāĻ¨ā§āϧāύ⧀ āĻĻā§āĻŦāĻžāϰāĻž āφāĻŦāĻĻā§āϧāĨ¤ āĻĒā§āϰāϤāĻŋāϟāĻŋ " -"āĻŦā§āϞāϕ⧇āϰ āĻāĻ•āϟāĻŋ āĻŽāĻžāύ āĻāĻŦāĻ‚ āĻāĻ•āϟāĻŋ āϟāĻžāχāĻĒ āϰāϝāĻŧ⧇āϛ⧇, āϝāĻž āϏ⧇āχ āĻŦā§āϞāϕ⧇āϰ āĻļ⧇āώ āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϗ⧁āϞāĻŋāϰ āĻĻā§āĻŦāĻžāϰāĻž " -"āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ:" - -#: src/control-flow-basics/blocks-and-scopes.md -msgid "\"y: {y}\"" -msgstr "\"y: {y}\"" -#: src/control-flow-basics/blocks-and-scopes.md +#: src/chromium/adding-third-party-crates/resolving-problems.md msgid "" -"If the last expression ends with `;`, then the resulting value and type is " -"`()`." +"Some `build.rs` actions are automatically supported; others require action:" msgstr "" -"āϝāĻĻāĻŋ āĻļ⧇āώ āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύāϟāĻŋ `;` āĻĻāĻŋāϝāĻŧ⧇ āĻļ⧇āώ āĻšāϝāĻŧ, āϤāĻžāĻšāϞ⧇ āĻĢāϞāĻ¸ā§āĻŦāϰ⧂āĻĒ āĻŽāĻžāύ āĻāĻŦāĻ‚ āϟāĻžāχāĻĒ āĻšāĻŦ⧇ `()`āĨ¤" -#: src/control-flow-basics/blocks-and-scopes.md -msgid "" -"You can show how the value of the block changes by changing the last line in " -"the block. For instance, adding/removing a semicolon or using a `return`." +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "build script effect" msgstr "" -"āφāĻĒāύāĻŋ āĻŦā§āϞāϕ⧇āϰ āĻļ⧇āώ āϞāĻžāχāύ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰ⧇ āĻŦā§āϞāϕ⧇āϰ āĻŽāĻžāύ āϕ⧀āĻ­āĻžāĻŦ⧇ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāĻŋāϤ āĻšāϝāĻŧ āϤāĻž āĻĻ⧇āĻ–āĻžāϤ⧇ " -"āĻĒāĻžāϰ⧇āύāĨ¤ āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āĻāĻ•āϟāĻŋ āϏ⧇āĻŽāĻŋāϕ⧋āϞāύ āϝ⧋āĻ— āĻ•āϰāĻž/āĻŽā§āϛ⧇ āĻĢ⧇āϞāĻž āĻŦāĻž āĻāĻ•āϟāĻŋ `āϰāĻŋāϟāĻžāĻ°ā§āύ` āĻŦā§āϝāĻŦāĻšāĻžāϰ " -"āĻ•āϰāĻžāĨ¤" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "A variable's scope is limited to the enclosing block." -msgstr "āĻāĻ•āϟāĻŋ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ⧇āϰ āĻ¸ā§āϕ⧋āĻĒ āϏ⧇āϟāĻŋāϰ āĻ˜ā§‡āϰāĻž āĻŦā§āϞāϕ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāĨ¤" +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "Supported by our gn templates" +msgstr "" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "" -"You can shadow variables, both those from outer scopes and variables from " -"the same scope:" +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "Work required by you" msgstr "" -"āφāĻĒāύāĻŋ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϗ⧁āϞāĻŋāϕ⧇ āĻ›āĻžāϝāĻŧāĻžāĻŦ⧃āϤ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ, āĻāϟāĻŋ āĻŦāĻžāχāϰ⧇āϰ āĻ¸ā§āϕ⧋āĻĒ āĻāĻŦāĻ‚ āĻāĻ•āχ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ⧇āϰ " -"āύāĻŋāĻœā§‡āĻ¸ā§āĻŦ āĻ¸ā§āϕ⧋āĻĒ āωāĻ­ā§Ÿā§‡ āĻĨ⧇āϕ⧇āχ āϏāĻŽā§āĻ­āĻŦ:" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "\"before: {a}\"" -msgstr "\"before: {a}\"" +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "Checking rustc version to configure features on and off" +msgstr "" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -#: src/std-traits/from-and-into.md src/slices-and-lifetimes/solution.md -msgid "\"hello\"" -msgstr "\"hello\"" +#: src/chromium/adding-third-party-crates/resolving-problems.md +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +#: src/unsafe-deep-dive/memory-lifecycle.md +msgid "Yes" +msgstr "" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "\"inner scope: {a}\"" -msgstr "\"inner scope: {a}\"" +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "None" +msgstr "" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "\"shadowed in inner scope: {a}\"" -msgstr "\"shadowed in inner scope: {a}\"" +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "Checking platform or CPU to configure features on and off" +msgstr "" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "\"after: {a}\"" -msgstr "\"after: {a}\"" +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "Generating code" +msgstr "" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "" -"Show that a variable's scope is limited by adding a `b` in the inner block " -"in the last example, and then trying to access it outside that block." +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "Yes - specify in `gnrt_config.toml`" msgstr "" -"āφāϗ⧇āϰ āωāĻĻāĻžāĻšāϰāϪ⧇ āϭ⧇āϤāϰ⧇āϰ āĻŦā§āϞāϕ⧇ āĻāĻ•āϟāĻŋ `b` āϞāĻžāĻ—āĻŋā§Ÿā§‡ āϏ⧇āϟāĻžāϕ⧇ āĻŦāĻžāχāϰ⧇ āĻĨ⧇āϕ⧇ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻ•āϰāĻŦāĻžāϰ " -"āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰ⧇ āĻāϟāĻž āĻĻ⧇āĻ–āĻžāύ āϝ⧇ āĻāĻ•āϟāĻŋ āĻ­ā§āϝāĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ⧇āϰ āĻ¸ā§āϕ⧋āĻĒ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧ āĻĨāĻžāϕ⧇āĨ¤" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "" -"Shadowing is different from mutation, because after shadowing both " -"variable's memory locations exist at the same time. Both are available under " -"the same name, depending where you use it in the code." +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "Building C/C++" msgstr "" -"āĻ›āĻžāϝāĻŧāĻžāĻŦ⧃āϤ āĻ•āϰāĻž āĻāĻŦāĻ‚ āĻĒāϰāĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϰ āĻŽāĻ§ā§āϝ⧇ āϤāĻĢāĻžā§Ž āφāϛ⧇, āĻ•āĻžāϰāĻŖ āĻ›āĻžā§ŸāĻžāĻŦ⧃āϤ āĻ•āϰāĻŦāĻžāϰ āĻĒāϰ⧇ āωāĻ­āϝāĻŧ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ⧇āϰ-" -"āχ āĻŽā§‡āĻŽāϰāĻŋ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ āĻāĻ•āχ āϏāĻŽāϝāĻŧ⧇ āĻŦāĻŋāĻĻā§āϝāĻŽāĻžāύ āĻĨāĻžāϕ⧇āĨ¤ āφāĻĒāύāĻŋ āϕ⧋āĻĄā§‡ āϕ⧋āĻĨāĻžāϝāĻŧ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇āύ āϤāĻžāϰ āωāĻĒāϰ " -"āύāĻŋāĻ°ā§āĻ­āϰ āĻ•āϰ⧇ āωāĻ­āϝāĻŧāχ āĻāĻ•āχ āύāĻžāĻŽā§‡ āωāĻĒāϞāĻŦā§āϧāĨ¤" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "A shadowing variable can have a different type." +#: src/chromium/adding-third-party-crates/resolving-problems.md +#: src/unsafe-deep-dive/memory-lifecycle.md +msgid "No" msgstr "" -"āĻāĻ•āϟāĻŋ āĻ­ā§āϝāĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ āϝ⧇āϟāĻŋ āĻ…āĻ¨ā§āϝ āĻ­ā§āϝāĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ⧇āϰ āĻ›āĻžā§ŸāĻž āĻšāĻŋāϏ⧇āĻŦ⧇ āĻŦāĻžāύāĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇ āϏ⧇āϟāĻŋāϰ āĻĨ⧇āϕ⧇ " -"āφāϞāĻžāĻĻāĻž āϟāĻžāχāĻĒ āϧāĻžāϰāĻŖ āĻ•āϰāϤ⧇āχ āĻĒāĻžāϰ⧇āĨ¤" -#: src/control-flow-basics/blocks-and-scopes/scopes.md -msgid "" -"Shadowing looks obscure at first, but is convenient for holding on to values " -"after `.unwrap()`." +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "Patch around it" msgstr "" -"āĻ›āĻžā§ŸāĻž āĻ•āϰāĻž āĻĒā§āϰāĻĨāĻŽā§‡ āĻ…āĻ¸ā§āĻĒāĻˇā§āϟ āĻĻ⧇āĻ–āĻžāϝāĻŧ, āĻ•āĻŋāĻ¨ā§āϤ⧁ `.unwrap()` āĻāϰ āĻĒāϰ⧇ āĻŽāĻžāύ āϧāϰ⧇ āϰāĻžāĻ–āĻžāϰ āϜāĻ¨ā§āϝ " -"āϏ⧁āĻŦāĻŋāϧāĻžāϜāύāĻ•āĨ¤" -#: src/control-flow-basics/functions.md -msgid "" -"Declaration parameters are followed by a type (the reverse of some " -"programming languages), then a return type." +#: src/chromium/adding-third-party-crates/resolving-problems.md +msgid "Arbitrary other actions" msgstr "" -"āĻ˜ā§‹āώāĻŋāϤ āĻĒāϰāĻžāĻŽāĻŋāϤāĻŋāϰ āĻĒāϰ⧇ āϤāĻžāϰ āϟāĻžāχāĻĒ āϞāĻžāĻ—āĻžāύ⧋ āĻšā§Ÿā§‡ (āĻāχ āϜāĻŋāύāĻŋāϏ āϤāĻž āĻ…āύ⧇āĻ• āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāĻŋāĻ‚ āĻ­āĻžāώāĻžāϰ " -"āϤ⧁āϞāύāĻžā§Ÿ āĻŦāĻŋāĻĒāϰ⧀āϤ) āĻāĻŦāĻ‚ āϤāĻžāϰ āĻĒāϰ⧇ āĻāĻ•āϟāĻŋ āϰāĻŋāϟāĻžāĻ°ā§āύ āϟāĻžāχāĻĒ āĻĻ⧇āĻ“ā§ŸāĻž āĻšā§Ÿā§‡āĨ¤" -#: src/control-flow-basics/functions.md +#: src/chromium/adding-third-party-crates/resolving-problems.md msgid "" -"The last expression in a function body (or any block) becomes the return " -"value. Simply omit the `;` at the end of the expression. The `return` " -"keyword can be used for early return, but the \"bare value\" form is " -"idiomatic at the end of a function (refactor `gcd` to use a `return`)." +"Fortunately, most crates don't contain a build script, and fortunately, most " +"build scripts only do the top two actions." msgstr "" -"āĻāĻ•āϟāĻŋ āĻĢāĻžāĻ‚āĻļāύ āĻŦāĻĄāĻŋ (āĻŦāĻž āϝ⧇āϕ⧋āύ⧋ āĻŦā§āϞāĻ•) āĻāϰ āĻļ⧇āώ āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋ āϏ⧇āϟāĻŋāϰ āĻĢ⧇āϰāϤāĻ—āĻžāĻŽā§€ āĻŽāĻžāύ āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧāĨ¤ " -"āĻļ⧁āϧ⧁ āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϰ āĻļ⧇āώ⧇ `;` āĻŦāĻžāĻĻ āĻĻāĻŋāύāĨ¤ `return` āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄāϟāĻŋ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āϰāĻŋāϟāĻžāĻ°ā§āύ⧇āϰ āϜāĻ¨ā§āϝ " -"āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇, āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻāĻ•āϟāĻŋ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻļ⧇āώ⧇ \"āĻŦ⧇āϝāĻŧāĻžāϰ āĻ­ā§āϝāĻžāϞ⧁\" āĻĢāĻ°ā§āĻŽāϟāĻŋ " -"āĻŦāĻžāĻ—ā§āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāϏāĻŽā§āĻŽāϤ (`gcd` āϟāĻžāϤ⧇ `return` āϞāĻžāĻ—āĻŋā§Ÿā§‡ āφāĻŦāĻžāϰ āϞāĻŋāϖ⧇ āĻĻ⧇āϖ⧁āύ)āĨ¤" -#: src/control-flow-basics/functions.md +#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md msgid "" -"Some functions have no return value, and return the 'unit type', `()`. The " -"compiler will infer this if the `-> ()` return type is omitted." +"If `ninja` complains about missing files, check the `build.rs` to see if it " +"writes source code files." msgstr "" -"āĻ…āύ⧇āĻ• āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āϰāĻŋāϟāĻžāĻ°ā§āύ āϟāĻžāχāĻĒ āĻĨāĻžāϕ⧇ āύāĻž āĻāĻŦāĻ‚ āϤāĻžāϰāĻž 'āĻāĻ•āĻ• āĻŦāĻž āχāωāύāĻŋāϟ āϟāĻžāχāĻĒ ' āĻŦāĻž `()` " -"āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ•āϰ⧇ āĻĨāĻžāϕ⧇āĨ¤ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āĻāϟāĻŋ āύāĻŋāĻœā§‡-āύāĻŋāĻœā§‡āχ āĻ…āύ⧁āĻŽāĻžāύ āĻ•āϰ⧇ āύāĻŋāϤ⧇ āĻĒāĻžāϰāĻŦ⧇ āϝāĻĻāĻŋ `-> ()` " -"āϰāĻŋāϟāĻžāĻ°ā§āύ āϟāĻžāχāĻĒ āĻŦāĻžāĻĻ āĻĻ⧇āĻ“āϝāĻŧāĻž āĻšāϝāĻŧāĨ¤" -#: src/control-flow-basics/functions.md +#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md msgid "" -"Overloading is not supported -- each function has a single implementation." -msgstr "āĻ“āĻ­āĻžāϰāϞ⧋āĻĄāĻŋāĻ‚ āϏāĻŽāĻ°ā§āĻĨāĻŋāϤ āύāϝāĻŧ -- āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻļ⧁āϧ⧁ āĻāĻ•āϟāĻŋ āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ āĻĨāĻžāĻ•āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" +"If so, modify [`gnrt_config.toml`](../configuring-gnrt-config-toml.md) to " +"add `build-script-outputs` to the crate. If this is a transitive dependency, " +"that is, one on which Chromium code should not directly depend, also add " +"`allow-first-party-usage=false`. There are several examples already in that " +"file:" +msgstr "" -#: src/control-flow-basics/functions.md +#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md msgid "" -"Always takes a fixed number of parameters. Default arguments are not " -"supported. Macros can be used to support variadic functions." +"```toml\n" +"[crate.unicode-linebreak]\n" +"allow-first-party-usage = false\n" +"build-script-outputs = [\"tables.rs\"]\n" +"```" msgstr "" -"āϏāĻ°ā§āĻŦāĻĻāĻž āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻ‚āĻ–ā§āϝāĻ• āĻĒāϰāĻžāĻŽāĻŋāϤāĻŋ āϞāĻžāϗ⧇āĨ¤ āϰ⧇āĻ¸ā§āϟ āĻ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āϏāĻŽāĻ°ā§āĻĨāĻŋāϤ āύāϝāĨ¤ " -"āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āĻĻāĻŋā§Ÿā§‡ āĻŦ⧈āϚāĻŋāĻ¤ā§āĻ°ā§āϝāĻŽāϝāĻŧ āĻŦāĻž āĻ­ā§āϝāĻžāϰāĻŋ⧟āĻžāĻĄāĻŋāĻ• āĻĢāĻžāĻ‚āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" -#: src/control-flow-basics/functions.md +#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md msgid "" -"Always takes a single set of parameter types. These types can be generic, " -"which will be covered later." +"Now rerun [`gnrt.py -- gen`](../generating-gn-build-rules.md) to regenerate " +"`BUILD.gn` files to inform ninja that this particular output file is input " +"to subsequent build steps." msgstr "" -"āϏāĻ°ā§āĻŦāĻĻāĻž āĻĒāϰāĻžāĻŽāĻŋāϤāĻŋāϰ āϟāĻžāχāĻĒ āĻāĻ•āϟāĻŋ āĻāĻ•āĻ• āϏ⧇āϟ-āχ āϞāĻžāϗ⧇āĨ¤ āĻāχ āϟāĻžāχāĻĒāϗ⧁āϞāĻŋ āĻœā§‡āύ⧇āϰāĻŋāĻ• āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ " -"āĻœā§‡āύ⧇āϰāĻŋāĻ• āĻĒāϰ⧇ āφāϞ⧋āϚāύāĻž āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤" -#: src/control-flow-basics/macros.md +#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md msgid "" -"Macros are expanded into Rust code during compilation, and can take a " -"variable number of arguments. They are distinguished by a `!` at the end. " -"The Rust standard library includes an assortment of useful macros." +"Some crates use the [`cc`](https://crates.io/crates/cc) crate to build and " +"link C/C++ libraries. Other crates parse C/C++ using [`bindgen`](https://" +"crates.io/crates/bindgen) within their build scripts. These actions can't be " +"supported in a Chromium context --- our gn, ninja and LLVM build system is " +"very specific in expressing relationships between build actions." msgstr "" -"āϏāĻ‚āĻ•āϞāύ⧇āϰ āϏāĻŽāϝāĻŧ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋āϗ⧁āϞāĻŋāϕ⧇ āϰāĻžāĻ¸ā§āϟ āϕ⧋āĻĄā§‡ āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āϰāĻž āĻšāϝāĻŧ āĻāĻŦāĻ‚ āĻāĻ•āϟāĻŋ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύāĻļā§€āϞ āϏāĻ‚āĻ–ā§āϝāĻ• " -"āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āύāĻŋāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋āϰ āĻļ⧇āώ⧇ āĻāĻ•āϟāĻŋ `!` āĻĻāĻŋā§Ÿā§‡ āϏ⧇āϟāĻŋ āĻ…āĻ¨ā§āϝ āϕ⧋āĻĄā§‡āϰ āĻĨ⧇āϕ⧇ āĻĒāĻžāĻ°ā§āĻĨāĻ•ā§āϝ āĻ•āϰāĻž " -"āĻšā§Ÿā§‡āĨ¤ āϰāĻžāĻ¸ā§āϟ āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋāϤ⧇ āĻĻāϰāĻ•āĻžāϰ⧀ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋āϗ⧁āϞāĻŋāϰ āĻāĻ•āϟāĻŋ āĻ­āĻžāĻŖā§āĻĄāĻžāϰ āĻ…āĻ¨ā§āϤāĻ°ā§āϭ⧁āĻ•ā§āϤ āϰāϝāĻŧ⧇āϛ⧇āĨ¤" -#: src/control-flow-basics/macros.md -msgid "" -"`println!(format, ..)` prints a line to standard output, applying formatting " -"described in [`std::fmt`](https://doc.rust-lang.org/std/fmt/index.html)." +#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md +msgid "So, your options are:" msgstr "" -"[`std::fmt`](https://doc.rust-lang.org/std/fmt/index.html) āĻ āĻŦāĻ°ā§āĻŖāĻŋāϤ āĻŦāĻŋāĻ¨ā§āϝāĻžāϏ " -"āĻĒā§āϰāϝāĻŧā§‹āĻ— āĻ•āϰ⧇ `println!(format, ..)` āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āφāωāϟāĻĒ⧁āĻŸā§‡ āĻāĻ•āϟāĻŋ āϞāĻžāχāύ āĻĒā§āϰāĻŋāĻ¨ā§āϟ āĻ•āϰ⧇āĨ¤" -#: src/control-flow-basics/macros.md -msgid "" -"`format!(format, ..)` works just like `println!` but returns the result as a " -"string." +#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md +msgid "Avoid these crates" msgstr "" -"`format!(format, ..)` āĻ āĻŋāĻ• `println!` āĻāϰ āĻŽāϤ⧋ āĻ•āĻžāϜ āĻ•āϰ⧇ āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻāĻ•āϟāĻŋ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻšāĻŋāϏ⧇āĻŦ⧇ " -"āĻĢāϞāĻžāĻĢāϞ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇āĨ¤" -#: src/control-flow-basics/macros.md -msgid "`dbg!(expression)` logs the value of the expression and returns it." -msgstr "`dbg!(expression)` āĻ…āĻ­āĻŋāĻŦā§āϝāĻ•ā§āϤāĻŋāϰ āĻŽāĻžāύ āϞāĻ— āĻ•āϰ⧇ āĻāĻŦāĻ‚ āϏ⧇āϟāĻŋāϕ⧇ āĻĢ⧇āϰāϤ āĻĻ⧇āϝāĻŧāĨ¤" +#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md +msgid "Apply a patch to the crate." +msgstr "" -#: src/control-flow-basics/macros.md +#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md msgid "" -"`todo!()` marks a bit of code as not-yet-implemented. If executed, it will " -"panic." +"Patches should be kept in `third_party/rust/chromium_crates_io/patches/" +"` - see for example the [patches against the `cxx` crate](https://" +"source.chromium.org/chromium/chromium/src/+/main:third_party/rust/" +"chromium_crates_io/patches/cxx/) - and will be applied automatically by " +"`gnrt` each time it upgrades the crate." msgstr "" -"`todo!()` āϕ⧋āĻĄā§‡āϰ āĻāĻ•āϟāĻŋ āĻŦā§āϞāĻ•āϕ⧇ āĻāĻ–āύ⧋-āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāĻŋāϤ āĻšāϝāĻŧāύāĻŋ āĻŦāϞ⧇ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧇āĨ¤ āĻāχ āϕ⧋āĻĄ āϚāĻžāϞāĻžāϞ⧇ " -"āϰāĻžāĻ¸ā§āϟ āφāϤāĻ™ā§āĻ•āĻŋāϤ āĻšāĻŦ⧇āĨ¤" -#: src/control-flow-basics/macros.md +#: src/chromium/adding-third-party-crates/depending-on-a-crate.md msgid "" -"`unreachable!()` marks a bit of code as unreachable. If executed, it will " -"panic." +"Once you've added a third-party crate and generated build rules, depending " +"on a crate is simple. Find your `rust_static_library` target, and add a " +"`dep` on the `:lib` target within your crate." msgstr "" -"`unreachable!()` āĻāĻ•āϟāĻŋ āϕ⧋āĻĄā§‡āϰ āĻ…āĻ‚āĻļ āϕ⧇ āĻĒ⧌āρāĻ›āĻžāύ⧋ āϝāĻžāϝāĻŧ āύāĻž āĻŦāϞ⧇ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧇āĨ¤ āĻāχ āϕ⧋āĻĄ " -"āϚāĻžāϞāĻžāϞ⧇ āϰāĻžāĻ¸ā§āϟ āφāϤāĻ™ā§āĻ•āĻŋāϤ āĻšāĻŦ⧇āĨ¤" - -#: src/control-flow-basics/macros.md -msgid "\"{n}! = {}\"" -msgstr "\"{n}! = {}\"" -#: src/control-flow-basics/macros.md -msgid "" -"The takeaway from this section is that these common conveniences exist, and " -"how to use them. Why they are defined as macros, and what they expand to, is " -"not especially critical." +#: src/chromium/adding-third-party-crates/depending-on-a-crate.md +msgid "Specifically," msgstr "" -"āĻāχ āĻŦāĻŋāĻ­āĻžāĻ— āĻĨ⧇āϕ⧇ āĻŦā§‹āĻāĻž āϝāĻžā§Ÿ āϝ⧇ āĻāχ āϏāĻžāϧāĻžāϰāĻŖ āϏ⧁āĻŦāĻŋāϧāĻžāϗ⧁āϞāĻŋ āĻŦāĻŋāĻĻā§āϝāĻŽāĻžāύ, āĻāĻŦāĻ‚ āϕ⧀āĻ­āĻžāĻŦ⧇ āϏ⧇āϗ⧁āϞāĻŋ " -"āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāϝāĻŧāĨ¤ āϕ⧇āύ āϏ⧇āϗ⧁āϞāĻŋ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āĻšāĻŋāϏāĻžāĻŦ⧇ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻ•āϰāĻž āφāϛ⧇, āĻāĻŦāĻ‚ āϏ⧇āϗ⧁āϞāĻŋ āĻ•āĻŋ " -"āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻšāϝāĻŧ, āĻŦāĻŋāĻļ⧇āώ āĻ•āϰ⧇ āϏāĻŽāĻžāϞ⧋āϚāύāĻžāĻŽā§‚āϞāĻ• āύāϝāĻŧāĨ¤" -#: src/control-flow-basics/macros.md +#: src/chromium/adding-third-party-crates/depending-on-a-crate.md msgid "" -"The course does not cover defining macros, but a later section will describe " -"use of derive macros." +"```bob\n" +" +------------+ +----------------------+\n" +"\"//third_party/rust\" | crate name | \"/v\" | major semver version | \":" +"lib\"\n" +" +------------+ +----------------------+\n" +"```" msgstr "" -"āϕ⧋āĻ°ā§āϏāϟāĻŋ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āϏ⧇āϟāĻž āφāϞ⧋āϚāύāĻž āĻ•āϰ⧇ āύāĻž, āϤāĻŦ⧇ āĻĒāϰāĻŦāĻ°ā§āϤ⧀ āĻāĻ•āϟāĻŋ āĻŦāĻŋāĻ­āĻžāϗ⧇ " -"āĻĄā§‡āϰāĻžāχāĻ­ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋āϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻŦāĻ°ā§āĻŖāύāĻž āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤" -#: src/control-flow-basics/exercise.md +#: src/chromium/adding-third-party-crates/depending-on-a-crate.md msgid "" -"The [Collatz Sequence](https://en.wikipedia.org/wiki/Collatz_conjecture) is " -"defined as follows, for an arbitrary n" +"```gn\n" +"rust_static_library(\"my_rust_lib\") {\n" +" crate_root = \"lib.rs\"\n" +" sources = [ \"lib.rs\" ]\n" +" deps = [ \"//third_party/rust/example_rust_crate/v1:lib\" ]\n" +"}\n" +"```" msgstr "" -"[Collatz āϏāĻŋāϕ⧋āϝāĻŧ⧇āĻ¨ā§āϏ](https://en.wikipedia.org/wiki/Collatz_conjecture) āύāĻŋāĻŽā§āύāϰ⧂āĻĒ " -"āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇, āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻŦāĻŋāϚāĻžāϰ⧇ n āĻāϰ āϜāĻ¨ā§āϝ" - -#: src/control-flow-basics/exercise.md -msgid "1" -msgstr "ā§§" - -#: src/control-flow-basics/exercise.md -msgid " greater than zero:" -msgstr "āĻļā§‚āĻ¨ā§āϝ⧇āϰ āĻšā§‡āϝāĻŧ⧇ āĻŦāĻĄāĻŧ:" - -#: src/control-flow-basics/exercise.md -msgid "If _n" -msgstr "If _n" - -#: src/control-flow-basics/exercise.md -msgid "i" -msgstr "i" - -#: src/control-flow-basics/exercise.md -msgid "_ is 1, then the sequence terminates at _n" -msgstr "1 āĻšāϞ⧇, āĻ•ā§āϰāĻŽāϟāĻŋ _n āĻļ⧇āώ āĻšā§Ÿā§‡" - -#: src/control-flow-basics/exercise.md -msgid "_." -msgstr "_." - -#: src/control-flow-basics/exercise.md -msgid "_ is even, then _n" -msgstr "_ āĻœā§‹āĻĄāĻŧ āĻšāϞ⧇ , āϤāĻžāĻšāϞ⧇ _n" - -#: src/control-flow-basics/exercise.md -msgid "i+1" -msgstr "i+1" - -#: src/control-flow-basics/exercise.md -msgid " = n" -msgstr " = n" - -#: src/control-flow-basics/exercise.md -msgid " / 2_." -msgstr " /2_." - -#: src/control-flow-basics/exercise.md -msgid "_ is odd, then _n" -msgstr "_ āĻŦāĻŋāĻœā§‹āĻĄāĻŧ āϝāĻĻāĻŋ āĻšā§Ÿā§‡, āϤāĻžāĻšāϞ⧇ _n" - -#: src/control-flow-basics/exercise.md -msgid " = 3 * n" -msgstr " = 3 * n" - -#: src/control-flow-basics/exercise.md -msgid " + 1_." -msgstr " + 1_." - -#: src/control-flow-basics/exercise.md -msgid "For example, beginning with _n" -msgstr "āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, _n āĻĻāĻŋāϝāĻŧ⧇ āĻļ⧁āϰ⧁ āĻšāϞ⧇" - -#: src/control-flow-basics/exercise.md -msgid "_ = 3:" -msgstr "_ = 3:" - -#: src/control-flow-basics/exercise.md -msgid "3 is odd, so _n" -msgstr "3 āĻŦāĻŋāĻœā§‹āĻĄāĻŧ, āϤāĻžāχ _n" - -#: src/control-flow-basics/exercise.md -msgid "2" -msgstr "2" - -#: src/control-flow-basics/exercise.md -msgid "_ = 3 * 3 + 1 = 10;" -msgstr "_ = 3 * 3 + 1 = 10;" - -#: src/control-flow-basics/exercise.md -msgid "10 is even, so _n" -msgstr "10 āĻœā§‹āĻĄāĻŧ, āϤāĻžāχ _n" - -#: src/control-flow-basics/exercise.md src/bare-metal/aps/better-uart.md -msgid "3" -msgstr "3" -#: src/control-flow-basics/exercise.md -msgid "_ = 10 / 2 = 5;" -msgstr "_ = 10 / 2 = 5;" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "Auditing Third Party Crates" +msgstr "" -#: src/control-flow-basics/exercise.md -msgid "5 is odd, so _n" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "" +"Adding new libraries is subject to Chromium's standard [policies](https://" +"chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/rust." +"md#Third_party-review), but of course also subject to security review. As " +"you may be bringing in not just a single crate but also transitive " +"dependencies, there may be a substantial amount of code to review. On the " +"other hand, safe Rust code can have limited negative side effects. How " +"should you review it?" msgstr "" -#: src/control-flow-basics/exercise.md src/bare-metal/aps/better-uart.md -msgid "4" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "" +"Over time Chromium aims to move to a process based around [cargo vet]" +"(https://mozilla.github.io/cargo-vet/)." msgstr "" -#: src/control-flow-basics/exercise.md -msgid "_ = 3 * 5 + 1 = 16;" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "" +"Meanwhile, for each new crate addition, we are checking for the following:" msgstr "" -#: src/control-flow-basics/exercise.md -msgid "16 is even, so _n" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "" +"Understand why each crate is used. What's the relationship between crates? " +"If the build system for each crate contains a `build.rs` or procedural " +"macros, work out what they're for. Are they compatible with the way Chromium " +"is normally built?" msgstr "" -#: src/control-flow-basics/exercise.md -msgid "5" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "Check each crate seems to be reasonably well maintained" msgstr "" -#: src/control-flow-basics/exercise.md -msgid "_ = 16 / 2 = 8;" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "" +"Use `cd third-party/rust/chromium_crates_io; cargo audit` to check for known " +"vulnerabilities (first you'll need to `cargo install cargo-audit`, which " +"ironically involves downloading lots of dependencies from the internet[2](../" +"cargo.md))" msgstr "" -#: src/control-flow-basics/exercise.md -msgid "8 is even, so _n" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "" +"Ensure any `unsafe` code is good enough for the [Rule of Two](https://" +"chromium.googlesource.com/chromium/src/+/main/docs/security/rule-of-2." +"md#unsafe-code-in-safe-languages)" msgstr "" -#: src/control-flow-basics/exercise.md src/bare-metal/aps/better-uart.md -msgid "6" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "Check for any use of `fs` or `net` APIs" msgstr "" -#: src/control-flow-basics/exercise.md -msgid "_ = 8 / 2 = 4;" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "" +"Read all the code at a sufficient level to look for anything out of place " +"that might have been maliciously inserted. (You can't realistically aim for " +"100% perfection here: there is often too much code.)" msgstr "" -#: src/control-flow-basics/exercise.md -msgid "4 is even, so _n" +#: src/chromium/adding-third-party-crates/reviews-and-audits.md +msgid "" +"These are just guidelines --- work with reviewers from `security@chromium." +"org` to work out the right way to become confident of the crate." msgstr "" -#: src/control-flow-basics/exercise.md -msgid "7" +#: src/chromium/adding-third-party-crates/checking-in.md +msgid "Checking Crates into Chromium Source Code" msgstr "" -#: src/control-flow-basics/exercise.md -msgid "_ = 4 / 2 = 2;" +#: src/chromium/adding-third-party-crates/checking-in.md +msgid "`git status` should reveal:" msgstr "" -#: src/control-flow-basics/exercise.md -msgid "2 is even, so _n" +#: src/chromium/adding-third-party-crates/checking-in.md +msgid "Crate code in `//third_party/rust/chromium_crates_io`" msgstr "" -#: src/control-flow-basics/exercise.md src/bare-metal/aps/better-uart.md -msgid "8" +#: src/chromium/adding-third-party-crates/checking-in.md +msgid "" +"Metadata (`BUILD.gn` and `README.chromium`) in `//third_party/rust//" +"`" msgstr "" -#: src/control-flow-basics/exercise.md -msgid "_ = 1; and" +#: src/chromium/adding-third-party-crates/checking-in.md +msgid "Please also add an `OWNERS` file in the latter location." msgstr "" -#: src/control-flow-basics/exercise.md -msgid "the sequence terminates." +#: src/chromium/adding-third-party-crates/checking-in.md +msgid "" +"You should land all this, along with your `Cargo.toml` and `gnrt_config." +"toml` changes, into the Chromium repo." msgstr "" -#: src/control-flow-basics/exercise.md +#: src/chromium/adding-third-party-crates/checking-in.md msgid "" -"Write a function to calculate the length of the collatz sequence for a given " -"initial `n`." +"**Important:** you need to use `git add -f` because otherwise `.gitignore` " +"files may result in some files being skipped." msgstr "" -#: src/control-flow-basics/exercise.md src/control-flow-basics/solution.md -msgid "/// Determine the length of the collatz sequence beginning at `n`.\n" -msgstr "/// Determine the length of the collatz sequence beginning at `n`.\n" - -#: src/control-flow-basics/solution.md src/concurrency/scoped-threads.md -msgid "\"Length: {}\"" -msgstr "\"Length: {}\"" - -#: src/welcome-day-1-afternoon.md src/welcome-day-2-afternoon.md -#: src/welcome-day-3-afternoon.md src/welcome-day-4-afternoon.md -msgid "Welcome Back" -msgstr "āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ" - -#: src/welcome-day-1-afternoon.md -msgid "[Tuples and Arrays](./tuples-and-arrays.md) (35 minutes)" -msgstr "[āϟāĻŋāωāĻĒ⧇āϞ āĻāĻŦāĻ‚ āĻ…ā§āϝāĻžāϰ⧇](./tuples-and-arrays.md) (ā§Šā§Ģ āĻŽāĻŋāύāĻŋāϟ)" - -#: src/welcome-day-1-afternoon.md -msgid "[References](./references.md) (35 minutes)" -msgstr "[āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ](./references.md)(ā§Šā§Ģ āĻŽāĻŋāύāĻŋāϟ)" - -#: src/welcome-day-1-afternoon.md -msgid "[User-Defined Types](./user-defined-types.md) (50 minutes)" -msgstr "[āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āĻĻā§āĻŦāĻžāϰāĻž āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āϟāĻžāχāĻĒ](./user-defined-types.md) (ā§Ģā§Ļ āĻŽāĻŋāύāĻŋāϟ)" - -#: src/welcome-day-1-afternoon.md +#: src/chromium/adding-third-party-crates/checking-in.md msgid "" -"Including 10 minute breaks, this session should take about 2 hours and 15 " -"minutes" -msgstr "ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ āĻŦāĻŋāϰāϤāĻŋāϏāĻš āĻāχ āĻ…āϧāĻŋāĻŦ⧇āĻļāύ āĻļ⧇āώ āĻ•āϰāϤ⧇ ⧍ āϘāĻ¨ā§āϟāĻž ā§§ā§Ģ āĻŽāĻŋāύāĻŋāϟ āϞāĻžāĻ—āĻŦ⧇" +"As you do so, you might find presubmit checks fail because of non-inclusive " +"language. This is because Rust crate data tends to include names of git " +"branches, and many projects still use non-inclusive terminology there. So " +"you may need to run:" +msgstr "" -#: src/tuples-and-arrays.md +#: src/chromium/adding-third-party-crates/keeping-up-to-date.md msgid "" -"[Tuples and Arrays](./tuples-and-arrays/tuples-and-arrays.md) (10 minutes)" +"As the OWNER of any third party Chromium dependency, you are [expected to " +"keep it up to date with any security fixes](https://chromium.googlesource." +"com/chromium/src/+/main/docs/adding_to_third_party.md#add-owners). It is " +"hoped that we will soon automate this for Rust crates, but for now, it's " +"still your responsibility just as it is for any other third party dependency." msgstr "" -"[āϟāĻŋāωāĻĒ⧇āϞ āĻāĻŦāĻ‚ āĻ…ā§āϝāĻžāϰ⧇](./tuples-and-arrays/tuples-and-arrays.md) (ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ)" -#: src/tuples-and-arrays.md -msgid "[Array Iteration](./tuples-and-arrays/iteration.md) (3 minutes)" +#: src/exercises/chromium/third-party.md +msgid "" +"Add [uwuify](https://crates.io/crates/uwuify) to Chromium, turning off the " +"crate's [default features](https://doc.rust-lang.org/cargo/reference/" +"features.html#the-default-feature). Assume that the crate will be used in " +"shipping Chromium, but won't be used to handle untrustworthy input." msgstr "" -#: src/tuples-and-arrays.md +#: src/exercises/chromium/third-party.md msgid "" -"[Patterns and Destructuring](./tuples-and-arrays/destructuring.md) (5 " -"minutes)" +"(In the next exercise we'll use uwuify from Chromium, but feel free to skip " +"ahead and do that now if you like. Or, you could create a new " +"[`rust_executable` target](https://source.chromium.org/chromium/chromium/src/" +"+/main:build/rust/rust_executable.gni) which uses `uwuify`)." msgstr "" -#: src/tuples-and-arrays.md -msgid "[Exercise: Nested Arrays](./tuples-and-arrays/exercise.md) (15 minutes)" +#: src/exercises/chromium/third-party.md +msgid "Students will need to download lots of transitive dependencies." msgstr "" -#: src/tuples-and-arrays.md src/references.md -msgid "This segment should take about 35 minutes" +#: src/exercises/chromium/third-party.md +msgid "The total crates needed are:" msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "" -"Tuples and arrays are the first \"compound\" types we have seen. All " -"elements of an array have the same type, while tuples can accommodate " -"different types. Both types have a size fixed at compile time." +#: src/exercises/chromium/third-party.md +msgid "`instant`," msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "Arrays" -msgstr "Arrays" - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "`[T; N]`" -msgstr "`[T; N]`" - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "`[20, 30, 40]`, `[0; 3]`" -msgstr "`[20, 30, 40]`, `[0; 3]`" - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "Tuples" -msgstr "Tuples" - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "`()`, `(T,)`, `(T1, T2)`, ..." -msgstr "`()`, `(T,)`, `(T1, T2)`, ..." - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "`()`, `('x',)`, `('x', 1.2)`, ..." -msgstr "`()`, `('x',)`, `('x', 1.2)`, ..." - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "Array assignment and access:" -msgstr "āĻ…ā§āϝāĻžāϰ⧇ āĻ…ā§āϝāĻžāϏāĻžāχāύāĻŽā§‡āĻ¨ā§āϟ āĻāĻŦāĻ‚ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ:" - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "Tuple assignment and access:" -msgstr "Tuple assignment and access:" - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "Arrays:" -msgstr "āĻ…ā§āϝāĻžāϰ⧇:" - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "" -"A value of the array type `[T; N]` holds `N` (a compile-time constant) " -"elements of the same type `T`. Note that the length of the array is _part of " -"its type_, which means that `[u8; 3]` and `[u8; 4]` are considered two " -"different types. Slices, which have a size determined at runtime, are " -"covered later." +#: src/exercises/chromium/third-party.md +msgid "`lock_api`," msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "" -"Try accessing an out-of-bounds array element. Array accesses are checked at " -"runtime. Rust can usually optimize these checks away, and they can be " -"avoided using unsafe Rust." +#: src/exercises/chromium/third-party.md +msgid "`parking_lot`," msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "We can use literals to assign values to arrays." +#: src/exercises/chromium/third-party.md +msgid "`parking_lot_core`," msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "" -"The `println!` macro asks for the debug implementation with the `?` format " -"parameter: `{}` gives the default output, `{:?}` gives the debug output. " -"Types such as integers and strings implement the default output, but arrays " -"only implement the debug output. This means that we must use debug output " -"here." +#: src/exercises/chromium/third-party.md +msgid "`redox_syscall`," msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "" -"Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be " -"easier to read." +#: src/exercises/chromium/third-party.md +msgid "`scopeguard`," msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "Tuples:" -msgstr "Tuples:" - -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "Like arrays, tuples have a fixed length." +#: src/exercises/chromium/third-party.md +msgid "`smallvec`, and" msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md -msgid "Tuples group together values of different types into a compound type." +#: src/exercises/chromium/third-party.md +msgid "`uwuify`." msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md +#: src/exercises/chromium/third-party.md msgid "" -"Fields of a tuple can be accessed by the period and the index of the value, " -"e.g. `t.0`, `t.1`." +"If students are downloading even more than that, they likely forgot to turn " +"off the default features." msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md +#: src/exercises/chromium/third-party.md msgid "" -"The empty tuple `()` is also known as the \"unit type\". It is both a type, " -"and the only valid value of that type --- that is to say both the type and " -"its value are expressed as `()`. It is used to indicate, for example, that a " -"function or expression has no return value, as we'll see in a future slide." +"Thanks to [Daniel Liu](https://github.com/Daniel-Liu-c0deb0t) for this crate!" +msgstr "" + +#: src/exercises/chromium/bringing-it-together.md +msgid "Bringing It Together --- Exercise" msgstr "" -#: src/tuples-and-arrays/tuples-and-arrays.md +#: src/exercises/chromium/bringing-it-together.md msgid "" -"You can think of it as `void` that can be familiar to you from other " -"programming languages." +"In this exercise, you're going to add a whole new Chromium feature, bringing " +"together everything you already learned." msgstr "" -#: src/tuples-and-arrays/iteration.md -msgid "The `for` statement supports iterating over arrays (but not tuples)." +#: src/exercises/chromium/bringing-it-together.md +msgid "The Brief from Product Management" msgstr "" -#: src/tuples-and-arrays/iteration.md +#: src/exercises/chromium/bringing-it-together.md msgid "" -"This functionality uses the `IntoIterator` trait, but we haven't covered " -"that yet." +"A community of pixies has been discovered living in a remote rainforest. " +"It's important that we get Chromium for Pixies delivered to them as soon as " +"possible." msgstr "" -#: src/tuples-and-arrays/iteration.md +#: src/exercises/chromium/bringing-it-together.md msgid "" -"The `assert_ne!` macro is new here. There are also `assert_eq!` and `assert!" -"` macros. These are always checked while, debug-only variants like " -"`debug_assert!` compile to nothing in release builds." +"The requirement is to translate all Chromium's UI strings into Pixie " +"language." msgstr "" -#: src/tuples-and-arrays/destructuring.md +#: src/exercises/chromium/bringing-it-together.md msgid "" -"When working with tuples and other structured values it's common to want to " -"extract the inner values into local variables. This can be done manually by " -"directly accessing the inner values:" +"There's not time to wait for proper translations, but fortunately pixie " +"language is very close to English, and it turns out there's a Rust crate " +"which does the translation." msgstr "" -#: src/tuples-and-arrays/destructuring.md -msgid "\"left: {left}, right: {right}\"" +#: src/exercises/chromium/bringing-it-together.md +msgid "" +"In fact, you already [imported that crate in the previous exercise](https://" +"crates.io/crates/uwuify)." msgstr "" -#: src/tuples-and-arrays/destructuring.md +#: src/exercises/chromium/bringing-it-together.md msgid "" -"However, Rust also supports using pattern matching to destructure a larger " -"value into its constituent parts:" +"(Obviously, real translations of Chrome require incredible care and " +"diligence. Don't ship this!)" msgstr "" -#: src/tuples-and-arrays/destructuring.md -msgid "This works with any kind of structured value:" +#: src/exercises/chromium/bringing-it-together.md +msgid "Steps" msgstr "" -#: src/tuples-and-arrays/destructuring.md -msgid "\"a: {a}, b: {b}\"" +#: src/exercises/chromium/bringing-it-together.md +msgid "" +"Modify `ResourceBundle::MaybeMangleLocalizedString` so that it uwuifies all " +"strings before display. In this special build of Chromium, it should always " +"do this irrespective of the setting of `mangle_localized_strings_`." msgstr "" -#: src/tuples-and-arrays/destructuring.md +#: src/exercises/chromium/bringing-it-together.md msgid "" -"The patterns used here are \"irrefutable\", meaning that the compiler can " -"statically verify that the value on the right of `=` has the same structure " -"as the pattern." +"If you've done everything right across all these exercises, congratulations, " +"you should have created Chrome for pixies!" msgstr "" -#: src/tuples-and-arrays/destructuring.md +#: src/exercises/chromium/bringing-it-together.md msgid "" -"A variable name is an irrefutable pattern that always matches any value, " -"hence why we can also use `let` to declare a single variable." +"UTF-16 vs UTF-8. Students should be aware that Rust strings are always " +"UTF-8, and will typically decide that it's better to do the conversion on " +"the C++ side using `base::UTF16ToUTF8` and back again." msgstr "" -#: src/tuples-and-arrays/destructuring.md +#: src/exercises/chromium/bringing-it-together.md msgid "" -"Rust also supports using patterns in conditionals, allowing for equality " -"comparison and destructuring to happen at the same time. This form of " -"pattern matching will be discussed in more detail later." +"If students decide to do the conversion on the Rust side, they'll need to " +"consider [`String::from_utf16`](https://doc.rust-lang.org/std/string/struct." +"String.html#method.from_utf16), consider error handling, and consider which " +"[CXX supported types can transfer many u16s](https://cxx.rs/binding/slice." +"html)." msgstr "" -#: src/tuples-and-arrays/destructuring.md +#: src/exercises/chromium/bringing-it-together.md msgid "" -"Edit the examples above to show the compiler error when the pattern doesn't " -"match the value being matched on." +"Students may design the C++/Rust boundary in several different ways, e.g. " +"taking and returning strings by value, or taking a mutable reference to a " +"string. If a mutable reference is used, CXX will likely tell the student " +"that they need to use [`Pin`](https://doc.rust-lang.org/std/pin/). You may " +"need to explain what `Pin` does, and then explain why CXX needs it for " +"mutable references to C++ data: the answer is that C++ data can't be moved " +"around like Rust data, because it may contain self-referential pointers." msgstr "" -#: src/tuples-and-arrays/exercise.md -msgid "Arrays can contain other arrays:" +#: src/exercises/chromium/bringing-it-together.md +msgid "" +"The C++ target containing `ResourceBundle::MaybeMangleLocalizedString` will " +"need to depend on a `rust_static_library` target. The student likely already " +"did this." msgstr "" -#: src/tuples-and-arrays/exercise.md -msgid "What is the type of this variable?" +#: src/exercises/chromium/bringing-it-together.md +msgid "" +"The `rust_static_library` target will need to depend on `//third_party/rust/" +"uwuify/v0_2:lib`." msgstr "" -#: src/tuples-and-arrays/exercise.md +#: src/exercises/chromium/solutions.md msgid "" -"Use an array such as the above to write a function `transpose` which will " -"transpose a matrix (turn rows into columns):" +"Solutions to the Chromium exercises can be found in [this series of CLs]" +"(https://chromium-review.googlesource.com/c/chromium/src/+/5096560)." msgstr "" -#: src/tuples-and-arrays/exercise.md -msgid "Hard-code both functions to operate on 3 × 3 matrices." +#: src/exercises/chromium/solutions.md +msgid "" +"Or, if you'd prefer \"standalone\" solutions that don't require applying " +"patchsets or integration with core Chromium code, you can find them in the " +"[`//chromium/src/codelabs/rust` subdirectory in Chromium](https://source." +"chromium.org/chromium/chromium/src/+/main:codelabs/rust/)." msgstr "" -#: src/tuples-and-arrays/exercise.md -msgid "" -"Copy the code below to and implement the " -"functions:" +#: src/bare-metal.md +msgid "Welcome to Bare Metal Rust" msgstr "" -#: src/tuples-and-arrays/exercise.md src/borrowing/exercise.md -#: src/unsafe-rust/exercise.md -msgid "// TODO: remove this when you're done with your implementation." +#: src/bare-metal.md +msgid "" +"This is a standalone one-day course about bare-metal Rust, aimed at people " +"who are familiar with the basics of Rust (perhaps from completing the " +"Comprehensive Rust course), and ideally also have some experience with bare-" +"metal programming in some other language such as C." msgstr "" -#: src/tuples-and-arrays/exercise.md src/tuples-and-arrays/solution.md -msgid "//\n" +#: src/bare-metal.md +msgid "" +"Today we will talk about 'bare-metal' Rust: running Rust code without an OS " +"underneath us. This will be divided into several parts:" msgstr "" -#: src/tuples-and-arrays/exercise.md src/tuples-and-arrays/solution.md -msgid "// <-- the comment makes rustfmt add a newline\n" +#: src/bare-metal.md +msgid "What is `no_std` Rust?" msgstr "" -#: src/tuples-and-arrays/exercise.md src/tuples-and-arrays/solution.md -msgid "\"matrix: {:#?}\"" +#: src/bare-metal.md +msgid "Writing firmware for microcontrollers." msgstr "" -#: src/tuples-and-arrays/exercise.md src/tuples-and-arrays/solution.md -msgid "\"transposed: {:#?}\"" +#: src/bare-metal.md +msgid "Writing bootloader / kernel code for application processors." msgstr "" -#: src/references.md -msgid "[Shared References](./references/shared.md) (10 minutes)" +#: src/bare-metal.md +msgid "Some useful crates for bare-metal Rust development." msgstr "" -#: src/references.md -msgid "[Exclusive References](./references/exclusive.md) (10 minutes)" +#: src/bare-metal.md +msgid "" +"For the microcontroller part of the course we will use the [BBC micro:bit]" +"(https://microbit.org/) v2 as an example. It's a [development board](https://" +"tech.microbit.org/hardware/) based on the Nordic nRF52833 microcontroller " +"with some LEDs and buttons, an I2C-connected accelerometer and compass, and " +"an on-board SWD debugger." msgstr "" -#: src/references.md -msgid "[Exercise: Geometry](./references/exercise.md) (15 minutes)" +#: src/bare-metal.md +msgid "" +"To get started, install some tools we'll need later. On gLinux or Debian:" msgstr "" -#: src/references/shared.md +#: src/bare-metal.md msgid "" -"A reference provides a way to access another value without taking " -"responsibility for the value, and is also called \"borrowing\". Shared " -"references are read-only, and the referenced data cannot change." +"And give users in the `plugdev` group access to the micro:bit programmer:" msgstr "" -#: src/references/shared.md +#: src/bare-metal.md msgid "" -"A shared reference to a type `T` has type `&T`. A reference value is made " -"with the `&` operator. The `*` operator \"dereferences\" a reference, " -"yielding its value." +"You should see \"NXP ARM mbed\" in the output of `lsusb` if the device is " +"available. If you are using a Linux environment on a Chromebook, you will " +"need to share the USB device with Linux, via `chrome://os-settings/crostini/" +"sharedUsbDevices`." msgstr "" -#: src/references/shared.md -msgid "Rust will statically forbid dangling references:" +#: src/bare-metal.md src/bare-metal/microcontrollers/debugging.md +msgid "On MacOS:" msgstr "" -#: src/references/shared.md -msgid "" -"A reference is said to \"borrow\" the value it refers to, and this is a good " -"model for students not familiar with pointers: code can use the reference to " -"access the value, but is still \"owned\" by the original variable. The " -"course will get into more detail on ownership in day 3." +#: src/bare-metal/no_std.md +msgid "`core`" msgstr "" -#: src/references/shared.md -msgid "" -"References are implemented as pointers, and a key advantage is that they can " -"be much smaller than the thing they point to. Students familiar with C or C+" -"+ will recognize references as pointers. Later parts of the course will " -"cover how Rust prevents the memory-safety bugs that come from using raw " -"pointers." +#: src/bare-metal/no_std.md +msgid "`std`" msgstr "" -#: src/references/shared.md -msgid "" -"Rust does not automatically create references for you - the `&` is always " -"required." +#: src/bare-metal/no_std.md +msgid "Slices, `&str`, `CStr`" msgstr "" -#: src/references/shared.md -msgid "" -"Rust will auto-dereference in some cases, in particular when invoking " -"methods (try `r.is_ascii()`). There is no need for an `->` operator like in " -"C++." +#: src/bare-metal/no_std.md +msgid "`NonZeroU8`..." msgstr "" -#: src/references/shared.md -msgid "" -"In this example, `r` is mutable so that it can be reassigned (`r = &b`). " -"Note that this re-binds `r`, so that it refers to something else. This is " -"different from C++, where assignment to a reference changes the referenced " -"value." +#: src/bare-metal/no_std.md +msgid "`Option`, `Result`" msgstr "" -#: src/references/shared.md -msgid "" -"A shared reference does not allow modifying the value it refers to, even if " -"that value was mutable. Try `*r = 'X'`." +#: src/bare-metal/no_std.md +msgid "`Display`, `Debug`, `write!`..." msgstr "" -#: src/references/shared.md -msgid "" -"Rust is tracking the lifetimes of all references to ensure they live long " -"enough. Dangling references cannot occur in safe Rust. `x_axis` would return " -"a reference to `point`, but `point` will be deallocated when the function " -"returns, so this will not compile." +#: src/bare-metal/no_std.md +msgid "`Iterator`" msgstr "" -#: src/references/shared.md -msgid "We will talk more about borrowing when we get to ownership." +#: src/bare-metal/no_std.md +msgid "`Error`" msgstr "" -#: src/references/exclusive.md -msgid "" -"Exclusive references, also known as mutable references, allow changing the " -"value they refer to. They have type `&mut T`." +#: src/bare-metal/no_std.md +msgid "`panic!`, `assert_eq!`..." msgstr "" -#: src/references/exclusive.md -msgid "" -"\"Exclusive\" means that only this reference can be used to access the " -"value. No other references (shared or exclusive) can exist at the same time, " -"and the referenced value cannot be accessed while the exclusive reference " -"exists. Try making an `&point.0` or changing `point.0` while `x_coord` is " -"alive." +#: src/bare-metal/no_std.md +msgid "`NonNull` and all the usual pointer-related functions" msgstr "" -#: src/references/exclusive.md -msgid "" -"Be sure to note the difference between `let mut x_coord: &i32` and `let " -"x_coord: &mut i32`. The first one represents a shared reference which can be " -"bound to different values, while the second represents an exclusive " -"reference to a mutable value." +#: src/bare-metal/no_std.md +msgid "`Future` and `async`/`await`" msgstr "" -#: src/references/exercise.md -msgid "" -"We will create a few utility functions for 3-dimensional geometry, " -"representing a point as `[f64;3]`. It is up to you to determine the function " -"signatures." +#: src/bare-metal/no_std.md +msgid "`fence`, `AtomicBool`, `AtomicPtr`, `AtomicU32`..." msgstr "" -#: src/references/exercise.md -msgid "" -"// Calculate the magnitude of a vector by summing the squares of its " -"coordinates" +#: src/bare-metal/no_std.md +msgid "`Duration`" msgstr "" -#: src/references/exercise.md -msgid "" -"// and taking the square root. Use the `sqrt()` method to calculate the " -"square" +#: src/bare-metal/no_std.md +msgid "`Box`, `Cow`, `Arc`, `Rc`" msgstr "" -#: src/references/exercise.md -msgid "// root, like `v.sqrt()`." +#: src/bare-metal/no_std.md +msgid "`Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque`" msgstr "" -#: src/references/exercise.md -msgid "" -"// Normalize a vector by calculating its magnitude and dividing all of its" +#: src/bare-metal/no_std.md +msgid "`String`, `CString`, `format!`" msgstr "" -#: src/references/exercise.md -msgid "// coordinates by that magnitude." +#: src/bare-metal/no_std.md +msgid "`Mutex`, `Condvar`, `Barrier`, `Once`, `RwLock`, `mpsc`" msgstr "" -#: src/references/exercise.md -msgid "// Use the following `main` to test your work." +#: src/bare-metal/no_std.md +msgid "`File` and the rest of `fs`" msgstr "" -#: src/references/exercise.md src/references/solution.md -msgid "\"Magnitude of a unit vector: {}\"" +#: src/bare-metal/no_std.md +msgid "`println!`, `Read`, `Write`, `Stdin`, `Stdout` and the rest of `io`" msgstr "" -#: src/references/exercise.md src/references/solution.md -msgid "\"Magnitude of {v:?}: {}\"" +#: src/bare-metal/no_std.md +msgid "`Path`, `OsString`" msgstr "" -#: src/references/exercise.md src/references/solution.md -msgid "\"Magnitude of {v:?} after normalization: {}\"" +#: src/bare-metal/no_std.md +msgid "`net`" msgstr "" -#: src/references/solution.md -msgid "/// Calculate the magnitude of the given vector.\n" +#: src/bare-metal/no_std.md +msgid "`Command`, `Child`, `ExitCode`" msgstr "" -#: src/references/solution.md -msgid "" -"/// Change the magnitude of the vector to 1.0 without changing its " -"direction.\n" +#: src/bare-metal/no_std.md +msgid "`spawn`, `sleep` and the rest of `thread`" msgstr "" -#: src/user-defined-types.md -msgid "[Named Structs](./user-defined-types/named-structs.md) (10 minutes)" +#: src/bare-metal/no_std.md +msgid "`SystemTime`, `Instant`" msgstr "" -#: src/user-defined-types.md -msgid "[Tuple Structs](./user-defined-types/tuple-structs.md) (10 minutes)" +#: src/bare-metal/no_std.md +msgid "`HashMap` depends on RNG." msgstr "" -#: src/user-defined-types.md -msgid "[Enums](./user-defined-types/enums.md) (5 minutes)" +#: src/bare-metal/no_std.md +msgid "`std` re-exports the contents of both `core` and `alloc`." msgstr "" -#: src/user-defined-types.md -msgid "" -"[Static and Const](./user-defined-types/static-and-const.md) (5 minutes)" +#: src/bare-metal/minimal.md +msgid "A minimal `no_std` program" msgstr "" -#: src/user-defined-types.md -msgid "[Type Aliases](./user-defined-types/aliases.md) (2 minutes)" +#: src/bare-metal/minimal.md +msgid "This will compile to an empty binary." msgstr "" -#: src/user-defined-types.md -msgid "" -"[Exercise: Elevator Events](./user-defined-types/exercise.md) (15 minutes)" +#: src/bare-metal/minimal.md +msgid "`std` provides a panic handler; without it we must provide our own." msgstr "" -#: src/user-defined-types.md src/borrowing.md -msgid "This segment should take about 50 minutes" +#: src/bare-metal/minimal.md +msgid "It can also be provided by another crate, such as `panic-halt`." msgstr "" -#: src/user-defined-types/named-structs.md -msgid "Like C and C++, Rust has support for custom structs:" +#: src/bare-metal/minimal.md +msgid "" +"Depending on the target, you may need to compile with `panic = \"abort\"` to " +"avoid an error about `eh_personality`." msgstr "" -#: src/user-defined-types/named-structs.md -msgid "\"{} is {} years old\"" +#: src/bare-metal/minimal.md +msgid "" +"Note that there is no `main` or any other entry point; it's up to you to " +"define your own entry point. This will typically involve a linker script and " +"some assembly code to set things up ready for Rust code to run." msgstr "" -#: src/user-defined-types/named-structs.md -#: src/android/interoperability/with-c/bindgen.md -msgid "\"Peter\"" +#: src/bare-metal/alloc.md +msgid "" +"To use `alloc` you must implement a [global (heap) allocator](https://doc." +"rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html)." msgstr "" -#: src/user-defined-types/named-structs.md -msgid "\"Avery\"" +#: src/bare-metal/alloc.md +msgid "// SAFETY: `HEAP` is only used here and `entry` is only called once.\n" msgstr "" -#: src/user-defined-types/named-structs.md -msgid "\"Jackie\"" +#: src/bare-metal/alloc.md +msgid "// Give the allocator some memory to allocate.\n" msgstr "" -#: src/user-defined-types/named-structs.md src/user-defined-types/enums.md -#: src/pattern-matching/match.md src/methods-and-traits/methods.md -msgid "Key Points:" +#: src/bare-metal/alloc.md +msgid "// Now we can do things that require heap allocation.\n" msgstr "" -#: src/user-defined-types/named-structs.md -msgid "Structs work like in C or C++." +#: src/bare-metal/alloc.md +msgid "\"A string\"" msgstr "" -#: src/user-defined-types/named-structs.md -msgid "Like in C++, and unlike in C, no typedef is needed to define a type." +#: src/bare-metal/alloc.md +msgid "" +"`buddy_system_allocator` is a crate implementing a basic buddy system " +"allocator. Other crates are available, or you can write your own or hook " +"into your existing allocator." msgstr "" -#: src/user-defined-types/named-structs.md -msgid "Unlike in C++, there is no inheritance between structs." +#: src/bare-metal/alloc.md +msgid "" +"The const parameter of `LockedHeap` is the max order of the allocator; i.e. " +"in this case it can allocate regions of up to 2\\*\\*32 bytes." msgstr "" -#: src/user-defined-types/named-structs.md +#: src/bare-metal/alloc.md msgid "" -"This may be a good time to let people know there are different types of " -"structs." +"If any crate in your dependency tree depends on `alloc` then you must have " +"exactly one global allocator defined in your binary. Usually this is done in " +"the top-level binary crate." msgstr "" -#: src/user-defined-types/named-structs.md +#: src/bare-metal/alloc.md msgid "" -"Zero-sized structs (e.g. `struct Foo;`) might be used when implementing a " -"trait on some type but don’t have any data that you want to store in the " -"value itself." +"`extern crate panic_halt as _` is necessary to ensure that the `panic_halt` " +"crate is linked in so we get its panic handler." msgstr "" -#: src/user-defined-types/named-structs.md +#: src/bare-metal/alloc.md +msgid "This example will build but not run, as it doesn't have an entry point." +msgstr "" + +#: src/bare-metal/microcontrollers.md msgid "" -"The next slide will introduce Tuple structs, used when the field names are " -"not important." +"The `cortex_m_rt` crate provides (among other things) a reset handler for " +"Cortex M microcontrollers." msgstr "" -#: src/user-defined-types/named-structs.md +#: src/bare-metal/microcontrollers.md msgid "" -"If you already have variables with the right names, then you can create the " -"struct using a shorthand." +"Next we'll look at how to access peripherals, with increasing levels of " +"abstraction." msgstr "" -#: src/user-defined-types/named-structs.md +#: src/bare-metal/microcontrollers.md msgid "" -"The syntax `..avery` allows us to copy the majority of the fields from the " -"old struct without having to explicitly type it all out. It must always be " -"the last element." +"The `cortex_m_rt::entry` macro requires that the function have type `fn() -" +"> !`, because returning to the reset handler doesn't make sense." msgstr "" -#: src/user-defined-types/tuple-structs.md -msgid "If the field names are unimportant, you can use a tuple struct:" +#: src/bare-metal/microcontrollers.md +msgid "Run the example with `cargo embed --bin minimal`" msgstr "" -#: src/user-defined-types/tuple-structs.md -msgid "\"({}, {})\"" +#: src/bare-metal/microcontrollers/mmio.md +msgid "" +"Most microcontrollers access peripherals via memory-mapped IO. Let's try " +"turning on an LED on our micro:bit:" msgstr "" -#: src/user-defined-types/tuple-structs.md -msgid "This is often used for single-field wrappers (called newtypes):" +#: src/bare-metal/microcontrollers/mmio.md +msgid "/// GPIO port 0 peripheral address\n" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md +msgid "// GPIO peripheral offsets\n" msgstr "" -#: src/user-defined-types/tuple-structs.md -msgid "\"Ask a rocket scientist at NASA\"" +#: src/bare-metal/microcontrollers/mmio.md +msgid "// PIN_CNF fields\n" msgstr "" -#: src/user-defined-types/tuple-structs.md -#: src/android/interoperability/cpp/cpp-bridge.md -#: src/async/pitfalls/cancellation.md -msgid "// ..." +#: src/bare-metal/microcontrollers/mmio.md +#: src/bare-metal/microcontrollers/pacs.md +#: src/bare-metal/microcontrollers/hals.md +msgid "// Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" msgstr "" -#: src/user-defined-types/tuple-structs.md +#: src/bare-metal/microcontrollers/mmio.md msgid "" -"Newtypes are a great way to encode additional information about the value in " -"a primitive type, for example:" +"// SAFETY: The pointers are to valid peripheral control registers, and no\n" +" // aliases exist.\n" msgstr "" -#: src/user-defined-types/tuple-structs.md -msgid "The number is measured in some units: `Newtons` in the example above." +#: src/bare-metal/microcontrollers/mmio.md +#: src/bare-metal/microcontrollers/pacs.md +#: src/bare-metal/microcontrollers/hals.md +msgid "// Set pin 28 low and pin 21 high to turn the LED on.\n" msgstr "" -#: src/user-defined-types/tuple-structs.md +#: src/bare-metal/microcontrollers/mmio.md msgid "" -"The value passed some validation when it was created, so you no longer have " -"to validate it again at every use: `PhoneNumber(String)` or `OddNumber(u32)`." +"GPIO 0 pin 21 is connected to the first column of the LED matrix, and pin 28 " +"to the first row." msgstr "" -#: src/user-defined-types/tuple-structs.md -msgid "" -"Demonstrate how to add a `f64` value to a `Newtons` type by accessing the " -"single field in the newtype." +#: src/bare-metal/microcontrollers/mmio.md +#: src/bare-metal/microcontrollers/pacs.md +#: src/bare-metal/microcontrollers/hals.md +#: src/bare-metal/microcontrollers/board-support.md +msgid "Run the example with:" msgstr "" -#: src/user-defined-types/tuple-structs.md +#: src/bare-metal/microcontrollers/pacs.md +msgid "Peripheral Access Crates" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md msgid "" -"Rust generally doesn’t like inexplicit things, like automatic unwrapping or " -"for instance using booleans as integers." +"[`svd2rust`](https://crates.io/crates/svd2rust) generates mostly-safe Rust " +"wrappers for memory-mapped peripherals from [CMSIS-SVD](https://www.keil.com/" +"pack/doc/CMSIS/SVD/html/index.html) files." msgstr "" -#: src/user-defined-types/tuple-structs.md -msgid "Operator overloading is discussed on Day 3 (generics)." +#: src/bare-metal/microcontrollers/pacs.md +msgid "" +"SVD (System View Description) files are XML files typically provided by " +"silicon vendors that describe the memory map of the device." msgstr "" -#: src/user-defined-types/tuple-structs.md +#: src/bare-metal/microcontrollers/pacs.md msgid "" -"The example is a subtle reference to the [Mars Climate Orbiter](https://en." -"wikipedia.org/wiki/Mars_Climate_Orbiter) failure." +"They are organized by peripheral, register, field and value, with names, " +"descriptions, addresses and so on." msgstr "" -#: src/user-defined-types/enums.md +#: src/bare-metal/microcontrollers/pacs.md msgid "" -"The `enum` keyword allows the creation of a type which has a few different " -"variants:" +"SVD files are frequently buggy and incomplete, so there are various projects " +"that patch the mistakes, add missing details, and publish the generated " +"crates." msgstr "" -#: src/user-defined-types/enums.md -msgid "// Simple variant" +#: src/bare-metal/microcontrollers/pacs.md +msgid "`cortex-m-rt` provides the vector table, among other things." msgstr "" -#: src/user-defined-types/enums.md -msgid "// Tuple variant" +#: src/bare-metal/microcontrollers/pacs.md +msgid "" +"If you `cargo install cargo-binutils` then you can run `cargo objdump --bin " +"pac -- -d --no-show-raw-insn` to see the resulting binary." msgstr "" -#: src/user-defined-types/enums.md -msgid "// Struct variant" +#: src/bare-metal/microcontrollers/hals.md +msgid "HAL crates" msgstr "" -#: src/user-defined-types/enums.md -msgid "\"On this turn: {:?}\"" +#: src/bare-metal/microcontrollers/hals.md +msgid "" +"[HAL crates](https://github.com/rust-embedded/awesome-embedded-rust#hal-" +"implementation-crates) for many microcontrollers provide wrappers around " +"various peripherals. These generally implement traits from [`embedded-hal`]" +"(https://crates.io/crates/embedded-hal)." msgstr "" -#: src/user-defined-types/enums.md -#, fuzzy -msgid "Enumerations allow you to collect a set of values under one type." -msgstr "Byte strings allow you to create a `&[u8]` value directly:" +#: src/bare-metal/microcontrollers/hals.md +msgid "// Create HAL wrapper for GPIO port 0.\n" +msgstr "" -#: src/user-defined-types/enums.md +#: src/bare-metal/microcontrollers/hals.md msgid "" -"`Direction` is a type with variants. There are two values of `Direction`: " -"`Direction::Left` and `Direction::Right`." +"`set_low` and `set_high` are methods on the `embedded_hal` `OutputPin` trait." msgstr "" -#: src/user-defined-types/enums.md +#: src/bare-metal/microcontrollers/hals.md msgid "" -"`PlayerMove` is a type with three variants. In addition to the payloads, " -"Rust will store a discriminant so that it knows at runtime which variant is " -"in a `PlayerMove` value." +"HAL crates exist for many Cortex-M and RISC-V devices, including various " +"STM32, GD32, nRF, NXP, MSP430, AVR and PIC microcontrollers." msgstr "" -#: src/user-defined-types/enums.md -msgid "This might be a good time to compare structs and enums:" +#: src/bare-metal/microcontrollers/board-support.md +msgid "Board support crates" msgstr "" -#: src/user-defined-types/enums.md +#: src/bare-metal/microcontrollers/board-support.md msgid "" -"In both, you can have a simple version without fields (unit struct) or one " -"with different types of fields (variant payloads)." +"Board support crates provide a further level of wrapping for a specific " +"board for convenience." msgstr "" -#: src/user-defined-types/enums.md +#: src/bare-metal/microcontrollers/board-support.md msgid "" -"You could even implement the different variants of an enum with separate " -"structs but then they wouldn’t be the same type as they would if they were " -"all defined in an enum." -msgstr "" - -#: src/user-defined-types/enums.md -msgid "Rust uses minimal space to store the discriminant." +"In this case the board support crate is just providing more useful names, " +"and a bit of initialization." msgstr "" -#: src/user-defined-types/enums.md -msgid "If necessary, it stores an integer of the smallest required size" +#: src/bare-metal/microcontrollers/board-support.md +msgid "" +"The crate may also include drivers for some on-board devices outside of the " +"microcontroller itself." msgstr "" -#: src/user-defined-types/enums.md -msgid "" -"If the allowed variant values do not cover all bit patterns, it will use " -"invalid bit patterns to encode the discriminant (the \"niche " -"optimization\"). For example, `Option<&u8>` stores either a pointer to an " -"integer or `NULL` for the `None` variant." +#: src/bare-metal/microcontrollers/board-support.md +msgid "`microbit-v2` includes a simple driver for the LED matrix." msgstr "" -#: src/user-defined-types/enums.md -msgid "" -"You can control the discriminant if needed (e.g., for compatibility with C):" +#: src/bare-metal/microcontrollers/type-state.md +msgid "The type state pattern" msgstr "" -#: src/user-defined-types/enums.md -msgid "" -"Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2 " -"bytes." +#: src/bare-metal/microcontrollers/type-state.md +msgid "// let gpio0_01_again = gpio0.p0_01; // Error, moved.\n" msgstr "" -#: src/user-defined-types/enums.md src/user-defined-types/static-and-const.md -#: src/memory-management/review.md src/memory-management/move.md -#: src/smart-pointers/box.md src/borrowing/shared.md -msgid "More to Explore" +#: src/bare-metal/microcontrollers/type-state.md +msgid "// pin_input.is_high(); // Error, moved.\n" msgstr "" -#: src/user-defined-types/enums.md +#: src/bare-metal/microcontrollers/type-state.md msgid "" -"Rust has several optimizations it can employ to make enums take up less " -"space." +"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." msgstr "" -#: src/user-defined-types/enums.md +#: src/bare-metal/microcontrollers/type-state.md msgid "" -"Null pointer optimization: For [some types](https://doc.rust-lang.org/std/" -"option/#representation), Rust guarantees that `size_of::()` equals " -"`size_of::>()`." +"Changing the configuration of a pin consumes the old pin instance, so you " +"can't use the old instance afterwards." msgstr "" -#: src/user-defined-types/enums.md +#: src/bare-metal/microcontrollers/type-state.md msgid "" -"Example code if you want to show how the bitwise representation _may_ look " -"like in practice. It's important to note that the compiler provides no " -"guarantees regarding this representation, therefore this is totally unsafe." +"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 " +"without properly configuring it first. Illegal state transitions are caught " +"at compile time." msgstr "" -#: src/user-defined-types/static-and-const.md +#: src/bare-metal/microcontrollers/type-state.md msgid "" -"Static and constant variables are two different ways to create globally-" -"scoped values that cannot be moved or reallocated during the execution of " -"the program." +"You can call `is_high` on an input pin and `set_high` on an output pin, but " +"not vice-versa." msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "`const`" +#: src/bare-metal/microcontrollers/type-state.md +msgid "Many HAL crates follow this pattern." msgstr "" -#: src/user-defined-types/static-and-const.md +#: src/bare-metal/microcontrollers/embedded-hal.md msgid "" -"Constant variables are evaluated at compile time and their values are " -"inlined wherever they are used:" +"The [`embedded-hal`](https://crates.io/crates/embedded-hal) crate provides a " +"number of traits covering common microcontroller peripherals:" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "" -"According to the [Rust RFC Book](https://rust-lang.github.io/rfcs/0246-const-" -"vs-static.html) these are inlined upon use." +#: src/bare-metal/microcontrollers/embedded-hal.md +msgid "GPIO" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "" -"Only functions marked `const` can be called at compile time to generate " -"`const` values. `const` functions can however be called at runtime." +#: src/bare-metal/microcontrollers/embedded-hal.md +msgid "PWM" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "`static`" +#: src/bare-metal/microcontrollers/embedded-hal.md +msgid "Delay timers" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "" -"Static variables will live during the whole execution of the program, and " -"therefore will not move:" +#: src/bare-metal/microcontrollers/embedded-hal.md +msgid "I2C and SPI buses and devices" msgstr "" -#: src/user-defined-types/static-and-const.md -#, fuzzy -msgid "\"Welcome to RustOS 3.14\"" -msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύ⧇ āφāĻĒāύāĻžāϕ⧇ āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ" +#: src/bare-metal/microcontrollers/embedded-hal.md +msgid "" +"Similar traits for byte streams (e.g. UARTs), CAN buses and RNGs are broken " +"out into [`embedded-io`](https://crates.io/crates/embedded-io), [`embedded-" +"can`](https://crates.io/crates/embedded-can) and [`rand_core`](https://" +"crates.io/crates/rand_core) respectively." +msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "\"{BANNER}\"" +#: src/bare-metal/microcontrollers/embedded-hal.md +msgid "" +"Other crates then implement [drivers](https://github.com/rust-embedded/" +"awesome-embedded-rust#driver-crates) in terms of these traits, e.g. an " +"accelerometer driver might need an I2C or SPI device instance." msgstr "" -#: src/user-defined-types/static-and-const.md +#: src/bare-metal/microcontrollers/embedded-hal.md msgid "" -"As noted in the [Rust RFC Book](https://rust-lang.github.io/rfcs/0246-const-" -"vs-static.html), these are not inlined upon use and have an actual " -"associated memory location. This is useful for unsafe and embedded code, and " -"the variable lives through the entirety of the program execution. When a " -"globally-scoped value does not have a reason to need object identity, " -"`const` is generally preferred." +"The traits cover using the peripherals but not initializing or configuring " +"them, as initialization and configuration is highly platform-specific." msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Mention that `const` behaves semantically similar to C++'s `constexpr`." +#: src/bare-metal/microcontrollers/embedded-hal.md +msgid "" +"There are implementations for many microcontrollers, as well as other " +"platforms such as Linux on Raspberry Pi." msgstr "" -#: src/user-defined-types/static-and-const.md +#: src/bare-metal/microcontrollers/embedded-hal.md msgid "" -"`static`, on the other hand, is much more similar to a `const` or mutable " -"global variable in C++." +"[`embedded-hal-async`](https://crates.io/crates/embedded-hal-async) provides " +"async versions of the traits." msgstr "" -#: src/user-defined-types/static-and-const.md +#: src/bare-metal/microcontrollers/embedded-hal.md msgid "" -"`static` provides object identity: an address in memory and state as " -"required by types with interior mutability such as `Mutex`." +"[`embedded-hal-nb`](https://crates.io/crates/embedded-hal-nb) provides " +"another approach to non-blocking I/O, based on the [`nb`](https://crates.io/" +"crates/nb) crate." msgstr "" -#: src/user-defined-types/static-and-const.md +#: src/bare-metal/microcontrollers/probe-rs.md msgid "" -"It isn't super common that one would need a runtime evaluated constant, but " -"it is helpful and safer than using a static." +"[probe-rs](https://probe.rs/) is a handy toolset for embedded debugging, " +"like OpenOCD but better integrated." msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Properties table:" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "" +"SWD (Serial Wire Debug) and JTAG via CMSIS-DAP, ST-Link and J-Link probes" msgstr "" -#: src/user-defined-types/static-and-const.md -#: src/chromium/adding-third-party-crates.md -msgid "Property" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "GDB stub and Microsoft DAP (Debug Adapter Protocol) server" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Static" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "Cargo integration" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Constant" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "" +"`cargo-embed` is a cargo subcommand to build and flash binaries, log RTT " +"(Real Time Transfers) output and connect GDB. It's configured by an `Embed." +"toml` file in your project directory." msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Has an address in memory" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "" +"[CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) is " +"an Arm standard protocol over USB for an in-circuit debugger to access the " +"CoreSight Debug Access Port of various Arm Cortex processors. It's what the " +"on-board debugger on the BBC micro:bit uses." msgstr "" -#: src/user-defined-types/static-and-const.md -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "Yes" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "" +"ST-Link is a range of in-circuit debuggers from ST Microelectronics, J-Link " +"is a range from SEGGER." msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "No (inlined)" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "" +"The Debug Access Port is usually either a 5-pin JTAG interface or 2-pin " +"Serial Wire Debug." msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Lives for the entire duration of the program" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "" +"probe-rs is a library that you can integrate into your own tools if you want " +"to." msgstr "" -#: src/user-defined-types/static-and-const.md -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "No" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "" +"The [Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-" +"adapter-protocol/) lets VSCode and other IDEs debug code running on any " +"supported microcontroller." msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Can be mutable" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "cargo-embed is a binary built using the probe-rs library." msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Yes (unsafe)" +#: src/bare-metal/microcontrollers/probe-rs.md +msgid "" +"RTT (Real Time Transfers) is a mechanism to transfer data between the debug " +"host and the target through a number of ring buffers." msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Evaluated at compile time" +#: src/bare-metal/microcontrollers/debugging.md +msgid "_Embed.toml_:" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Yes (initialised at compile time)" +#: src/bare-metal/microcontrollers/debugging.md +msgid "In one terminal under `src/bare-metal/microcontrollers/examples/`:" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Inlined wherever it is used" +#: src/bare-metal/microcontrollers/debugging.md +msgid "In another terminal in the same directory:" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "" -"Because `static` variables are accessible from any thread, they must be " -"`Sync`. Interior mutability is possible through a [`Mutex`](https://doc.rust-" -"lang.org/std/sync/struct.Mutex.html), atomic or similar." +#: src/bare-metal/microcontrollers/debugging.md +msgid "On gLinux or Debian:" msgstr "" -#: src/user-defined-types/static-and-const.md -msgid "Thread-local data can be created with the macro `std::thread_local`." +#: src/bare-metal/microcontrollers/debugging.md +msgid "In GDB, try running:" msgstr "" -#: src/user-defined-types/aliases.md -msgid "" -"A type alias creates a name for another type. The two types can be used " -"interchangeably." +#: src/bare-metal/microcontrollers/other-projects.md +#: src/bare-metal/aps/other-projects.md +msgid "Other projects" msgstr "" -#: src/user-defined-types/aliases.md -msgid "// Aliases are more useful with long, complex types:" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "[RTIC](https://rtic.rs/)" msgstr "" -#: src/user-defined-types/aliases.md -msgid "C programmers will recognize this as similar to a `typedef`." +#: src/bare-metal/microcontrollers/other-projects.md +msgid "\"Real-Time Interrupt-driven Concurrency\"." msgstr "" -#: src/user-defined-types/exercise.md +#: src/bare-metal/microcontrollers/other-projects.md msgid "" -"We will create a data structure to represent an event in an elevator control " -"system. It is up to you to define the types and functions to construct " -"various events. Use `#[derive(Debug)]` to allow the types to be formatted " -"with `{:?}`." +"Shared resource management, message passing, task scheduling, timer queue." msgstr "" -#: src/user-defined-types/exercise.md -msgid "" -"This exercise only requires creating and populating data structures so that " -"`main` runs without errors. The next part of the course will cover getting " -"data out of these structures." +#: src/bare-metal/microcontrollers/other-projects.md +msgid "[Embassy](https://embassy.dev/)" msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "" -"/// An event in the elevator system that the controller must react to.\n" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "`async` executors with priorities, timers, networking, USB." msgstr "" -#: src/user-defined-types/exercise.md -msgid "// TODO: add required variants" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "[TockOS](https://www.tockos.org/documentation/getting-started)" msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "/// A direction of travel.\n" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "" +"Security-focused RTOS with preemptive scheduling and Memory Protection Unit " +"support." msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "/// The car has arrived on the given floor.\n" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "[Hubris](https://hubris.oxide.computer/)" msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "/// The car doors have opened.\n" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "" +"Microkernel RTOS from Oxide Computer Company with memory protection, " +"unprivileged drivers, IPC." msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "/// The car doors have closed.\n" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "[Bindings for FreeRTOS](https://github.com/lobaro/FreeRTOS-rust)." msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md +#: src/bare-metal/microcontrollers/other-projects.md msgid "" -"/// A directional button was pressed in an elevator lobby on the given " -"floor.\n" -msgstr "" - -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "/// A floor button was pressed in the elevator car.\n" +"Some platforms have `std` implementations, e.g. [esp-idf](https://esp-rs." +"github.io/book/overview/using-the-standard-library.html)." msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "\"A ground floor passenger has pressed the up button: {:?}\"" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "RTIC can be considered either an RTOS or a concurrency framework." msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "\"The car has arrived on the ground floor: {:?}\"" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "It doesn't include any HALs." msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "\"The car door opened: {:?}\"" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "" +"It uses the Cortex-M NVIC (Nested Virtual Interrupt Controller) for " +"scheduling rather than a proper kernel." msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "\"A passenger has pressed the 3rd floor button: {:?}\"" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "Cortex-M only." msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "\"The car door closed: {:?}\"" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "" +"Google uses TockOS on the Haven microcontroller for Titan security keys." msgstr "" -#: src/user-defined-types/exercise.md src/user-defined-types/solution.md -msgid "\"The car has arrived on the 3rd floor: {:?}\"" +#: src/bare-metal/microcontrollers/other-projects.md +msgid "" +"FreeRTOS is mostly written in C, but there are Rust bindings for writing " +"applications." msgstr "" -#: src/user-defined-types/solution.md -msgid "/// A button was pressed.\n" +#: src/exercises/bare-metal/morning.md +msgid "" +"We will read the direction from an I2C compass, and log the readings to a " +"serial port." msgstr "" -#: src/user-defined-types/solution.md -msgid "/// The car has arrived at the given floor.\n" +#: src/exercises/bare-metal/morning.md +msgid "" +"After looking at the exercises, you can look at the [solutions](solutions-" +"morning.md) provided." msgstr "" -#: src/user-defined-types/solution.md -msgid "/// The car's doors have opened.\n" +#: src/exercises/bare-metal/compass.md +msgid "" +"We will read the direction from an I2C compass, and log the readings to a " +"serial port. If you have time, try displaying it on the LEDs somehow too, or " +"use the buttons somehow." msgstr "" -#: src/user-defined-types/solution.md -msgid "/// The car's doors have closed.\n" +#: src/exercises/bare-metal/compass.md +msgid "Hints:" msgstr "" -#: src/user-defined-types/solution.md -msgid "/// A floor is represented as an integer.\n" +#: src/exercises/bare-metal/compass.md +msgid "" +"Check the documentation for the [`lsm303agr`](https://docs.rs/lsm303agr/" +"latest/lsm303agr/) and [`microbit-v2`](https://docs.rs/microbit-v2/latest/" +"microbit/) crates, as well as the [micro:bit hardware](https://tech.microbit." +"org/hardware/)." msgstr "" -#: src/user-defined-types/solution.md -msgid "/// A user-accessible button.\n" +#: src/exercises/bare-metal/compass.md +msgid "" +"The LSM303AGR Inertial Measurement Unit is connected to the internal I2C bus." msgstr "" -#: src/user-defined-types/solution.md -msgid "/// A button in the elevator lobby on the given floor.\n" +#: src/exercises/bare-metal/compass.md +msgid "" +"TWI is another name for I2C, so the I2C master peripheral is called TWIM." msgstr "" -#: src/user-defined-types/solution.md -msgid "/// A floor button within the car.\n" +#: src/exercises/bare-metal/compass.md +msgid "" +"The LSM303AGR driver needs something implementing the `embedded_hal::i2c::" +"I2c` trait. The [`microbit::hal::Twim`](https://docs.rs/microbit-v2/latest/" +"microbit/hal/struct.Twim.html) struct implements this." msgstr "" -#: src/welcome-day-2.md -msgid "Welcome to Day 2" +#: src/exercises/bare-metal/compass.md +msgid "" +"You have a [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/" +"struct.Board.html) struct with fields for the various pins and peripherals." msgstr "" -#: src/welcome-day-2.md +#: src/exercises/bare-metal/compass.md msgid "" -"Now that we have seen a fair amount of Rust, today will focus on Rust's type " -"system:" +"You can also look at the [nRF52833 datasheet](https://infocenter.nordicsemi." +"com/pdf/nRF52833_PS_v1.5.pdf) if you want, but it shouldn't be necessary for " +"this exercise." msgstr "" -#: src/welcome-day-2.md -msgid "Pattern matching: extracting data from structures." +#: src/exercises/bare-metal/compass.md +msgid "" +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and " +"look in the `compass` directory for the following files." msgstr "" -#: src/welcome-day-2.md -msgid "Methods: associating functions with types." +#: src/exercises/bare-metal/compass.md src/exercises/bare-metal/rtc.md +msgid "_src/main.rs_:" msgstr "" -#: src/welcome-day-2.md -msgid "Traits: behaviors shared by multiple types." +#: src/exercises/bare-metal/compass.md src/exercises/bare-metal/rtc.md +msgid "_Cargo.toml_ (you shouldn't need to change this):" msgstr "" -#: src/welcome-day-2.md -msgid "Generics: parameterizing types on other types." +#: src/exercises/bare-metal/compass.md +msgid "_Embed.toml_ (you shouldn't need to change this):" msgstr "" -#: src/welcome-day-2.md -msgid "" -"Standard library types and traits: a tour of Rust's rich standard library." +#: src/exercises/bare-metal/compass.md src/exercises/bare-metal/rtc.md +msgid "_.cargo/config.toml_ (you shouldn't need to change this):" msgstr "" -#: src/welcome-day-2.md -msgid "[Welcome](./welcome-day-2.md) (3 minutes)" +#: src/exercises/bare-metal/compass.md +msgid "See the serial output on Linux with:" msgstr "" -#: src/welcome-day-2.md -msgid "[Pattern Matching](./pattern-matching.md) (1 hour)" +#: src/exercises/bare-metal/compass.md +msgid "" +"Or on Mac OS something like (the device name may be slightly different):" msgstr "" -#: src/welcome-day-2.md -msgid "[Methods and Traits](./methods-and-traits.md) (45 minutes)" +#: src/exercises/bare-metal/compass.md +msgid "Use Ctrl+A Ctrl+Q to quit picocom." msgstr "" -#: src/welcome-day-2.md -msgid "[Generics](./generics.md) (40 minutes)" +#: src/exercises/bare-metal/solutions-morning.md +msgid "Bare Metal Rust Morning Exercise" msgstr "" -#: src/welcome-day-2.md src/welcome-day-4.md -msgid "" -"Including 10 minute breaks, this session should take about 2 hours and 50 " -"minutes" +#: src/exercises/bare-metal/solutions-morning.md +msgid "([back to exercise](compass.md))" msgstr "" -#: src/pattern-matching.md -msgid "[Matching Values](./pattern-matching/match.md) (10 minutes)" +#: src/exercises/bare-metal/solutions-morning.md +msgid "// Configure serial port.\n" msgstr "" -#: src/pattern-matching.md -msgid "[Destructuring](./pattern-matching/destructuring.md) (10 minutes)" +#: src/exercises/bare-metal/solutions-morning.md +msgid "// Use the system timer as a delay provider.\n" msgstr "" -#: src/pattern-matching.md -msgid "[Let Control Flow](./pattern-matching/let-control-flow.md) (10 minutes)" +#: src/exercises/bare-metal/solutions-morning.md +msgid "// Set up the I2C controller and Inertial Measurement Unit.\n" msgstr "" -#: src/pattern-matching.md -msgid "" -"[Exercise: Expression Evaluation](./pattern-matching/exercise.md) (30 " -"minutes)" +#: src/exercises/bare-metal/solutions-morning.md +msgid "\"Setting up IMU...\"" msgstr "" -#: src/pattern-matching.md src/memory-management.md src/testing.md -msgid "This segment should take about 1 hour" +#: src/exercises/bare-metal/solutions-morning.md +msgid "// Set up display and timer.\n" msgstr "" -#: src/pattern-matching/match.md -msgid "" -"The `match` keyword lets you match a value against one or more _patterns_. " -"The comparisons are done from top to bottom and the first match wins." +#: src/exercises/bare-metal/solutions-morning.md +msgid "\"Ready.\"" msgstr "" -#: src/pattern-matching/match.md -msgid "The patterns can be simple values, similarly to `switch` in C and C++:" +#: src/exercises/bare-metal/solutions-morning.md +msgid "// Read compass data and log it to the serial port.\n" msgstr "" -#: src/pattern-matching/match.md -msgid "'x'" +#: src/exercises/bare-metal/solutions-morning.md +msgid "\"{},{},{}\\t{},{},{}\"" msgstr "" -#: src/pattern-matching/match.md -msgid "'q'" +#: src/exercises/bare-metal/solutions-morning.md +msgid "" +"// If button A is pressed, switch to the next mode and briefly blink all " +"LEDs\n" +" // on.\n" msgstr "" -#: src/pattern-matching/match.md -msgid "\"Quitting\"" +#: src/bare-metal/aps.md +msgid "Application processors" msgstr "" -#: src/pattern-matching/match.md src/std-traits/solution.md -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "'a'" +#: src/bare-metal/aps.md +msgid "" +"So far we've talked about microcontrollers, such as the Arm Cortex-M series. " +"These are typically small systems with very limited resources." msgstr "" -#: src/pattern-matching/match.md -msgid "'s'" +#: src/bare-metal/aps.md +msgid "" +"Larger systems with more resources are typically called application " +"processors, built around processors such as the ARM Cortex-A or Intel Atom." msgstr "" -#: src/pattern-matching/match.md -msgid "'w'" +#: src/bare-metal/aps.md +msgid "" +"For simplicity we'll just work with QEMU's aarch64 ['virt'](https://qemu-" +"project.gitlab.io/qemu/system/arm/virt.html) board." msgstr "" -#: src/pattern-matching/match.md -msgid "'d'" +#: src/bare-metal/aps.md +msgid "" +"Broadly speaking, microcontrollers don't have an MMU or multiple levels of " +"privilege (exception levels on Arm CPUs, rings on x86)." msgstr "" -#: src/pattern-matching/match.md -msgid "\"Moving around\"" +#: src/bare-metal/aps.md +msgid "" +"Application processors have more resources, and often run an operating " +"system, instead of directly executing the target application on startup." msgstr "" -#: src/pattern-matching/match.md src/error-handling/exercise.md -#: src/error-handling/solution.md -msgid "'0'" +#: src/bare-metal/aps.md +msgid "" +"QEMU supports emulating various different machines or board models for each " +"architecture. The 'virt' board doesn't correspond to any particular real " +"hardware, but is designed purely for virtual machines." msgstr "" -#: src/pattern-matching/match.md src/error-handling/exercise.md -#: src/error-handling/solution.md -msgid "'9'" +#: src/bare-metal/aps.md +msgid "" +"We will still address this board as bare-metal, as if we were writing an " +"operating system." msgstr "" -#: src/pattern-matching/match.md -msgid "\"Number input\"" +#: src/bare-metal/aps/entry-point.md +msgid "" +"Before we can start running Rust code, we need to do some initialization." msgstr "" -#: src/pattern-matching/match.md -msgid "\"Lowercase: {key}\"" +#: src/bare-metal/aps/entry-point.md +msgid "" +"```armasm\n" +"/**\n" +" * This is a generic entry point for an image. It carries out the\n" +" * operations required to prepare the loaded image to be run.\n" +" * Specifically, it\n" +" *\n" +" * - sets up the MMU with an identity map of virtual to physical\n" +" * addresses, and enables caching\n" +" * - enables floating point\n" +" * - zeroes the bss section using registers x25 and above\n" +" * - prepares the stack, pointing to a section within the image\n" +" * - sets up the exception vector\n" +" * - branches to the Rust `main` function\n" +" *\n" +" * It preserves x0-x3 for the Rust entry point, as these may contain\n" +" * boot parameters.\n" +" */\n" +".section .init.entry, \"ax\"\n" +".global entry\n" +"entry:\n" +" /*\n" +" * Load and apply the memory management configuration, ready to\n" +" * enable MMU and caches.\n" +" */\n" +" adrp x30, idmap\n" +" msr ttbr0_el1, x30\n" +"\n" +" mov_i x30, .Lmairval\n" +" msr mair_el1, x30\n" +"\n" +" mov_i x30, .Ltcrval\n" +" /* Copy the supported PA range into TCR_EL1.IPS. */\n" +" mrs x29, id_aa64mmfr0_el1\n" +" bfi x30, x29, #32, #4\n" +"\n" +" msr tcr_el1, x30\n" +"\n" +" mov_i x30, .Lsctlrval\n" +"\n" +" /*\n" +" * Ensure everything before this point has completed, then\n" +" * invalidate any potentially stale local TLB entries before they\n" +" * start being used.\n" +" */\n" +" isb\n" +" tlbi vmalle1\n" +" ic iallu\n" +" dsb nsh\n" +" isb\n" +"\n" +" /*\n" +" * Configure sctlr_el1 to enable MMU and cache and don't proceed\n" +" * until this has completed.\n" +" */\n" +" msr sctlr_el1, x30\n" +" isb\n" +"\n" +" /* Disable trapping floating point access in EL1. */\n" +" mrs x30, cpacr_el1\n" +" orr x30, x30, #(0x3 << 20)\n" +" msr cpacr_el1, x30\n" +" isb\n" +"\n" +" /* Zero out the bss section. */\n" +" adr_l x29, bss_begin\n" +" adr_l x30, bss_end\n" +"0: cmp x29, x30\n" +" b.hs 1f\n" +" stp xzr, xzr, [x29], #16\n" +" b 0b\n" +"\n" +"1: /* Prepare the stack. */\n" +" adr_l x30, boot_stack_end\n" +" mov sp, x30\n" +"\n" +" /* Set up exception vector. */\n" +" adr x30, vector_table_el1\n" +" msr vbar_el1, x30\n" +"\n" +" /* Call into Rust code. */\n" +" bl main\n" +"\n" +" /* Loop forever waiting for interrupts. */\n" +"2: wfi\n" +" b 2b\n" +"```" msgstr "" -#: src/pattern-matching/match.md -msgid "\"Something else\"" +#: src/bare-metal/aps/entry-point.md +msgid "" +"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 some low-" +"level setup is needed to meet Rust's expectations of the system." msgstr "" -#: src/pattern-matching/match.md +#: src/bare-metal/aps/entry-point.md msgid "" -"The `_` pattern is a wildcard pattern which matches any value. The " -"expressions _must_ be exhaustive, meaning that it covers every possibility, " -"so `_` is often used as the final catch-all case." +"This is the same as it would be for C: initializing the processor state, " +"zeroing the BSS, and setting up the stack pointer." msgstr "" -#: src/pattern-matching/match.md +#: src/bare-metal/aps/entry-point.md msgid "" -"Match can be used as an expression. Just like `if`, each match arm must have " -"the same type. The type is the last expression of the block, if any. In the " -"example above, the type is `()`." +"The BSS (block starting symbol, for historical reasons) is the part of the " +"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." msgstr "" -#: src/pattern-matching/match.md +#: src/bare-metal/aps/entry-point.md msgid "" -"A variable in the pattern (`key` in this example) will create a binding that " -"can be used within the match arm." +"The BSS may already be zeroed, depending on how memory is initialized and " +"the image is loaded, but we zero it to be sure." msgstr "" -#: src/pattern-matching/match.md -msgid "A match guard causes the arm to match only if the condition is true." +#: src/bare-metal/aps/entry-point.md +msgid "" +"We need to enable the MMU and cache before reading or writing any memory. If " +"we don't:" msgstr "" -#: src/pattern-matching/match.md +#: src/bare-metal/aps/entry-point.md msgid "" -"You might point out how some specific characters are being used when in a " -"pattern" +"Unaligned accesses will fault. We build the Rust code for the `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." msgstr "" -#: src/pattern-matching/match.md -msgid "`|` as an `or`" +#: src/bare-metal/aps/entry-point.md +msgid "" +"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 " +"doesn't explicitly access the memory, speculative accesses can lead to cache " +"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.)" msgstr "" -#: src/pattern-matching/match.md -msgid "`..` can expand as much as it needs to be" +#: src/bare-metal/aps/entry-point.md +msgid "" +"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." msgstr "" -#: src/pattern-matching/match.md -msgid "`1..=5` represents an inclusive range" +#: src/bare-metal/aps/entry-point.md +msgid "" +"We also set up the exception vector (`vbar_el1`), which we'll see more about " +"later." msgstr "" -#: src/pattern-matching/match.md -msgid "`_` is a wild card" +#: src/bare-metal/aps/entry-point.md +msgid "" +"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." msgstr "" -#: src/pattern-matching/match.md -msgid "" -"Match guards as a separate syntax feature are important and necessary when " -"we wish to concisely express more complex ideas than patterns alone would " -"allow." +#: src/bare-metal/aps/inline-assembly.md +msgid "Inline assembly" msgstr "" -#: src/pattern-matching/match.md +#: src/bare-metal/aps/inline-assembly.md msgid "" -"They are not the same as separate `if` expression inside of the match arm. " -"An `if` expression inside of the branch block (after `=>`) happens after the " -"match arm is selected. Failing the `if` condition inside of that block won't " -"result in other arms of the original `match` expression being considered." +"Sometimes we need to use assembly to do things that aren't possible with " +"Rust code. For example, to make an HVC (hypervisor call) to tell the " +"firmware to power off the system:" msgstr "" -#: src/pattern-matching/match.md +#: src/bare-metal/aps/inline-assembly.md msgid "" -"The condition defined in the guard applies to every expression in a pattern " -"with an `|`." +"// SAFETY: this only uses the declared registers and doesn't do anything\n" +" // with memory.\n" msgstr "" -#: src/pattern-matching/destructuring.md -msgid "Like tuples, structs and enums can also be destructured by matching:" +#: src/bare-metal/aps/inline-assembly.md +msgid "\"hvc #0\"" msgstr "" -#: src/pattern-matching/destructuring.md -msgid "Structs" -msgstr "Structs" +#: src/bare-metal/aps/inline-assembly.md +msgid "\"w0\"" +msgstr "" -#: src/pattern-matching/destructuring.md -msgid "\"x.0 = 1, b = {b}, y = {y}\"" +#: src/bare-metal/aps/inline-assembly.md +msgid "\"w1\"" msgstr "" -#: src/pattern-matching/destructuring.md -msgid "\"y = 2, x = {i:?}\"" +#: src/bare-metal/aps/inline-assembly.md +msgid "\"w2\"" msgstr "" -#: src/pattern-matching/destructuring.md -msgid "\"y = {y}, other fields were ignored\"" +#: src/bare-metal/aps/inline-assembly.md +msgid "\"w3\"" msgstr "" -#: src/pattern-matching/destructuring.md -msgid "" -"Patterns can also be used to bind variables to parts of your values. This is " -"how you inspect the structure of your types. Let us start with a simple " -"`enum` type:" +#: src/bare-metal/aps/inline-assembly.md +msgid "\"w4\"" msgstr "" -#: src/pattern-matching/destructuring.md -msgid "\"cannot divide {n} into two equal parts\"" +#: src/bare-metal/aps/inline-assembly.md +msgid "\"w5\"" msgstr "" -#: src/pattern-matching/destructuring.md -msgid "\"{n} divided in two is {half}\"" +#: src/bare-metal/aps/inline-assembly.md +msgid "\"w6\"" msgstr "" -#: src/pattern-matching/destructuring.md -msgid "\"sorry, an error happened: {msg}\"" +#: src/bare-metal/aps/inline-assembly.md +msgid "\"w7\"" msgstr "" -#: src/pattern-matching/destructuring.md +#: src/bare-metal/aps/inline-assembly.md msgid "" -"Here we have used the arms to _destructure_ the `Result` value. In the first " -"arm, `half` is bound to the value inside the `Ok` variant. In the second " -"arm, `msg` is bound to the error message." +"(If you actually want to do this, use the [`smccc`](https://crates.io/crates/" +"smccc) crate which has wrappers for all these functions.)" msgstr "" -#: src/pattern-matching/destructuring.md -msgid "Change the literal values in `foo` to match with the other patterns." +#: src/bare-metal/aps/inline-assembly.md +msgid "" +"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." msgstr "" -#: src/pattern-matching/destructuring.md -msgid "Add a new field to `Foo` and make changes to the pattern as needed." +#: src/bare-metal/aps/inline-assembly.md +msgid "" +"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." msgstr "" -#: src/pattern-matching/destructuring.md +#: src/bare-metal/aps/inline-assembly.md msgid "" -"The distinction between a capture and a constant expression can be hard to " -"spot. Try changing the `2` in the second arm to a variable, and see that it " -"subtly doesn't work. Change it to a `const` and see it working again." +"This `main` function needs to be `#[unsafe(no_mangle)]` and `extern \"C\"` " +"because it is called from our entry point in `entry.S`." msgstr "" -#: src/pattern-matching/destructuring.md +#: src/bare-metal/aps/inline-assembly.md msgid "" -"The `if`/`else` expression is returning an enum that is later unpacked with " -"a `match`." +"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 that might cause undefined behavior if used " +"incorrectly." msgstr "" -#: src/pattern-matching/destructuring.md +#: src/bare-metal/aps/inline-assembly.md msgid "" -"You can try adding a third variant to the enum definition and displaying the " -"errors when running the code. Point out the places where your code is now " -"inexhaustive and how the compiler tries to give you hints." +"`_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. " +"According to the standard aarch64 calling convention (which is what `extern " +"\"C\"` specifies to use), registers `x0`–`x7` are used for the first 8 " +"arguments passed to a function, so `entry.S` doesn't need to do anything " +"special except make sure it doesn't change these registers." msgstr "" -#: src/pattern-matching/destructuring.md +#: src/bare-metal/aps/inline-assembly.md msgid "" -"The values in the enum variants can only be accessed after being pattern " -"matched." +"Run the example in QEMU with `make qemu_psci` under `src/bare-metal/aps/" +"examples`." msgstr "" -#: src/pattern-matching/destructuring.md -msgid "" -"Demonstrate what happens when the search is inexhaustive. Note the advantage " -"the Rust compiler provides by confirming when all cases are handled." +#: src/bare-metal/aps/mmio.md +msgid "Volatile memory access for MMIO" msgstr "" -#: src/pattern-matching/destructuring.md +#: src/bare-metal/aps/mmio.md msgid "" -"Save the result of `divide_in_two` in the `result` variable and `match` it " -"in a loop. That won't compile because `msg` is consumed when matched. To fix " -"it, match `&result` instead of `result`. That will make `msg` a reference so " -"it won't be consumed. This [\"match ergonomics\"](https://rust-lang.github." -"io/rfcs/2005-match-ergonomics.html) appeared in Rust 2018. If you want to " -"support older Rust, replace `msg` with `ref msg` in the pattern." +"Use [`pointer::read_volatile`](https://doc.rust-lang.org/stable/core/" +"primitive.pointer.html#method.read_volatile) and [`pointer::write_volatile`]" +"(https://doc.rust-lang.org/stable/core/primitive.pointer.html#method." +"write_volatile)." msgstr "" -#: src/pattern-matching/let-control-flow.md +#: src/bare-metal/aps/mmio.md msgid "" -"Rust has a few control flow constructs which differ from other languages. " -"They are used for pattern matching:" +"Never hold a reference to a location being accessed with these methods. Rust " +"may read from (or write to, for `&mut`) a reference at any time." msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "`if let` expressions" +#: src/bare-metal/aps/mmio.md +msgid "" +"Use `&raw` to get fields of structs without creating an intermediate " +"reference." msgstr "" -#: src/pattern-matching/let-control-flow.md -#, fuzzy -msgid "`while let` expressions" -msgstr "while let āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ" - -#: src/pattern-matching/let-control-flow.md -msgid "`match` expressions" +#: src/bare-metal/aps/mmio.md +msgid "// SAFETY: Some device is mapped at this address.\n" msgstr "" -#: src/pattern-matching/let-control-flow.md +#: src/bare-metal/aps/mmio.md msgid "" -"The [`if let` expression](https://doc.rust-lang.org/reference/expressions/if-" -"expr.html#if-let-expressions) lets you execute different code depending on " -"whether a value matches a pattern:" +"Volatile access: read or write operations may have side-effects, so prevent " +"the compiler or hardware from reordering, duplicating or eliding them." msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "\"slept for {:?}\"" +#: src/bare-metal/aps/mmio.md +msgid "" +"If you write and then read, e.g. via a mutable reference, the compiler may " +"assume that the value read is the same as the value just written, and not " +"bother actually reading memory." msgstr "" -#: src/pattern-matching/let-control-flow.md -#, fuzzy -msgid "`let else` expressions" -msgstr "while let āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ" - -#: src/pattern-matching/let-control-flow.md +#: src/bare-metal/aps/mmio.md msgid "" -"For the common case of matching a pattern and returning from the function, " -"use [`let else`](https://doc.rust-lang.org/rust-by-example/flow_control/" -"let_else.html). The \"else\" case must diverge (`return`, `break`, or panic " -"- anything but falling off the end of the block)." +"Some existing crates for volatile access to hardware do hold references, but " +"this is unsound. Whenever a reference exists, the compiler may choose to " +"dereference it." msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "\"got None\"" +#: src/bare-metal/aps/mmio.md +msgid "Use `&raw` to get struct field pointers from a pointer to the struct." msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "\"got empty string\"" +#: src/bare-metal/aps/mmio.md +msgid "" +"For compatibility with old versions of Rust you can use the [`addr_of!`]" +"(https://doc.rust-lang.org/stable/core/ptr/macro.addr_of.html) macro instead." msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "\"not a hex digit\"" +#: src/bare-metal/aps/uart.md +msgid "Let's write a UART driver" msgstr "" -#: src/pattern-matching/let-control-flow.md src/pattern-matching/solution.md -msgid "\"result: {:?}\"" +#: src/bare-metal/aps/uart.md +msgid "" +"The QEMU 'virt' machine has a [PL011](https://developer.arm.com/" +"documentation/ddi0183/g) UART, so let's write a driver for that." msgstr "" -#: src/pattern-matching/let-control-flow.md src/generics/trait-bounds.md -#: src/smart-pointers/solution.md src/testing/googletest.md -#: src/testing/solution.md -msgid "\"foo\"" +#: src/bare-metal/aps/uart.md +msgid "/// Minimal driver for a PL011 UART.\n" msgstr "" -#: src/pattern-matching/let-control-flow.md +#: src/bare-metal/aps/uart.md msgid "" -"Like with `if let`, there is a [`while let`](https://doc.rust-lang.org/" -"reference/expressions/loop-expr.html#predicate-pattern-loops) variant which " -"repeatedly tests a value against a pattern:" +"/// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of " +"a\n" +" /// PL011 device, which must be mapped into the address space of the " +"process\n" +" /// as device memory and not have any other aliases.\n" msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "" -"Here [`String::pop`](https://doc.rust-lang.org/stable/std/string/struct." -"String.html#method.pop) returns `Some(c)` until the string is empty, after " -"which it will return `None`. The `while let` lets us keep iterating through " -"all items." +#: src/bare-metal/aps/uart.md src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md +msgid "/// Writes a single byte to the UART.\n" msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "if-let" +#: src/bare-metal/aps/uart.md src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md +msgid "// Wait until there is room in the TX buffer.\n" msgstr "" -#: src/pattern-matching/let-control-flow.md +#: src/bare-metal/aps/uart.md msgid "" -"Unlike `match`, `if let` does not have to cover all branches. This can make " -"it more concise than `match`." +"// SAFETY: We know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "A common usage is handling `Some` values when working with `Option`." +#: src/bare-metal/aps/uart.md src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md +msgid "// Write to the TX buffer.\n" msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "" -"Unlike `match`, `if let` does not support guard clauses for pattern matching." +#: src/bare-metal/aps/uart.md src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md +msgid "// Wait until the UART is no longer busy.\n" msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "let-else" +#: src/bare-metal/aps/uart.md +msgid "" +"Note that `Uart::new` is unsafe while the other methods are safe. This is " +"because as long as the caller of `Uart::new` guarantees that its safety " +"requirements are met (i.e. that there is only ever one instance of the " +"driver for a given UART, and nothing else aliasing its address space), then " +"it is always safe to call `write_byte` later because we can assume the " +"necessary preconditions." msgstr "" -#: src/pattern-matching/let-control-flow.md +#: src/bare-metal/aps/uart.md msgid "" -"`if-let`s can pile up, as shown. The `let-else` construct supports " -"flattening this nested code. Rewrite the awkward version for students, so " -"they can see the transformation." +"We could have done it the other way around (making `new` safe but " +"`write_byte` unsafe), but that would be much less convenient to use as every " +"place that calls `write_byte` would need to reason about the safety" msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "The rewritten version is:" +#: src/bare-metal/aps/uart.md +msgid "" +"This is a common pattern for writing safe wrappers of unsafe code: moving " +"the burden of proof for soundness from a large number of places to a smaller " +"number of places." msgstr "" -#: src/pattern-matching/let-control-flow.md -msgid "while-let" +#: src/bare-metal/aps/uart/traits.md +msgid "More traits" msgstr "" -#: src/pattern-matching/let-control-flow.md +#: src/bare-metal/aps/uart/traits.md msgid "" -"Point out that the `while let` loop will keep going as long as the value " -"matches the pattern." +"We derived the `Debug` trait. It would be useful to implement a few more " +"traits too." msgstr "" -#: src/pattern-matching/let-control-flow.md +#: src/bare-metal/aps/uart/traits.md msgid "" -"You could rewrite the `while let` loop as an infinite loop with an if " -"statement that breaks when there is no value to unwrap for `name.pop()`. The " -"`while let` provides syntactic sugar for the above scenario." +"// SAFETY: `Uart` just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" msgstr "" -#: src/pattern-matching/exercise.md -msgid "Let's write a simple recursive evaluator for arithmetic expressions." +#: src/bare-metal/aps/uart/traits.md +msgid "" +"Implementing `Write` lets us use the `write!` and `writeln!` macros with our " +"`Uart` type." msgstr "" -#: src/pattern-matching/exercise.md +#: src/bare-metal/aps/uart/traits.md msgid "" -"The `Box` type here is a smart pointer, and will be covered in detail later " -"in the course. An expression can be \"boxed\" with `Box::new` as seen in the " -"tests. To evaluate a boxed expression, use the deref operator (`*`) to " -"\"unbox\" it: `eval(*boxed_expr)`." +"`Send` is an auto-trait, but not implemented automatically because it is not " +"implemented for pointers." msgstr "" -#: src/pattern-matching/exercise.md -msgid "" -"Some expressions cannot be evaluated and will return an error. The standard " -"[`Result`](https://doc.rust-lang.org/std/result/enum.Result." -"html) type is an enum that represents either a successful value " -"(`Ok(Value)`) or an error (`Err(String)`). We will cover this type in detail " -"later." +#: src/bare-metal/aps/uart/using.md src/bare-metal/aps/logging/using.md +msgid "Using it" msgstr "" -#: src/pattern-matching/exercise.md +#: src/bare-metal/aps/uart/using.md msgid "" -"Copy and paste the code into the Rust playground, and begin implementing " -"`eval`. The final product should pass the tests. It may be helpful to use " -"`todo!()` and get the tests to pass one-by-one. You can also skip a test " -"temporarily with `#[ignore]`:" +"Let's write a small program using our driver to write to the serial console." msgstr "" -#: src/pattern-matching/exercise.md +#: src/bare-metal/aps/uart/using.md src/bare-metal/aps/safemmio/using.md +#: src/bare-metal/aps/logging/using.md src/bare-metal/aps/aarch64-rt.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Base address of the primary PL011 UART.\n" +msgstr "" + +#: src/bare-metal/aps/uart/using.md src/bare-metal/aps/safemmio/using.md +#: src/bare-metal/aps/logging/using.md src/bare-metal/aps/aarch64-rt.md +#: src/exercises/bare-metal/solutions-afternoon.md msgid "" -"If you finish early, try writing a test that results in division by zero or " -"integer overflow. How could you handle this with `Result` instead of a panic?" +"// SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and\n" +" // nothing else accesses that address range.\n" msgstr "" -#: src/pattern-matching/exercise.md src/pattern-matching/solution.md -msgid "/// An operation to perform on two subexpressions.\n" +#: src/bare-metal/aps/uart/using.md src/bare-metal/aps/safemmio/using.md +#: src/bare-metal/aps/logging/using.md src/bare-metal/aps/aarch64-rt.md +msgid "\"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\"" msgstr "" -#: src/pattern-matching/exercise.md src/pattern-matching/solution.md -msgid "/// An expression, in tree form.\n" +#: src/bare-metal/aps/uart/using.md +msgid "" +"As in the [inline assembly](../inline-assembly.md) example, this `main` " +"function is called from our entry point code in `entry.S`. See the speaker " +"notes there for details." msgstr "" -#: src/pattern-matching/exercise.md src/pattern-matching/solution.md -msgid "/// An operation on two subexpressions.\n" +#: src/bare-metal/aps/uart/using.md +msgid "" +"Run the example in QEMU with `make qemu_minimal` under `src/bare-metal/aps/" +"examples`." msgstr "" -#: src/pattern-matching/exercise.md src/pattern-matching/solution.md -msgid "/// A literal value\n" +#: src/bare-metal/aps/better-uart.md +msgid "A better UART driver" msgstr "" -#: src/pattern-matching/exercise.md src/pattern-matching/solution.md -msgid "\"division by zero\"" +#: src/bare-metal/aps/better-uart.md +msgid "" +"The PL011 actually has [more registers](https://developer.arm.com/" +"documentation/ddi0183/g/programmers-model/summary-of-registers), 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." msgstr "" -#: src/pattern-matching/solution.md -msgid "\"expr: {:?}\"" +#: src/bare-metal/aps/better-uart.md +msgid "Offset" msgstr "" -#: src/methods-and-traits.md -msgid "[Methods](./methods-and-traits/methods.md) (10 minutes)" +#: src/bare-metal/aps/better-uart.md +msgid "Register name" msgstr "" -#: src/methods-and-traits.md -msgid "[Traits](./methods-and-traits/traits.md) (10 minutes)" +#: src/bare-metal/aps/better-uart.md +msgid "Width" msgstr "" -#: src/methods-and-traits.md -msgid "[Deriving](./methods-and-traits/deriving.md) (3 minutes)" +#: src/bare-metal/aps/better-uart.md +msgid "0x00" msgstr "" -#: src/methods-and-traits.md -msgid "" -"[Exercise: Generic Logger](./methods-and-traits/exercise.md) (20 minutes)" +#: src/bare-metal/aps/better-uart.md +msgid "DR" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"Rust allows you to associate functions with your new types. You do this with " -"an `impl` block:" +#: src/bare-metal/aps/better-uart.md +msgid "12" msgstr "" -#: src/methods-and-traits/methods.md -msgid "// No receiver, a static method" +#: src/bare-metal/aps/better-uart.md +msgid "0x04" msgstr "" -#: src/methods-and-traits/methods.md -msgid "// Exclusive borrowed read-write access to self" +#: src/bare-metal/aps/better-uart.md +msgid "RSR" msgstr "" -#: src/methods-and-traits/methods.md -msgid "// Shared and read-only borrowed access to self" +#: src/bare-metal/aps/better-uart.md +msgid "4" msgstr "" -#: src/methods-and-traits/methods.md -msgid "\"Recorded {} laps for {}:\"" +#: src/bare-metal/aps/better-uart.md +msgid "0x18" msgstr "" -#: src/methods-and-traits/methods.md -msgid "\"Lap {idx}: {lap} sec\"" +#: src/bare-metal/aps/better-uart.md +msgid "FR" msgstr "" -#: src/methods-and-traits/methods.md -msgid "// Exclusive ownership of self" +#: src/bare-metal/aps/better-uart.md +msgid "9" msgstr "" -#: src/methods-and-traits/methods.md -msgid "\"Race {} is finished, total lap time: {}\"" +#: src/bare-metal/aps/better-uart.md +msgid "0x20" msgstr "" -#: src/methods-and-traits/methods.md -msgid "\"Monaco Grand Prix\"" +#: src/bare-metal/aps/better-uart.md +msgid "ILPR" msgstr "" -#: src/methods-and-traits/methods.md -msgid "// race.add_lap(42);" +#: src/bare-metal/aps/better-uart.md +msgid "8" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"The `self` arguments specify the \"receiver\" - the object the method acts " -"on. There are several common receivers for a method:" +#: src/bare-metal/aps/better-uart.md +msgid "0x24" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"`&self`: borrows the object from the caller using a shared and immutable " -"reference. The object can be used again afterwards." +#: src/bare-metal/aps/better-uart.md +msgid "IBRD" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"`&mut self`: borrows the object from the caller using a unique and mutable " -"reference. The object can be used again afterwards." +#: src/bare-metal/aps/better-uart.md +msgid "16" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"`self`: takes ownership of the object and moves it away from the caller. The " -"method becomes the owner of the object. The object will be dropped " -"(deallocated) when the method returns, unless its ownership is explicitly " -"transmitted. Complete ownership does not automatically mean mutability." +#: src/bare-metal/aps/better-uart.md +msgid "0x28" msgstr "" -#: src/methods-and-traits/methods.md -msgid "`mut self`: same as above, but the method can mutate the object." +#: src/bare-metal/aps/better-uart.md +msgid "FBRD" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"No receiver: this becomes a static method on the struct. Typically used to " -"create constructors which are called `new` by convention." +#: src/bare-metal/aps/better-uart.md +msgid "6" msgstr "" -#: src/methods-and-traits/methods.md -msgid "It can be helpful to introduce methods by comparing them to functions." +#: src/bare-metal/aps/better-uart.md +msgid "0x2c" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"Methods are called on an instance of a type (such as a struct or enum), the " -"first parameter represents the instance as `self`." +#: src/bare-metal/aps/better-uart.md +msgid "LCR_H" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"Developers may choose to use methods to take advantage of method receiver " -"syntax and to help keep them more organized. By using methods we can keep " -"all the implementation code in one predictable place." +#: src/bare-metal/aps/better-uart.md +msgid "0x30" msgstr "" -#: src/methods-and-traits/methods.md -msgid "Point out the use of the keyword `self`, a method receiver." +#: src/bare-metal/aps/better-uart.md +msgid "CR" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"Show that it is an abbreviated term for `self: Self` and perhaps show how " -"the struct name could also be used." +#: src/bare-metal/aps/better-uart.md +msgid "0x34" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"Explain that `Self` is a type alias for the type the `impl` block is in and " -"can be used elsewhere in the block." +#: src/bare-metal/aps/better-uart.md +msgid "IFLS" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"Note how `self` is used like other structs and dot notation can be used to " -"refer to individual fields." +#: src/bare-metal/aps/better-uart.md +msgid "0x38" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"This might be a good time to demonstrate how the `&self` differs from `self` " -"by trying to run `finish` twice." +#: src/bare-metal/aps/better-uart.md +msgid "IMSC" msgstr "" -#: src/methods-and-traits/methods.md -msgid "" -"Beyond variants on `self`, there are also [special wrapper types](https://" -"doc.rust-lang.org/reference/special-types-and-traits.html) allowed to be " -"receiver types, such as `Box`." +#: src/bare-metal/aps/better-uart.md +msgid "11" msgstr "" -#: src/methods-and-traits/traits.md -msgid "" -"Rust lets you abstract over types with traits. They're similar to interfaces:" +#: src/bare-metal/aps/better-uart.md +msgid "0x3c" msgstr "" -#: src/methods-and-traits/traits.md -msgid "/// Return a sentence from this pet." +#: src/bare-metal/aps/better-uart.md +msgid "RIS" msgstr "" -#: src/methods-and-traits/traits.md -msgid "/// Print a string to the terminal greeting this pet." +#: src/bare-metal/aps/better-uart.md +msgid "0x40" msgstr "" -#: src/methods-and-traits/traits.md -msgid "" -"A trait defines a number of methods that types must have in order to " -"implement the trait." +#: src/bare-metal/aps/better-uart.md +msgid "MIS" msgstr "" -#: src/methods-and-traits/traits.md -msgid "" -"In the \"Generics\" segment, next, we will see how to build functionality " -"that is generic over all types implementing a trait." +#: src/bare-metal/aps/better-uart.md +msgid "0x44" msgstr "" -#: src/methods-and-traits/traits/implementing.md -#, fuzzy -msgid "Implementing Traits" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ Traits āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ" +#: src/bare-metal/aps/better-uart.md +msgid "ICR" +msgstr "" -#: src/methods-and-traits/traits/implementing.md -msgid "\"Oh you're a cutie! What's your name? {}\"" +#: src/bare-metal/aps/better-uart.md +msgid "0x48" msgstr "" -#: src/methods-and-traits/traits/implementing.md -#: src/smart-pointers/trait-objects.md -msgid "\"Woof, my name is {}!\"" +#: src/bare-metal/aps/better-uart.md +msgid "DMACR" msgstr "" -#: src/methods-and-traits/traits/implementing.md -#: src/smart-pointers/trait-objects.md -msgid "\"Fido\"" +#: src/bare-metal/aps/better-uart.md +msgid "3" msgstr "" -#: src/methods-and-traits/traits/implementing.md -msgid "" -"To implement `Trait` for `Type`, you use an `impl Trait for Type { .. }` " -"block." +#: src/bare-metal/aps/better-uart.md +msgid "There are also some ID registers that have been omitted for brevity." msgstr "" -#: src/methods-and-traits/traits/implementing.md +#: src/bare-metal/aps/better-uart/bitflags.md msgid "" -"Unlike Go interfaces, just having matching methods is not enough: a `Cat` " -"type with a `talk()` method would not automatically satisfy `Pet` unless it " -"is in an `impl Pet` block." +"The [`bitflags`](https://crates.io/crates/bitflags) crate is useful for " +"working with bitflags." msgstr "" -#: src/methods-and-traits/traits/implementing.md -msgid "" -"Traits may provide default implementations of some methods. Default " -"implementations can rely on all the methods of the trait. In this case, " -"`greet` is provided, and relies on `talk`." +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// Flags from the UART flag register.\n" msgstr "" -#: src/methods-and-traits/traits/associated-types.md -msgid "" -"Associated types allow are placeholder types which are filled in by the " -"trait implementation." +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// Clear to send.\n" msgstr "" -#: src/methods-and-traits/traits/associated-types.md -msgid "" -"Associated types are sometimes also called \"output types\". The key " -"observation is that the implementer, not the caller, chooses this type." +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// Data set ready.\n" msgstr "" -#: src/methods-and-traits/traits/associated-types.md -msgid "" -"Many standard library traits have associated types, including arithmetic " -"operators and `Iterator`." +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// Data carrier detect.\n" msgstr "" -#: src/methods-and-traits/deriving.md -msgid "" -"Supported traits can be automatically implemented for your custom types, as " -"follows:" +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// UART busy transmitting data.\n" msgstr "" -#: src/methods-and-traits/deriving.md -msgid "// Default trait adds `default` constructor." +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// Receive FIFO is empty.\n" msgstr "" -#: src/methods-and-traits/deriving.md -msgid "// Clone trait adds `clone` method." +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// Transmit FIFO is full.\n" msgstr "" -#: src/methods-and-traits/deriving.md -msgid "\"EldurScrollz\"" +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// Receive FIFO is full.\n" msgstr "" -#: src/methods-and-traits/deriving.md -msgid "// Debug trait adds support for printing with `{:?}`." +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// Transmit FIFO is empty.\n" msgstr "" -#: src/methods-and-traits/deriving.md -msgid "\"{:?} vs. {:?}\"" +#: src/bare-metal/aps/better-uart/bitflags.md +msgid "/// Ring indicator.\n" msgstr "" -#: src/methods-and-traits/deriving.md +#: src/bare-metal/aps/better-uart/bitflags.md msgid "" -"Derivation is implemented with macros, and many crates provide useful derive " -"macros to add useful functionality. For example, `serde` can derive " -"serialization support for a struct using `#[derive(Serialize)]`." +"The `bitflags!` macro creates a newtype something like `struct Flags(u16)`, " +"along with a bunch of method implementations to get and set flags." msgstr "" -#: src/methods-and-traits/exercise.md -msgid "" -"Let's design a simple logging utility, using a trait `Logger` with a `log` " -"method. Code which might log its progress can then take an `&impl Logger`. " -"In testing, this might put messages in the test logfile, while in a " -"production build it would send messages to a log server." +#: src/bare-metal/aps/better-uart/registers.md +msgid "Multiple registers" msgstr "" -#: src/methods-and-traits/exercise.md +#: src/bare-metal/aps/better-uart/registers.md msgid "" -"However, the `StderrLogger` given below logs all messages, regardless of " -"verbosity. Your task is to write a `VerbosityFilter` type that will ignore " -"messages above a maximum verbosity." +"We can use a struct to represent the memory layout of the UART's registers." msgstr "" -#: src/methods-and-traits/exercise.md +#: src/bare-metal/aps/better-uart/registers.md msgid "" -"This is a common pattern: a struct wrapping a trait implementation and " -"implementing that same trait, adding behavior in the process. What other " -"kinds of wrappers might be useful in a logging utility?" +"[`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-" +"representation) tells the compiler to lay the struct fields out in order, " +"following the same rules as C. This is necessary for our struct to have a " +"predictable layout, as default Rust representation allows the compiler to " +"(among other things) reorder fields however it sees fit." msgstr "" -#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md -msgid "/// Log a message at the given verbosity level.\n" +#: src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md +msgid "Now let's use the new `Registers` struct in our driver." msgstr "" -#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md -msgid "\"verbosity={verbosity}: {message}\"" +#: src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md +msgid "/// Driver for a PL011 UART.\n" msgstr "" -#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md -msgid "\"FYI\"" +#: src/bare-metal/aps/better-uart/driver.md +msgid "" +"/// Constructs a new instance of the UART driver for a PL011 device with " +"the\n" +" /// given set of registers.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given pointer must point to the 8 MMIO control registers of a " +"PL011\n" +" /// device, which must be mapped into the address space of the process " +"as\n" +" /// device memory and not have any other aliases.\n" msgstr "" -#: src/methods-and-traits/exercise.md src/methods-and-traits/solution.md -msgid "\"Uhoh\"" +#: src/bare-metal/aps/better-uart/driver.md +msgid "" +"// SAFETY: We know that self.registers points to the control registers\n" +" // of a PL011 device which is appropriately mapped.\n" msgstr "" -#: src/methods-and-traits/exercise.md -msgid "// TODO: Define and implement `VerbosityFilter`." +#: src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md +msgid "" +"/// Reads and returns a pending byte, or `None` if nothing has been\n" +" /// received.\n" msgstr "" -#: src/methods-and-traits/solution.md -msgid "/// Only log messages up to the given verbosity level.\n" +#: src/bare-metal/aps/better-uart/driver.md +msgid "" +"// SAFETY: We know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" msgstr "" -#: src/generics.md -msgid "[Generic Functions](./generics/generic-functions.md) (5 minutes)" +#: src/bare-metal/aps/better-uart/driver.md +#: src/bare-metal/aps/safemmio/driver.md +msgid "// TODO: Check for error conditions in bits 8-11.\n" msgstr "" -#: src/generics.md -msgid "[Generic Data Types](./generics/generic-data.md) (10 minutes)" +#: src/bare-metal/aps/better-uart/driver.md +msgid "" +"Note the use of `&raw const` / `&raw mut` to get pointers to individual " +"fields without creating an intermediate reference, which would be unsound." msgstr "" -#: src/generics.md -msgid "[Trait Bounds](./generics/trait-bounds.md) (10 minutes)" +#: src/bare-metal/aps/better-uart/driver.md +msgid "" +"The example isn't included in the slides because it is very similar to the " +"`safe-mmio` example which comes next. You can run it in QEMU with `make " +"qemu` under `src/bare-metal/aps/examples` if you need to." msgstr "" -#: src/generics.md -msgid "[impl Trait](./generics/impl-trait.md) (5 minutes)" +#: src/bare-metal/aps/safemmio/registers.md +msgid "" +"The [`safe-mmio`](https://crates.io/crates/safe-mmio) crate provides types " +"to wrap registers that can be read or written safely." msgstr "" -#: src/generics.md -msgid "[Exercise: Generic min](./generics/exercise.md) (10 minutes)" +#: src/bare-metal/aps/safemmio/registers.md +msgid "Can't read" msgstr "" -#: src/generics/generic-functions.md -msgid "" -"Rust supports generics, which lets you abstract algorithms or data " -"structures (such as sorting or a binary tree) over the types used or stored." +#: src/bare-metal/aps/safemmio/registers.md +msgid "Read has no side-effects" msgstr "" -#: src/generics/generic-functions.md -msgid "/// Pick `even` or `odd` depending on the value of `n`." +#: src/bare-metal/aps/safemmio/registers.md +msgid "Read has side-effects" msgstr "" -#: src/generics/generic-functions.md -msgid "\"picked a number: {:?}\"" +#: src/bare-metal/aps/safemmio/registers.md +msgid "Can't write" msgstr "" -#: src/generics/generic-functions.md -msgid "\"picked a tuple: {:?}\"" +#: src/bare-metal/aps/safemmio/registers.md +msgid "" +"[`ReadPure`](https://docs.rs/safe-mmio/latest/safe_mmio/fields/struct." +"ReadPure.html)" msgstr "" -#: src/generics/generic-functions.md -msgid "\"dog\"" +#: src/bare-metal/aps/safemmio/registers.md +msgid "" +"[`ReadOnly`](https://docs.rs/safe-mmio/latest/safe_mmio/fields/struct." +"ReadOnly.html)" msgstr "" -#: src/generics/generic-functions.md -msgid "\"cat\"" +#: src/bare-metal/aps/safemmio/registers.md +msgid "Can write" msgstr "" -#: src/generics/generic-functions.md +#: src/bare-metal/aps/safemmio/registers.md msgid "" -"Rust infers a type for T based on the types of the arguments and return " -"value." +"[`WriteOnly`](https://docs.rs/safe-mmio/latest/safe_mmio/fields/struct." +"WriteOnly.html)" msgstr "" -#: src/generics/generic-functions.md +#: src/bare-metal/aps/safemmio/registers.md msgid "" -"This is similar to C++ templates, but Rust partially compiles the generic " -"function immediately, so that function must be valid for all types matching " -"the constraints. For example, try modifying `pick` to return `even + odd` if " -"`n == 0`. Even if only the `pick` instantiation with integers is used, Rust " -"still considers it invalid. C++ would let you do this." +"[`ReadPureWrite`](https://docs.rs/safe-mmio/latest/safe_mmio/fields/struct." +"ReadPureWrite.html)" msgstr "" -#: src/generics/generic-functions.md +#: src/bare-metal/aps/safemmio/registers.md msgid "" -"Generic code is turned into non-generic code based on the call sites. This " -"is a zero-cost abstraction: you get exactly the same result as if you had " -"hand-coded the data structures without the abstraction." +"[`ReadWrite`](https://docs.rs/safe-mmio/latest/safe_mmio/fields/struct." +"ReadWrite.html)" msgstr "" -#: src/generics/generic-data.md -msgid "You can use generics to abstract over the concrete field type:" +#: src/bare-metal/aps/safemmio/registers.md +msgid "Reading `dr` has a side effect: it pops a byte from the receive FIFO." msgstr "" -#: src/generics/generic-data.md -msgid "// fn set_x(&mut self, x: T)" +#: src/bare-metal/aps/safemmio/registers.md +msgid "" +"Reading `rsr` (and other registers) has no side-effects. It is a 'pure' read." msgstr "" -#: src/generics/generic-data.md -msgid "\"{integer:?} and {float:?}\"" +#: src/bare-metal/aps/safemmio/registers.md +msgid "" +"There are a number of different crates providing safe abstractions around " +"MMIO operations; we recommend the `safe-mmio` crate." msgstr "" -#: src/generics/generic-data.md -msgid "\"coords: {:?}\"" +#: src/bare-metal/aps/safemmio/registers.md +msgid "" +"The difference between `ReadPure` or `ReadOnly` (and likewise between " +"`ReadPureWrite` and `ReadWrite`) is whether reading a register can have 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." msgstr "" -#: src/generics/generic-data.md +#: src/bare-metal/aps/safemmio/driver.md msgid "" -"_Q:_ Why `T` is specified twice in `impl Point {}`? Isn't that " -"redundant?" +"/// Constructs a new instance of the UART driver for a PL011 device with " +"the\n" +" /// given set of registers.\n" msgstr "" -#: src/generics/generic-data.md +#: src/bare-metal/aps/safemmio/driver.md +msgid "The driver no longer needs any unsafe code!" +msgstr "" + +#: src/bare-metal/aps/safemmio/driver.md msgid "" -"This is because it is a generic implementation section for generic type. " -"They are independently generic." +"`UniqueMmioPointer` is a wrapper around a raw pointer to an MMIO device or " +"register. The caller of `UniqueMmioPointer::new` promises that it is valid " +"and unique for the given lifetime, so it can provide safe methods to read " +"and write fields." msgstr "" -#: src/generics/generic-data.md -msgid "It means these methods are defined for any `T`." +#: src/bare-metal/aps/safemmio/driver.md +msgid "" +"Note that `Uart::new` is now safe; `UniqueMmioPointer::new` is unsafe " +"instead." msgstr "" -#: src/generics/generic-data.md -msgid "It is possible to write `impl Point { .. }`." +#: src/bare-metal/aps/safemmio/driver.md +msgid "" +"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 virtualization." msgstr "" -#: src/generics/generic-data.md +#: src/bare-metal/aps/safemmio/driver.md msgid "" -"`Point` is still generic and you can use `Point`, but methods in this " -"block will only be available for `Point`." +"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." msgstr "" -#: src/generics/generic-data.md +#: src/bare-metal/aps/safemmio/driver.md msgid "" -"Try declaring a new variable `let p = Point { x: 5, y: 10.0 };`. Update the " -"code to allow points that have elements of different types, by using two " -"type variables, e.g., `T` and `U`." +"`field!` needs a mutable reference to a `UniqueMmioPointer`, and returns a " +"`UniqueMmioPointer` that allows reads with side effects and writes." msgstr "" -#: src/generics/trait-bounds.md +#: src/bare-metal/aps/safemmio/driver.md msgid "" -"When working with generics, you often want to require the types to implement " -"some trait, so that you can call this trait's methods." +"`field_shared!` works with a shared reference to either a " +"`UniqueMmioPointer` or a `SharedMmioPointer`. It returns a " +"`SharedMmioPointer` that only allows pure reads." msgstr "" -#: src/generics/trait-bounds.md -msgid "You can do this with `T: Trait` or `impl Trait`:" +#: src/bare-metal/aps/safemmio/using.md +msgid "" +"Let's write a small program using our driver to write to the serial console, " +"and echo incoming bytes." msgstr "" -#: src/generics/trait-bounds.md -msgid "// struct NotClonable;" +#: src/bare-metal/aps/safemmio/using.md +msgid "b'\\r'" msgstr "" -#: src/generics/trait-bounds.md -msgid "\"{pair:?}\"" +#: src/bare-metal/aps/safemmio/using.md +#: src/concurrency/async-pitfalls/cancellation.md +msgid "b'\\n'" msgstr "" -#: src/generics/trait-bounds.md -msgid "Try making a `NonClonable` and passing it to `duplicate`." +#: src/bare-metal/aps/safemmio/using.md +msgid "b'q'" msgstr "" -#: src/generics/trait-bounds.md -msgid "When multiple traits are necessary, use `+` to join them." +#: src/bare-metal/aps/safemmio/using.md +msgid "\"\\n\\nBye!\"" msgstr "" -#: src/generics/trait-bounds.md -msgid "Show a `where` clause, students will encounter it when reading code." +#: src/bare-metal/aps/safemmio/using.md +msgid "" +"Run the example in QEMU with `make qemu_safemmio` under `src/bare-metal/aps/" +"examples`." msgstr "" -#: src/generics/trait-bounds.md -msgid "It declutters the function signature if you have many parameters." +#: src/bare-metal/aps/logging.md +msgid "" +"It would be nice to be able to use the logging macros from the [`log`]" +"(https://crates.io/crates/log) crate. We can do this by implementing the " +"`Log` trait." +msgstr "" + +#: src/bare-metal/aps/logging.md +msgid "\"[{}] {}\"" msgstr "" -#: src/generics/trait-bounds.md -msgid "It has additional features making it more powerful." +#: src/bare-metal/aps/logging.md +msgid "/// Initialises UART logger.\n" msgstr "" -#: src/generics/trait-bounds.md +#: src/bare-metal/aps/logging.md msgid "" -"If someone asks, the extra feature is that the type on the left of \":\" can " -"be arbitrary, like `Option`." +"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`." msgstr "" -#: src/generics/trait-bounds.md -msgid "" -"Note that Rust does not (yet) support specialization. For example, given the " -"original `duplicate`, it is invalid to add a specialized `duplicate(a: u32)`." +#: src/bare-metal/aps/logging/using.md +msgid "We need to initialise the logger before we use it." msgstr "" -#: src/generics/impl-trait.md -msgid "" -"Similar to trait bounds, an `impl Trait` syntax can be used in function " -"arguments and return values:" +#: src/bare-metal/aps/logging/using.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "\"{info}\"" msgstr "" -#: src/generics/impl-trait.md -msgid "// Syntactic sugar for:" +#: src/bare-metal/aps/logging/using.md +msgid "Note that our panic handler can now log details of panics." msgstr "" -#: src/generics/impl-trait.md -msgid "// fn add_42_millions>(x: T) -> i32 {" +#: src/bare-metal/aps/logging/using.md +msgid "" +"Run the example in QEMU with `make qemu_logger` under `src/bare-metal/aps/" +"examples`." msgstr "" -#: src/generics/impl-trait.md -msgid "\"{many}\"" +#: src/bare-metal/aps/exceptions.md +msgid "" +"AArch64 defines an exception vector table with 16 entries, for 4 types of " +"exceptions (synchronous, IRQ, FIQ, SError) from 4 states (current EL with " +"SP0, current EL with SPx, lower EL using AArch64, lower EL using AArch32). " +"We implement this in assembly to save volatile registers to the stack before " +"calling into Rust code:" msgstr "" -#: src/generics/impl-trait.md -msgid "\"{many_more}\"" +#: src/bare-metal/aps/exceptions.md +msgid "EL is exception level; all our examples this afternoon run in EL1." msgstr "" -#: src/generics/impl-trait.md -msgid "\"debuggable: {debuggable:?}\"" +#: src/bare-metal/aps/exceptions.md +msgid "" +"For simplicity we aren't distinguishing between SP0 and SPx for the current " +"EL exceptions, or between AArch32 and AArch64 for the lower EL exceptions." msgstr "" -#: src/generics/impl-trait.md +#: src/bare-metal/aps/exceptions.md msgid "" -"`impl Trait` allows you to work with types which you cannot name. The " -"meaning of `impl Trait` is a bit different in the different positions." +"For this example we just log the exception and power down, as we don't " +"expect any of them to actually happen." msgstr "" -#: src/generics/impl-trait.md +#: src/bare-metal/aps/exceptions.md msgid "" -"For a parameter, `impl Trait` is like an anonymous generic parameter with a " -"trait bound." +"We can think of exception handlers and our main execution context more or " +"less like different threads. [`Send` and `Sync`](../../concurrency/send-sync." +"md) will control what we can share between them, just like with threads. For " +"example, if we want to share some value between exception handlers and the " +"rest of the program, and it's `Send` but not `Sync`, then we'll need to wrap " +"it in something like a `Mutex` and put it in a static." msgstr "" -#: src/generics/impl-trait.md -msgid "" -"For a return type, it means that the return type is some concrete type that " -"implements the trait, without naming the type. This can be useful when you " -"don't want to expose the concrete type in a public API." +#: src/bare-metal/aps/exceptions.md +msgid "The assembly code for the exception vector:" msgstr "" -#: src/generics/impl-trait.md +#: src/bare-metal/aps/aarch64-rt.md msgid "" -"Inference is hard in return position. A function returning `impl Foo` picks " -"the concrete type it returns, without writing it out in the source. A " -"function returning a generic type like `collect() -> B` can return any " -"type satisfying `B`, and the caller may need to choose one, such as with " -"`let x: Vec<_> = foo.collect()` or with the turbofish, `foo.collect::" -">()`." +"The `aarch64-rt` crate provides the assembly entry point and exception " +"vector that we implemented before. We just need to mark our main function " +"with the `entry!` macro." msgstr "" -#: src/generics/impl-trait.md +#: src/bare-metal/aps/aarch64-rt.md msgid "" -"What is the type of `debuggable`? Try `let debuggable: () = ..` to see what " -"the error message shows." +"It also provides the `initial_pagetable!` macro to let us define an initial " +"static pagetable in Rust, rather than in assembly code like we did before." msgstr "" -#: src/generics/exercise.md +#: src/bare-metal/aps/aarch64-rt.md msgid "" -"In this short exercise, you will implement a generic `min` function that " -"determines the minimum of two values, using a `LessThan` trait." +"We can also use the UART driver from the `arm-pl011-uart` crate rather than " +"writing our own." msgstr "" -#: src/generics/exercise.md src/generics/solution.md -msgid "/// Return true if self is less than other.\n" +#: src/bare-metal/aps/aarch64-rt.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Attributes to use for device memory in the initial identity map.\n" msgstr "" -#: src/generics/exercise.md -msgid "// TODO: implement the `min` function used in `main`." +#: src/bare-metal/aps/aarch64-rt.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Attributes to use for normal memory in the initial identity map.\n" msgstr "" -#: src/generics/exercise.md src/generics/solution.md -msgid "\"Shapiro\"" +#: src/bare-metal/aps/aarch64-rt.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "// 1 GiB of device memory.\n" msgstr "" -#: src/generics/exercise.md src/generics/solution.md -msgid "\"Baumann\"" +#: src/bare-metal/aps/aarch64-rt.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "// 1 GiB of normal memory.\n" msgstr "" -#: src/welcome-day-2-afternoon.md -msgid "[Standard Library Types](./std-types.md) (1 hour and 20 minutes)" +#: src/bare-metal/aps/aarch64-rt.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "// Another 1 GiB of device memory starting at 256 GiB.\n" msgstr "" -#: src/welcome-day-2-afternoon.md -msgid "[Standard Library Traits](./std-traits.md) (1 hour and 40 minutes)" +#: src/bare-metal/aps/aarch64-rt.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "\"system_off returned\"" msgstr "" -#: src/welcome-day-2-afternoon.md +#: src/bare-metal/aps/aarch64-rt.md msgid "" -"Including 10 minute breaks, this session should take about 3 hours and 10 " -"minutes" -msgstr "" - -#: src/std-types.md -msgid "[Standard Library](./std-types/std.md) (3 minutes)" +"Run the example in QEMU with `make qemu_rt` under `src/bare-metal/aps/" +"examples`." msgstr "" -#: src/std-types.md -msgid "[Documentation](./std-types/docs.md) (5 minutes)" +#: src/bare-metal/aps/aarch64-rt/exceptions.md +msgid "" +"`aarch64-rt` provides a trait to define exception handlers, and a macro to " +"generate the assembly code for the exception vector to call them." msgstr "" -#: src/std-types.md -msgid "[Option](./std-types/option.md) (10 minutes)" +#: src/bare-metal/aps/aarch64-rt/exceptions.md +msgid "" +"The trait has default implementations for each method which simply panic, so " +"we can omit methods for exceptions we don't expect to happen." msgstr "" -#: src/std-types.md -msgid "[Result](./std-types/result.md) (10 minutes)" +#: src/bare-metal/aps/aarch64-rt/exceptions.md +msgid "" +"The `exception_handlers` macro generates a `global_asm!` block with the " +"exception vector to call into the Rust code, similar to the `exceptions.S` " +"we had before." msgstr "" -#: src/std-types.md -msgid "[String](./std-types/string.md) (10 minutes)" +#: src/bare-metal/aps/aarch64-rt/exceptions.md +msgid "" +"`RegisterStateRef` wraps a reference to the stack frame where the register " +"values were saved by the assembly code when the exception happed. This can " +"be used for example to extract the parameters for an SMC or HVC call from a " +"lower EL, and update the values to be restored when the exception handler " +"returns." msgstr "" -#: src/std-types.md -msgid "[Vec](./std-types/vec.md) (10 minutes)" +#: src/bare-metal/aps/other-projects.md +msgid "[oreboot](https://github.com/oreboot/oreboot)" msgstr "" -#: src/std-types.md -msgid "[HashMap](./std-types/hashmap.md) (10 minutes)" +#: src/bare-metal/aps/other-projects.md +msgid "\"coreboot without the C\"." msgstr "" -#: src/std-types.md -msgid "[Exercise: Counter](./std-types/exercise.md) (20 minutes)" +#: src/bare-metal/aps/other-projects.md +msgid "Supports x86, aarch64 and RISC-V." msgstr "" -#: src/std-types.md -msgid "This segment should take about 1 hour and 20 minutes" +#: src/bare-metal/aps/other-projects.md +msgid "Relies on LinuxBoot rather than having many drivers itself." msgstr "" -#: src/std-types.md +#: src/bare-metal/aps/other-projects.md msgid "" -"For each of the slides in this section, spend some time reviewing the " -"documentation pages, highlighting some of the more common methods." +"[Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-" +"raspberrypi-OS-tutorials)" msgstr "" -#: src/std-types/std.md +#: src/bare-metal/aps/other-projects.md msgid "" -"Rust comes with a standard library which helps establish a set of common " -"types used by Rust libraries and programs. This way, two libraries can work " -"together smoothly because they both use the same `String` type." +"Initialization, UART driver, simple bootloader, JTAG, exception levels, " +"exception handling, page tables." msgstr "" -#: src/std-types/std.md +#: src/bare-metal/aps/other-projects.md msgid "" -"In fact, Rust contains several layers of the Standard Library: `core`, " -"`alloc` and `std`." +"Some caveats around cache maintenance and initialization in Rust, not " +"necessarily a good example to copy for production code." msgstr "" -#: src/std-types/std.md -msgid "" -"`core` includes the most basic types and functions that don't depend on " -"`libc`, allocator or even the presence of an operating system." +#: src/bare-metal/aps/other-projects.md +msgid "[`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)" msgstr "" -#: src/std-types/std.md -msgid "" -"`alloc` includes types which require a global heap allocator, such as `Vec`, " -"`Box` and `Arc`." +#: src/bare-metal/aps/other-projects.md +msgid "Static analysis to determine maximum stack usage." msgstr "" -#: src/std-types/std.md +#: src/bare-metal/aps/other-projects.md msgid "" -"Embedded Rust applications often only use `core`, and sometimes `alloc`." +"The RaspberryPi OS tutorial runs Rust code before the MMU and caches are " +"enabled. This will read and write memory (e.g. the stack). However, this has " +"the problems mentioned at the beginning of this session regarding unaligned " +"access and cache coherency." msgstr "" -#: src/std-types/docs.md -msgid "Rust comes with extensive documentation. For example:" +#: src/bare-metal/useful-crates.md +msgid "Useful crates" msgstr "" -#: src/std-types/docs.md +#: src/bare-metal/useful-crates.md msgid "" -"All of the details about [loops](https://doc.rust-lang.org/stable/reference/" -"expressions/loop-expr.html)." +"We'll look at a few crates that solve some common problems in bare-metal " +"programming." msgstr "" -#: src/std-types/docs.md +#: src/bare-metal/useful-crates/zerocopy.md msgid "" -"Primitive types like [`u8`](https://doc.rust-lang.org/stable/std/primitive." -"u8.html)." +"The [`zerocopy`](https://docs.rs/zerocopy/) crate (from Fuchsia) provides " +"traits and macros for safely converting between byte sequences and other " +"types." msgstr "" -#: src/std-types/docs.md +#: src/bare-metal/useful-crates/zerocopy.md msgid "" -"Standard library types like [`Option`](https://doc.rust-lang.org/stable/std/" -"option/enum.Option.html) or [`BinaryHeap`](https://doc.rust-lang.org/stable/" -"std/collections/struct.BinaryHeap.html)." -msgstr "" - -#: src/std-types/docs.md -msgid "In fact, you can document your own code:" +"This is not suitable for MMIO (as it doesn't use volatile reads and writes), " +"but can be useful for working with structures shared with hardware e.g. by " +"DMA, or sent over some external interface." msgstr "" -#: src/std-types/docs.md +#: src/bare-metal/useful-crates/zerocopy.md msgid "" -"/// Determine whether the first argument is divisible by the second argument." -msgstr "" - -#: src/std-types/docs.md src/testing/other.md -#: src/unsafe-rust/unsafe-functions.md -msgid "///" +"`FromBytes` can be implemented for types for which any byte pattern is " +"valid, and so can safely be converted from an untrusted sequence of bytes." msgstr "" -#: src/std-types/docs.md -msgid "/// If the second argument is zero, the result is false." +#: src/bare-metal/useful-crates/zerocopy.md +msgid "" +"Attempting to derive `FromBytes` for these types would fail, because " +"`RequestType` doesn't use all possible u32 values as discriminants, so not " +"all byte patterns are valid." msgstr "" -#: src/std-types/docs.md +#: src/bare-metal/useful-crates/zerocopy.md msgid "" -"The contents are treated as Markdown. All published Rust library crates are " -"automatically documented at [`docs.rs`](https://docs.rs) using the [rustdoc]" -"(https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It is " -"idiomatic to document all public items in an API using this pattern." +"`zerocopy::byteorder` has types for byte-order aware numeric primitives." msgstr "" -#: src/std-types/docs.md +#: src/bare-metal/useful-crates/zerocopy.md msgid "" -"To document an item from inside the item (such as inside a module), use `//!" -"` or `/*! .. */`, called \"inner doc comments\":" +"Run the example with `cargo run` under `src/bare-metal/useful-crates/" +"zerocopy-example/`. (It won't run in the Playground because of the crate " +"dependency.)" msgstr "" -#: src/std-types/docs.md +#: src/bare-metal/useful-crates/aarch64-paging.md msgid "" -"//! This module contains functionality relating to divisibility of integers." +"The [`aarch64-paging`](https://crates.io/crates/aarch64-paging) crate lets " +"you create page tables according to the AArch64 Virtual Memory System " +"Architecture." msgstr "" -#: src/std-types/docs.md -msgid "" -"Show students the generated docs for the `rand` crate at ." +#: src/bare-metal/useful-crates/aarch64-paging.md +msgid "// Create a new page table with identity mapping.\n" msgstr "" -#: src/std-types/option.md -#, fuzzy -msgid "Option" -msgstr "āĻŦā§āϝāϤāĻŋāĻ•ā§āϰāĻŽ" +#: src/bare-metal/useful-crates/aarch64-paging.md +msgid "// Map a 2 MiB region of memory as read-only.\n" +msgstr "" -#: src/std-types/option.md -msgid "" -"We have already seen some use of `Option`. It stores either a value of " -"type `T` or nothing. For example, [`String::find`](https://doc.rust-lang.org/" -"stable/std/string/struct.String.html#method.find) returns an `Option`." +#: src/bare-metal/useful-crates/aarch64-paging.md +msgid "// Set `TTBR0_EL1` to activate the page table.\n" msgstr "" -#: src/std-types/option.md -msgid "\"LÃļwe 老虎 LÊopard Gepardi\"" +#: src/bare-metal/useful-crates/aarch64-paging.md +msgid "" +"This is used in Android for the [Protected VM Firmware](https://cs.android." +"com/android/platform/superproject/main/+/main:packages/modules/" +"Virtualization/guest/pvmfw/)." msgstr "" -#: src/std-types/option.md -msgid "'Ê'" +#: src/bare-metal/useful-crates/aarch64-paging.md +msgid "" +"There's no easy way to run this example by itself, as it needs to run on " +"real hardware or under QEMU." msgstr "" -#: src/std-types/option.md -msgid "\"find returned {position:?}\"" +#: src/bare-metal/useful-crates/buddy_system_allocator.md +msgid "" +"[`buddy_system_allocator`](https://crates.io/crates/buddy_system_allocator) " +"is a crate that implements a basic buddy system allocator. It can be used " +"both to implement [`GlobalAlloc`](https://doc.rust-lang.org/core/alloc/trait." +"GlobalAlloc.html) (using [`LockedHeap`](https://docs.rs/" +"buddy_system_allocator/0.9.0/buddy_system_allocator/struct.LockedHeap.html)) " +"so you can use the standard `alloc` crate (as we saw [before](../alloc.md)), " +"or for allocating other address space (using [`FrameAllocator`](https://docs." +"rs/buddy_system_allocator/0.9.0/buddy_system_allocator/struct.FrameAllocator." +"html)) . For example, we might want to allocate MMIO space for PCI BARs:" msgstr "" -#: src/std-types/option.md -msgid "'Z'" +#: src/bare-metal/useful-crates/buddy_system_allocator.md +msgid "PCI BARs always have alignment equal to their size." msgstr "" -#: src/std-types/option.md -msgid "\"Character not found\"" +#: src/bare-metal/useful-crates/buddy_system_allocator.md +msgid "" +"Run the example with `cargo run` under `src/bare-metal/useful-crates/" +"allocator-example/`. (It won't run in the Playground because of the crate " +"dependency.)" msgstr "" -#: src/std-types/option.md -msgid "`Option` is widely used, not just in the standard library." +#: src/bare-metal/useful-crates/tinyvec.md +msgid "" +"Sometimes you want something that can be resized like a `Vec`, but without " +"heap allocation. [`tinyvec`](https://crates.io/crates/tinyvec) provides " +"this: a vector backed by an array or slice, 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." msgstr "" -#: src/std-types/option.md +#: src/bare-metal/useful-crates/tinyvec.md msgid "" -"`unwrap` will return the value in an `Option`, or panic. `expect` is similar " -"but takes an error message." +"`tinyvec` requires that the element type implement `Default` for " +"initialization." msgstr "" -#: src/std-types/option.md +#: src/bare-metal/useful-crates/tinyvec.md msgid "" -"You can panic on None, but you can't \"accidentally\" forget to check for " -"None." +"The Rust Playground includes `tinyvec`, so this example will run fine inline." msgstr "" -#: src/std-types/option.md +#: src/bare-metal/useful-crates/spin.md msgid "" -"It's common to `unwrap`/`expect` all over the place when hacking something " -"together, but production code typically handles `None` in a nicer fashion." +"`std::sync::Mutex` and the other synchronisation primitives from `std::sync` " +"are not available in `core` or `alloc`. How can we manage synchronisation or " +"interior mutability, such as for sharing state between different CPUs?" msgstr "" -#: src/std-types/option.md +#: src/bare-metal/useful-crates/spin.md msgid "" -"The niche optimization means that `Option` often has the same size in " -"memory as `T`." +"The [`spin`](https://crates.io/crates/spin) crate provides spinlock-based " +"equivalents of many of these primitives." msgstr "" -#: src/std-types/result.md -msgid "Result" +#: src/bare-metal/useful-crates/spin.md +msgid "Be careful to avoid deadlock if you take locks in interrupt handlers." msgstr "" -#: src/std-types/result.md +#: src/bare-metal/useful-crates/spin.md msgid "" -"`Result` is similar to `Option`, but indicates the success or failure of an " -"operation, each with a different type. This is similar to the `Res` defined " -"in the expression exercise, but generic: `Result` where `T` is used in " -"the `Ok` variant and `E` appears in the `Err` variant." +"`spin` also has a ticket lock mutex implementation; equivalents of `RwLock`, " +"`Barrier` and `Once` from `std::sync`; and `Lazy` for lazy initialization." msgstr "" -#: src/std-types/result.md -msgid "\"diary.txt\"" +#: src/bare-metal/useful-crates/spin.md +msgid "" +"The [`once_cell`](https://crates.io/crates/once_cell) crate also has some " +"useful types for late initialization with a slightly different approach to " +"`spin::once::Once`." msgstr "" -#: src/std-types/result.md -msgid "\"Dear diary: {contents} ({bytes} bytes)\"" +#: src/bare-metal/useful-crates/spin.md +msgid "" +"The Rust Playground includes `spin`, so this example will run fine inline." msgstr "" -#: src/std-types/result.md -msgid "\"Could not read file content\"" +#: src/bare-metal/android.md +msgid "" +"To build a bare-metal Rust binary in AOSP, you need to use a " +"`rust_ffi_static` Soong rule to build your Rust code, then a `cc_binary` " +"with a linker script to produce the binary itself, and then a `raw_binary` " +"to convert the ELF to a raw binary ready to be run." msgstr "" -#: src/std-types/result.md -msgid "\"The diary could not be opened: {err}\"" +#: src/bare-metal/android/vmbase.md +msgid "vmbase" msgstr "" -#: src/std-types/result.md +#: src/bare-metal/android/vmbase.md msgid "" -"As with `Option`, the successful value sits inside of `Result`, forcing the " -"developer to explicitly extract it. This encourages error checking. In the " -"case where an error should never happen, `unwrap()` or `expect()` can be " -"called, and this is a signal of the developer intent too." +"For VMs running under crosvm on aarch64, the [vmbase](https://android." +"googlesource.com/platform/packages/modules/Virtualization/+/refs/heads/main/" +"libs/libvmbase/) library provides a linker script and useful defaults for " +"the build rules, along with an entry point, UART console logging and more." msgstr "" -#: src/std-types/result.md +#: src/bare-metal/android/vmbase.md msgid "" -"`Result` documentation is a recommended read. Not during the course, but it " -"is worth mentioning. It contains a lot of convenience methods and functions " -"that help functional-style programming." +"The `main!` macro marks your main function, to be called from the `vmbase` " +"entry point." msgstr "" -#: src/std-types/result.md +#: src/bare-metal/android/vmbase.md msgid "" -"`Result` is the standard type to implement error handling as we will see on " -"Day 3." +"The `vmbase` entry point handles console initialisation, and issues a " +"PSCI_SYSTEM_OFF to shutdown the VM if your main function returns." msgstr "" -#: src/std-types/string.md -msgid "String" -msgstr "String" - -#: src/std-types/string.md -msgid "" -"[`String`](https://doc.rust-lang.org/std/string/struct.String.html) is the " -"standard heap-allocated growable UTF-8 string buffer:" +#: src/exercises/bare-metal/afternoon.md +msgid "We will write a driver for the PL031 real-time clock device." msgstr "" -#: src/std-types/string.md src/std-traits/read-and-write.md -#: src/memory-management/review.md src/testing/unit-tests.md -#: src/concurrency/scoped-threads.md -msgid "\"Hello\"" +#: src/exercises/bare-metal/afternoon.md +msgid "" +"After looking at the exercises, you can look at the [solutions](solutions-" +"afternoon.md) provided." msgstr "" -#: src/std-types/string.md -msgid "\"s1: len = {}, capacity = {}\"" +#: src/exercises/bare-metal/rtc.md +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "RTC driver" msgstr "" -#: src/std-types/string.md -msgid "'!'" +#: src/exercises/bare-metal/rtc.md +msgid "" +"The QEMU aarch64 virt machine has a [PL031](https://developer.arm.com/" +"documentation/ddi0224/c) real-time clock at 0x9010000. For this exercise, " +"you should write a driver for it." msgstr "" -#: src/std-types/string.md -msgid "\"s2: len = {}, capacity = {}\"" +#: src/exercises/bare-metal/rtc.md +msgid "" +"Use it to print the current time to the serial console. You can use the " +"[`chrono`](https://crates.io/crates/chrono) crate for date/time formatting." msgstr "" -#: src/std-types/string.md -msgid "\"🇨🇭\"" +#: src/exercises/bare-metal/rtc.md +msgid "" +"Use the match register and raw interrupt status to busy-wait until a given " +"time, e.g. 3 seconds in the future. (Call [`core::hint::spin_loop`](https://" +"doc.rust-lang.org/core/hint/fn.spin_loop.html) inside the loop.)" msgstr "" -#: src/std-types/string.md -msgid "\"s3: len = {}, number of chars = {}\"" +#: src/exercises/bare-metal/rtc.md +msgid "" +"_Extension if you have time:_ Enable and handle the interrupt generated by " +"the RTC match. You can use the driver provided in the [`arm-gic`](https://" +"docs.rs/arm-gic/) crate to configure the Arm Generic Interrupt Controller." msgstr "" -#: src/std-types/string.md -msgid "" -"`String` implements [`Deref`](https://doc.rust-lang.org/std/" -"string/struct.String.html#deref-methods-str), which means that you can call " -"all `str` methods on a `String`." +#: src/exercises/bare-metal/rtc.md +msgid "Use the RTC interrupt, which is wired to the GIC as `IntId::spi(2)`." msgstr "" -#: src/std-types/string.md +#: src/exercises/bare-metal/rtc.md msgid "" -"`String::new` returns a new empty string, use `String::with_capacity` when " -"you know how much data you want to push to the string." +"Once the interrupt is enabled, you can put the core to sleep via `arm_gic::" +"wfi()`, which will cause the core to sleep until it receives an interrupt." msgstr "" -#: src/std-types/string.md +#: src/exercises/bare-metal/rtc.md msgid "" -"`String::len` returns the size of the `String` in bytes (which can be " -"different from its length in characters)." +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and " +"look in the `rtc` directory for the following files." msgstr "" -#: src/std-types/string.md +#: src/exercises/bare-metal/rtc.md msgid "" -"`String::chars` returns an iterator over the actual characters. Note that a " -"`char` can be different from what a human will consider a \"character\" due " -"to [grapheme clusters](https://docs.rs/unicode-segmentation/latest/" -"unicode_segmentation/struct.Graphemes.html)." +"_src/exceptions.rs_ (you should only need to change this for the 3rd part of " +"the exercise):" msgstr "" -#: src/std-types/string.md -msgid "" -"When people refer to strings they could either be talking about `&str` or " -"`String`." +#: src/exercises/bare-metal/rtc.md +msgid "_src/logger.rs_ (you shouldn't need to change this):" msgstr "" -#: src/std-types/string.md -msgid "" -"When a type implements `Deref`, the compiler will let you " -"transparently call methods from `T`." +#: src/exercises/bare-metal/rtc.md +msgid "_build.rs_ (you shouldn't need to change this):" msgstr "" -#: src/std-types/string.md -msgid "" -"We haven't discussed the `Deref` trait yet, so at this point this mostly " -"explains the structure of the sidebar in the documentation." +#: src/exercises/bare-metal/rtc.md +msgid "_memory.ld_ (you shouldn't need to change this):" msgstr "" -#: src/std-types/string.md -msgid "" -"`String` implements `Deref` which transparently gives it " -"access to `str`'s methods." +#: src/exercises/bare-metal/rtc.md +msgid "_Makefile_ (you shouldn't need to change this):" msgstr "" -#: src/std-types/string.md -msgid "Write and compare `let s3 = s1.deref();` and `let s3 = &*s1;`." +#: src/exercises/bare-metal/rtc.md +msgid "Run the code in QEMU with `make qemu`." msgstr "" -#: src/std-types/string.md -msgid "" -"`String` is implemented as a wrapper around a vector of bytes, many of the " -"operations you see supported on vectors are also supported on `String`, but " -"with some extra guarantees." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "Bare Metal Rust Afternoon" msgstr "" -#: src/std-types/string.md -msgid "Compare the different ways to index a `String`:" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "([back to exercise](rtc.md))" msgstr "" -#: src/std-types/string.md -msgid "" -"To a character by using `s3.chars().nth(i).unwrap()` where `i` is in-bound, " -"out-of-bounds." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "_main.rs_:" msgstr "" -#: src/std-types/string.md -msgid "" -"To a substring by using `s3[0..4]`, where that slice is on character " -"boundaries or not." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Base addresses of the GICv3.\n" msgstr "" -#: src/std-types/string.md -msgid "" -"Many types can be converted to a string with the [`to_string`](https://doc." -"rust-lang.org/std/string/trait.ToString.html#tymethod.to_string) method. " -"This trait is automatically implemented for all types that implement " -"`Display`, so anything that can be formatted can also be converted to a " -"string." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Base address of the PL031 RTC.\n" msgstr "" -#: src/std-types/vec.md -msgid "" -"[`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html) is the standard " -"resizable heap-allocated buffer:" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// The IRQ used by the PL031 RTC.\n" msgstr "" -#: src/std-types/vec.md -msgid "\"v1: len = {}, capacity = {}\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "\"main({:#x}, {:#x}, {:#x}, {:#x})\"" msgstr "" -#: src/std-types/vec.md -msgid "\"v2: len = {}, capacity = {}\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "" +"// SAFETY: `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base\n" +" // addresses of a GICv3 distributor and redistributor respectively, and\n" +" // nothing else accesses those address ranges.\n" msgstr "" -#: src/std-types/vec.md -msgid "// Canonical macro to initialize a vector with elements." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "" +"// SAFETY: `PL031_BASE_ADDRESS` is the base address of a PL031 device, and\n" +" // nothing else accesses that address range.\n" msgstr "" -#: src/std-types/vec.md -msgid "// Retain only the even elements." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "\"RTC: {time}\"" msgstr "" -#: src/std-types/vec.md -msgid "\"{v3:?}\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "// Wait for 3 seconds, without interrupts.\n" msgstr "" -#: src/std-types/vec.md -msgid "// Remove consecutive duplicates." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "\"Waiting for {}\"" msgstr "" -#: src/std-types/vec.md -msgid "" -"`Vec` implements [`Deref`](https://doc.rust-lang.org/std/vec/" -"struct.Vec.html#deref-methods-%5BT%5D), which means that you can call slice " -"methods on a `Vec`." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "\"matched={}, interrupt_pending={}\"" msgstr "" -#: src/std-types/vec.md -msgid "" -"`Vec` is a type of collection, along with `String` and `HashMap`. The data " -"it contains is stored on the heap. This means the amount of data doesn't " -"need to be known at compile time. It can grow or shrink at runtime." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "\"Finished waiting\"" msgstr "" -#: src/std-types/vec.md -msgid "" -"Notice how `Vec` is a generic type too, but you don't have to specify `T` " -"explicitly. As always with Rust type inference, the `T` was established " -"during the first `push` call." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "// Wait another 3 seconds for an interrupt.\n" msgstr "" -#: src/std-types/vec.md -msgid "" -"`vec![...]` is a canonical macro to use instead of `Vec::new()` and it " -"supports adding initial elements to the vector." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "_pl031.rs_:" msgstr "" -#: src/std-types/vec.md -msgid "" -"To index the vector you use `[` `]`, but they will panic if out of bounds. " -"Alternatively, using `get` will return an `Option`. The `pop` function will " -"remove the last element." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Data register\n" msgstr "" -#: src/std-types/vec.md -msgid "" -"Slices are covered on day 3. For now, students only need to know that a " -"value of type `Vec` gives access to all of the documented slice methods, too." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Match register\n" msgstr "" -#: src/std-types/hashmap.md -msgid "Standard hash map with protection against HashDoS attacks:" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Load register\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"Adventures of Huckleberry Finn\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Control register\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"Grimms' Fairy Tales\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Interrupt Mask Set or Clear register\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"Pride and Prejudice\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Raw Interrupt Status\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"Les MisÊrables\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Masked Interrupt Status\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"We know about {} books, but not Les MisÊrables.\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Interrupt Clear Register\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"Alice's Adventure in Wonderland\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Driver for a PL031 real-time clock.\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"{book}: {count} pages\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "" +"/// Constructs a new instance of the RTC driver for a PL031 device with the\n" +" /// given set of registers.\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"{book} is unknown.\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Reads the current RTC value.\n" msgstr "" -#: src/std-types/hashmap.md -msgid "// Use the .entry() method to insert a value if nothing is found." +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "" +"/// Writes a match value. When the RTC value matches this then an interrupt\n" +" /// will be generated (if it is enabled).\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"{page_counts:#?}\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "" +"/// Returns whether the match register matches the RTC value, whether or " +"not\n" +" /// the interrupt is enabled.\n" msgstr "" -#: src/std-types/hashmap.md +#: src/exercises/bare-metal/solutions-afternoon.md msgid "" -"`HashMap` is not defined in the prelude and needs to be brought into scope." +"/// Returns whether there is currently an interrupt pending.\n" +" ///\n" +" /// This should be true if and only if `matched` returns true and the\n" +" /// interrupt is masked.\n" msgstr "" -#: src/std-types/hashmap.md +#: src/exercises/bare-metal/solutions-afternoon.md msgid "" -"Try the following lines of code. The first line will see if a book is in the " -"hashmap and if not return an alternative value. The second line will insert " -"the alternative value in the hashmap if the book is not found." +"/// Sets or clears the interrupt mask.\n" +" ///\n" +" /// When the mask is true the interrupt is enabled; when it is false " +"the\n" +" /// interrupt is disabled.\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"Harry Potter and the Sorcerer's Stone\"" +#: src/exercises/bare-metal/solutions-afternoon.md +msgid "/// Clears a pending interrupt, if any.\n" msgstr "" -#: src/std-types/hashmap.md -msgid "\"The Hunger Games\"" +#: src/concurrency/welcome.md +msgid "Welcome to Concurrency in Rust" msgstr "" -#: src/std-types/hashmap.md -msgid "Unlike `vec!`, there is unfortunately no standard `hashmap!` macro." +#: src/concurrency/welcome.md +msgid "" +"Rust has full support for concurrency using OS threads with mutexes and " +"channels." msgstr "" -#: src/std-types/hashmap.md +#: src/concurrency/welcome.md msgid "" -"Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`](https://" -"doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#impl-" -"From%3C%5B(K,+V);+N%5D%3E-for-HashMap%3CK,+V,+RandomState%3E), which allows " -"us to easily initialize a hash map from a literal array:" +"The Rust type system plays an important role in making many concurrency bugs " +"compile time errors. This idea is known as _fearless concurrency_ since you " +"can rely on the compiler to ensure correctness at runtime." msgstr "" -#: src/std-types/hashmap.md +#: src/concurrency/welcome.md msgid "" -"Alternatively HashMap can be built from any `Iterator` which yields key-" -"value tuples." +"Including 10 minute breaks, this session should take about 3 hours and 20 " +"minutes. It contains:" msgstr "" -#: src/std-types/hashmap.md +#: src/concurrency/welcome.md msgid "" -"We are showing `HashMap`, and avoid using `&str` as key to make " -"examples easier. Using references in collections can, of course, be done, " -"but it can lead into complications with the borrow checker." +"Rust lets us access OS concurrency toolkit: threads, sync. primitives, etc." msgstr "" -#: src/std-types/hashmap.md +#: src/concurrency/welcome.md msgid "" -"Try removing `to_string()` from the example above and see if it still " -"compiles. Where do you think we might run into issues?" +"The type system gives us safety for concurrency without any special features." msgstr "" -#: src/std-types/hashmap.md +#: src/concurrency/welcome.md msgid "" -"This type has several \"method-specific\" return types, such as `std::" -"collections::hash_map::Keys`. These types often appear in searches of the " -"Rust docs. Show students the docs for this type, and the helpful link back " -"to the `keys` method." +"The same tools that help with \"concurrent\" access in a single thread (e." +"g., a called function that might mutate an argument or save references to it " +"to read later) save us from multi-threading issues." msgstr "" -#: src/std-types/exercise.md -msgid "" -"In this exercise you will take a very simple data structure and make it " -"generic. It uses a [`std::collections::HashMap`](https://doc.rust-lang.org/" -"stable/std/collections/struct.HashMap.html) to keep track of which values " -"have been seen and how many times each one has appeared." +#: src/concurrency/threads/plain.md +msgid "Rust threads work similarly to threads in other languages:" msgstr "" -#: src/std-types/exercise.md -msgid "" -"The initial version of `Counter` is hard coded to only work for `u32` " -"values. Make the struct and its methods generic over the type of value being " -"tracked, that way `Counter` can track any type of value." +#: src/concurrency/threads/plain.md +msgid "\"Count in thread: {i}!\"" msgstr "" -#: src/std-types/exercise.md +#: src/concurrency/threads/plain.md +msgid "\"Main thread: {i}\"" +msgstr "" + +#: src/concurrency/threads/plain.md msgid "" -"If you finish early, try using the [`entry`](https://doc.rust-lang.org/" -"stable/std/collections/struct.HashMap.html#method.entry) method to halve the " -"number of hash lookups required to implement the `count` method." +"Spawning new threads does not automatically delay program termination at the " +"end of `main`." msgstr "" -#: src/std-types/exercise.md +#: src/concurrency/threads/plain.md +msgid "Thread panics are independent of each other." +msgstr "" + +#: src/concurrency/threads/plain.md msgid "" -"/// Counter counts the number of times each value of type T has been seen." +"Panics can carry a payload, which can be unpacked with [`Any::downcast_ref`]" +"(https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_ref)." msgstr "" -#: src/std-types/exercise.md -msgid "/// Create a new Counter." +#: src/concurrency/threads/plain.md +msgid "Run the example." msgstr "" -#: src/std-types/exercise.md -msgid "/// Count an occurrence of the given value." +#: src/concurrency/threads/plain.md +msgid "" +"5ms timing is loose enough that main and spawned threads stay mostly in " +"lockstep." msgstr "" -#: src/std-types/exercise.md -msgid "/// Return the number of times the given value has been seen." +#: src/concurrency/threads/plain.md +msgid "Notice that the program ends before the spawned thread reaches 10!" msgstr "" -#: src/std-types/exercise.md src/std-types/solution.md -msgid "\"saw {} values equal to {}\"" +#: src/concurrency/threads/plain.md +msgid "" +"This is because `main` ends the program and spawned threads do not make it " +"persist." msgstr "" -#: src/std-types/exercise.md src/std-types/solution.md -msgid "\"apple\"" +#: src/concurrency/threads/plain.md +msgid "Compare to `pthreads`/C++ `std::thread`/`boost::thread` if desired." msgstr "" -#: src/std-types/exercise.md src/std-types/solution.md -msgid "\"orange\"" +#: src/concurrency/threads/plain.md +msgid "How do we wait around for the spawned thread to complete?" msgstr "" -#: src/std-types/exercise.md src/std-types/solution.md -msgid "\"got {} apples\"" +#: src/concurrency/threads/plain.md +msgid "" +"[`thread::spawn`](https://doc.rust-lang.org/std/thread/fn.spawn.html) " +"returns a `JoinHandle`. Look at the docs." msgstr "" -#: src/std-types/solution.md +#: src/concurrency/threads/plain.md msgid "" -"/// Counter counts the number of times each value of type T has been seen.\n" +"`JoinHandle` has a [`.join()`](https://doc.rust-lang.org/std/thread/struct." +"JoinHandle.html#method.join) method that blocks." msgstr "" -#: src/std-types/solution.md -msgid "/// Create a new Counter.\n" +#: src/concurrency/threads/plain.md +msgid "" +"Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for " +"the thread to finish and have the program count all the way to 10." msgstr "" -#: src/std-types/solution.md -msgid "/// Count an occurrence of the given value.\n" +#: src/concurrency/threads/plain.md +msgid "Now what if we want to return a value?" msgstr "" -#: src/std-types/solution.md -msgid "/// Return the number of times the given value has been seen.\n" +#: src/concurrency/threads/plain.md +msgid "Look at docs again:" msgstr "" -#: src/std-traits.md -msgid "[Comparisons](./std-traits/comparisons.md) (10 minutes)" +#: src/concurrency/threads/plain.md +msgid "" +"[`thread::spawn`](https://doc.rust-lang.org/std/thread/fn.spawn.html)'s " +"closure returns `T`" msgstr "" -#: src/std-traits.md -msgid "[Operators](./std-traits/operators.md) (10 minutes)" +#: src/concurrency/threads/plain.md +msgid "" +"`JoinHandle` [`.join()`](https://doc.rust-lang.org/std/thread/struct." +"JoinHandle.html#method.join) returns `thread::Result`" msgstr "" -#: src/std-traits.md -msgid "[From and Into](./std-traits/from-and-into.md) (10 minutes)" +#: src/concurrency/threads/plain.md +msgid "" +"Use the `Result` return value from `handle.join()` to get access to the " +"returned value." msgstr "" -#: src/std-traits.md -msgid "[Casting](./std-traits/casting.md) (5 minutes)" +#: src/concurrency/threads/plain.md +msgid "Ok, what about the other case?" msgstr "" -#: src/std-traits.md -msgid "[Read and Write](./std-traits/read-and-write.md) (10 minutes)" +#: src/concurrency/threads/plain.md +msgid "Trigger a panic in the thread. Note that this doesn't panic `main`." msgstr "" -#: src/std-traits.md -msgid "[Default, struct update syntax](./std-traits/default.md) (5 minutes)" +#: src/concurrency/threads/plain.md +msgid "" +"Access the panic payload. This is a good time to talk about [`Any`](https://" +"doc.rust-lang.org/std/any/index.html)." msgstr "" -#: src/std-traits.md -msgid "[Closures](./std-traits/closures.md) (20 minutes)" +#: src/concurrency/threads/plain.md +msgid "Now we can return values from threads! What about taking inputs?" msgstr "" -#: src/std-traits.md -msgid "[Exercise: ROT13](./std-traits/exercise.md) (30 minutes)" +#: src/concurrency/threads/plain.md +msgid "Capture something by reference in the thread closure." msgstr "" -#: src/std-traits.md -msgid "This segment should take about 1 hour and 40 minutes" +#: src/concurrency/threads/plain.md +msgid "An error message indicates we must move it." msgstr "" -#: src/std-traits.md -msgid "" -"As with the standard-library types, spend time reviewing the documentation " -"for each trait." +#: src/concurrency/threads/plain.md +msgid "Move it in, see we can compute and then return a derived value." msgstr "" -#: src/std-traits.md -msgid "This section is long. Take a break midway through." +#: src/concurrency/threads/plain.md +msgid "If we want to borrow?" msgstr "" -#: src/std-traits/comparisons.md +#: src/concurrency/threads/plain.md msgid "" -"These traits support comparisons between values. All traits can be derived " -"for types containing fields that implement these traits." +"Main kills child threads when it returns, but another function would just " +"return and leave them running." msgstr "" -#: src/std-traits/comparisons.md -msgid "`PartialEq` and `Eq`" +#: src/concurrency/threads/plain.md +msgid "That would be stack use-after-return, which violates memory safety!" msgstr "" -#: src/std-traits/comparisons.md +#: src/concurrency/threads/plain.md +msgid "How do we avoid this? See next slide." +msgstr "" + +#: src/concurrency/threads/scoped.md +msgid "Normal threads cannot borrow from their environment:" +msgstr "" + +#: src/concurrency/threads/scoped.md msgid "" -"`PartialEq` is a partial equivalence relation, with required method `eq` and " -"provided method `ne`. The `==` and `!=` operators will call these methods." +"However, you can use a [scoped thread](https://doc.rust-lang.org/std/thread/" +"fn.scope.html) for this:" msgstr "" -#: src/std-traits/comparisons.md +#: src/concurrency/threads/scoped.md msgid "" -"`Eq` is a full equivalence relation (reflexive, symmetric, and transitive) " -"and implies `PartialEq`. Functions that require full equivalence will use " -"`Eq` as a trait bound." +"The reason for that is that when the `thread::scope` function completes, all " +"the threads are guaranteed to be joined, so they can return borrowed data." msgstr "" -#: src/std-traits/comparisons.md -msgid "`PartialOrd` and `Ord`" +#: src/concurrency/threads/scoped.md +msgid "" +"Normal Rust borrowing rules apply: you can either borrow mutably by one " +"thread, or immutably by any number of threads." msgstr "" -#: src/std-traits/comparisons.md +#: src/concurrency/channels.md src/concurrency/async-control-flow.md +msgid "This segment should take about 20 minutes. It contains:" +msgstr "" + +#: src/concurrency/channels/senders-receivers.md msgid "" -"`PartialOrd` defines a partial ordering, with a `partial_cmp` method. It is " -"used to implement the `<`, `<=`, `>=`, and `>` operators." +"Rust channels have two parts: a [`Sender`](https://doc.rust-lang.org/std/" +"sync/mpsc/struct.Sender.html) and a [`Receiver`](https://doc.rust-lang." +"org/std/sync/mpsc/struct.Receiver.html). The two parts are connected via the " +"channel, but you only see the end-points." msgstr "" -#: src/std-traits/comparisons.md -msgid "`Ord` is a total ordering, with `cmp` returning `Ordering`." +#: src/concurrency/channels/senders-receivers.md +msgid "\"Received: {:?}\"" msgstr "" -#: src/std-traits/comparisons.md +#: src/concurrency/channels/senders-receivers.md msgid "" -"`PartialEq` can be implemented between different types, but `Eq` cannot, " -"because it is reflexive:" +"[`mpsc`](https://doc.rust-lang.org/std/sync/mpsc/index.html) stands for " +"Multi-Producer, Single-Consumer. `Sender` and `SyncSender` implement `Clone` " +"(so you can make multiple producers) but `Receiver` does not." msgstr "" -#: src/std-traits/comparisons.md +#: src/concurrency/channels/senders-receivers.md msgid "" -"In practice, it's common to derive these traits, but uncommon to implement " -"them." +"[`send()`](https://doc.rust-lang.org/std/sync/mpsc/struct.Sender.html#method." +"send) and [`recv()`](https://doc.rust-lang.org/std/sync/mpsc/struct.Receiver." +"html#method.recv) return `Result`. If they return `Err`, it means the " +"counterpart `Sender` or `Receiver` is dropped and the channel is closed." msgstr "" -#: src/std-traits/operators.md +#: src/concurrency/channels/unbounded.md msgid "" -"Operator overloading is implemented via traits in [`std::ops`](https://doc." -"rust-lang.org/std/ops/index.html):" +"You get an unbounded and asynchronous channel with [`mpsc::channel()`]" +"(https://doc.rust-lang.org/std/sync/mpsc/fn.channel.html):" msgstr "" -#: src/std-traits/operators.md -msgid "\"{:?} + {:?} = {:?}\"" +#: src/concurrency/channels/unbounded.md src/concurrency/channels/bounded.md +msgid "\"Message {i}\"" msgstr "" -#: src/std-traits/operators.md src/memory-management/drop.md -msgid "Discussion points:" +#: src/concurrency/channels/unbounded.md src/concurrency/channels/bounded.md +msgid "\"{thread_id:?}: sent Message {i}\"" msgstr "" -#: src/std-traits/operators.md +#: src/concurrency/channels/unbounded.md src/concurrency/channels/bounded.md +msgid "\"{thread_id:?}: done\"" +msgstr "" + +#: src/concurrency/channels/unbounded.md src/concurrency/channels/bounded.md +msgid "\"Main: got {msg}\"" +msgstr "" + +#: src/concurrency/channels/unbounded.md msgid "" -"You could implement `Add` for `&Point`. In which situations is that useful?" +"An unbounded channel will allocate as much space as is necessary to store " +"pending messages. The `send()` method will not block the calling thread." msgstr "" -#: src/std-traits/operators.md +#: src/concurrency/channels/unbounded.md msgid "" -"Answer: `Add:add` consumes `self`. If type `T` for which you are overloading " -"the operator is not `Copy`, you should consider overloading the operator for " -"`&T` as well. This avoids unnecessary cloning on the call site." +"A call to `send()` will abort with an error (that is why it returns " +"`Result`) if the channel is closed. A channel is closed when the receiver is " +"dropped." msgstr "" -#: src/std-traits/operators.md +#: src/concurrency/channels/bounded.md msgid "" -"Why is `Output` an associated type? Could it be made a type parameter of the " -"method?" +"With bounded (synchronous) channels, [`send()`](https://doc.rust-lang.org/" +"std/sync/mpsc/struct.SyncSender.html#method.send) can block the current " +"thread:" msgstr "" -#: src/std-traits/operators.md +#: src/concurrency/channels/bounded.md msgid "" -"Short answer: Function type parameters are controlled by the caller, but " -"associated types (like `Output`) are controlled by the implementer of a " -"trait." +"Calling `send()` will block the current thread until there is space in the " +"channel for the new message. The thread can be blocked indefinitely if there " +"is nobody who reads from the channel." msgstr "" -#: src/std-traits/operators.md +#: src/concurrency/channels/bounded.md msgid "" -"You could implement `Add` for two different types, e.g. `impl Add<(i32, " -"i32)> for Point` would add a tuple to a `Point`." +"Like unbounded channels, a call to `send()` will abort with an error if the " +"channel is closed." msgstr "" -#: src/std-traits/from-and-into.md +#: src/concurrency/channels/bounded.md msgid "" -"Types implement [`From`](https://doc.rust-lang.org/std/convert/trait.From." -"html) and [`Into`](https://doc.rust-lang.org/std/convert/trait.Into.html) to " -"facilitate type conversions:" +"A bounded channel with a size of zero is called a \"rendezvous channel\". " +"Every send will block the current thread until another thread calls " +"[`recv()`](https://doc.rust-lang.org/std/sync/mpsc/struct.Receiver." +"html#method.recv)." msgstr "" -#: src/std-traits/from-and-into.md -msgid "\"{s}, {addr}, {one}, {bigger}\"" +#: src/concurrency/send-sync.md +msgid "Send" msgstr "" -#: src/std-traits/from-and-into.md +#: src/concurrency/send-sync.md +msgid "Sync" +msgstr "" + +#: src/concurrency/send-sync/marker-traits.md msgid "" -"[`Into`](https://doc.rust-lang.org/std/convert/trait.Into.html) is " -"automatically implemented when [`From`](https://doc.rust-lang.org/std/" -"convert/trait.From.html) is implemented:" +"How does Rust know to forbid shared access across threads? The answer is in " +"two traits:" msgstr "" -#: src/std-traits/from-and-into.md +#: src/concurrency/send-sync/marker-traits.md msgid "" -"That's why it is common to only implement `From`, as your type will get " -"`Into` implementation too." +"[`Send`](https://doc.rust-lang.org/std/marker/trait.Send.html): a type `T` " +"is `Send` if it is safe to move a `T` across a thread boundary." msgstr "" -#: src/std-traits/from-and-into.md +#: src/concurrency/send-sync/marker-traits.md msgid "" -"When declaring a function argument input type like \"anything that can be " -"converted into a `String`\", the rule is opposite, you should use `Into`. " -"Your function will accept types that implement `From` and those that _only_ " -"implement `Into`." +"[`Sync`](https://doc.rust-lang.org/std/marker/trait.Sync.html): a type `T` " +"is `Sync` if it is safe to move a `&T` across a thread boundary." msgstr "" -#: src/std-traits/casting.md +#: src/concurrency/send-sync/marker-traits.md msgid "" -"Rust has no _implicit_ type conversions, but does support explicit casts " -"with `as`. These generally follow C semantics where those are defined." +"`Send` and `Sync` are [unsafe traits](../../unsafe-rust/unsafe-traits.md). " +"The compiler will automatically derive them for your types as long as they " +"only contain `Send` and `Sync` types. You can also implement them manually " +"when you know it is valid." msgstr "" -#: src/std-traits/casting.md -msgid "\"as u16: {}\"" +#: src/concurrency/send-sync/marker-traits.md +msgid "" +"One can think of these traits as markers that the type has certain thread-" +"safety properties." msgstr "" -#: src/std-traits/casting.md -msgid "\"as i16: {}\"" +#: src/concurrency/send-sync/marker-traits.md +msgid "They can be used in the generic constraints as normal traits." msgstr "" -#: src/std-traits/casting.md -msgid "\"as u8: {}\"" +#: src/concurrency/send-sync/send.md +msgid "" +"A type `T` is [`Send`](https://doc.rust-lang.org/std/marker/trait.Send.html) " +"if it is safe to move a `T` value to another thread." msgstr "" -#: src/std-traits/casting.md +#: src/concurrency/send-sync/send.md msgid "" -"The results of `as` are _always_ defined in Rust and consistent across " -"platforms. This might not match your intuition for changing sign or casting " -"to a smaller type -- check the docs, and comment for clarity." +"The effect of moving ownership to another thread is that _destructors_ will " +"run in that thread. So the question is when you can allocate a value in one " +"thread and deallocate it in another." msgstr "" -#: src/std-traits/casting.md +#: src/concurrency/send-sync/send.md msgid "" -"Casting with `as` is a relatively sharp tool that is easy to use " -"incorrectly, and can be a source of subtle bugs as future maintenance work " -"changes the types that are used or the ranges of values in types. Casts are " -"best used only when the intent is to indicate unconditional truncation (e.g. " -"selecting the bottom 32 bits of a `u64` with `as u32`, regardless of what " -"was in the high bits)." +"As an example, a connection to the SQLite library must only be accessed from " +"a single thread." msgstr "" -#: src/std-traits/casting.md +#: src/concurrency/send-sync/sync.md msgid "" -"For infallible casts (e.g. `u32` to `u64`), prefer using `From` or `Into` " -"over `as` to confirm that the cast is in fact infallible. For fallible " -"casts, `TryFrom` and `TryInto` are available when you want to handle casts " -"that fit differently from those that don't." +"A type `T` is [`Sync`](https://doc.rust-lang.org/std/marker/trait.Sync.html) " +"if it is safe to access a `T` value from multiple threads at the same time." msgstr "" -#: src/std-traits/casting.md -msgid "Consider taking a break after this slide." +#: src/concurrency/send-sync/sync.md +msgid "More precisely, the definition is:" msgstr "" -#: src/std-traits/casting.md -msgid "" -"`as` is similar to a C++ static cast. Use of `as` in cases where data might " -"be lost is generally discouraged, or at least deserves an explanatory " -"comment." +#: src/concurrency/send-sync/sync.md +msgid "`T` is `Sync` if and only if `&T` is `Send`" msgstr "" -#: src/std-traits/casting.md -msgid "This is common in casting integers to `usize` for use as an index." +#: src/concurrency/send-sync/sync.md +msgid "" +"This statement is essentially a shorthand way of saying that if a type is " +"thread-safe for shared use, it is also thread-safe to pass references of it " +"across threads." msgstr "" -#: src/std-traits/read-and-write.md +#: src/concurrency/send-sync/sync.md msgid "" -"Using [`Read`](https://doc.rust-lang.org/std/io/trait.Read.html) and " -"[`BufRead`](https://doc.rust-lang.org/std/io/trait.BufRead.html), you can " -"abstract over `u8` sources:" +"This is because if a type is Sync it means that it can be shared across " +"multiple threads without the risk of data races or other synchronization " +"issues, so it is safe to move it to another thread. A reference to the type " +"is also safe to move to another thread, because the data it references can " +"be accessed from any thread safely." msgstr "" -#: src/std-traits/read-and-write.md -msgid "b\"foo\\nbar\\nbaz\\n\"" +#: src/concurrency/send-sync/examples.md +msgid "`Send + Sync`" msgstr "" -#: src/std-traits/read-and-write.md -msgid "\"lines in slice: {}\"" +#: src/concurrency/send-sync/examples.md +msgid "Most types you come across are `Send + Sync`:" msgstr "" -#: src/std-traits/read-and-write.md -msgid "\"lines in file: {}\"" +#: src/concurrency/send-sync/examples.md +msgid "`i8`, `f32`, `bool`, `char`, `&str`, ..." msgstr "" -#: src/std-traits/read-and-write.md -msgid "" -"Similarly, [`Write`](https://doc.rust-lang.org/std/io/trait.Write.html) lets " -"you abstract over `u8` sinks:" +#: src/concurrency/send-sync/examples.md +msgid "`(T1, T2)`, `[T; N]`, `&[T]`, `struct { x: T }`, ..." msgstr "" -#: src/std-traits/read-and-write.md -msgid "\"\\n\"" +#: src/concurrency/send-sync/examples.md +msgid "`String`, `Option`, `Vec`, `Box`, ..." msgstr "" -#: src/std-traits/read-and-write.md src/slices-and-lifetimes/str.md -msgid "\"World\"" +#: src/concurrency/send-sync/examples.md +msgid "`Arc`: Explicitly thread-safe via atomic reference count." msgstr "" -#: src/std-traits/read-and-write.md -msgid "\"Logged: {:?}\"" +#: src/concurrency/send-sync/examples.md +msgid "`Mutex`: Explicitly thread-safe via internal locking." msgstr "" -#: src/std-traits/default.md -msgid "The `Default` Trait" +#: src/concurrency/send-sync/examples.md +msgid "`mpsc::Sender`: As of 1.72.0." msgstr "" -#: src/std-traits/default.md +#: src/concurrency/send-sync/examples.md +msgid "`AtomicBool`, `AtomicU8`, ...: Uses special atomic instructions." +msgstr "" + +#: src/concurrency/send-sync/examples.md msgid "" -"[`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) trait " -"produces a default value for a type." +"The generic types are typically `Send + Sync` when the type parameters are " +"`Send + Sync`." msgstr "" -#: src/std-traits/default.md -msgid "\"John Smith\"" +#: src/concurrency/send-sync/examples.md +msgid "`Send + !Sync`" msgstr "" -#: src/std-traits/default.md -msgid "\"{default_struct:#?}\"" +#: src/concurrency/send-sync/examples.md +msgid "" +"These types can be moved to other threads, but they're not thread-safe. " +"Typically because of interior mutability:" msgstr "" -#: src/std-traits/default.md -msgid "\"Y is set!\"" +#: src/concurrency/send-sync/examples.md +msgid "`mpsc::Receiver`" msgstr "" -#: src/std-traits/default.md -msgid "\"{almost_default_struct:#?}\"" +#: src/concurrency/send-sync/examples.md +msgid "`Cell`" msgstr "" -#: src/std-traits/default.md src/slices-and-lifetimes/exercise.md -#: src/slices-and-lifetimes/solution.md -msgid "\"{:#?}\"" +#: src/concurrency/send-sync/examples.md +msgid "`RefCell`" msgstr "" -#: src/std-traits/default.md -msgid "" -"It can be implemented directly or it can be derived via `#[derive(Default)]`." +#: src/concurrency/send-sync/examples.md +msgid "`!Send + Sync`" msgstr "" -#: src/std-traits/default.md +#: src/concurrency/send-sync/examples.md msgid "" -"A derived implementation will produce a value where all fields are set to " -"their default values." +"These types are safe to access (via shared references) from multiple " +"threads, but they cannot be moved to another thread:" msgstr "" -#: src/std-traits/default.md -msgid "This means all types in the struct must implement `Default` too." +#: src/concurrency/send-sync/examples.md +msgid "" +"`MutexGuard`: Uses OS level primitives which must be deallocated on the " +"thread which created them. However, an already-locked mutex can have its " +"guarded variable read by any thread with which the guard is shared (unless " +"`T` itself is `!Sync`)." msgstr "" -#: src/std-traits/default.md -msgid "" -"Standard Rust types often implement `Default` with reasonable values (e.g. " -"`0`, `\"\"`, etc)." +#: src/concurrency/send-sync/examples.md +msgid "`!Send + !Sync`" msgstr "" -#: src/std-traits/default.md -msgid "The partial struct initialization works nicely with default." +#: src/concurrency/send-sync/examples.md +msgid "These types are not thread-safe and cannot be moved to other threads:" msgstr "" -#: src/std-traits/default.md +#: src/concurrency/send-sync/examples.md msgid "" -"The Rust standard library is aware that types can implement `Default` and " -"provides convenience methods that use it." +"`Rc`: each `Rc` has a reference to an `RcBox`, which contains a non-" +"atomic reference count." msgstr "" -#: src/std-traits/default.md +#: src/concurrency/send-sync/examples.md msgid "" -"The `..` syntax is called [struct update syntax](https://doc.rust-lang.org/" -"book/ch05-01-defining-structs.html#creating-instances-from-other-instances-" -"with-struct-update-syntax)." +"`*const T`, `*mut T`: Rust assumes raw pointers may have special concurrency " +"considerations." +msgstr "" + +#: src/concurrency/shared-state.md +msgid "Arc" msgstr "" -#: src/std-traits/closures.md +#: src/concurrency/shared-state/arc.md msgid "" -"Closures or lambda expressions have types which 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:" +"[`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) allows " +"shared, read-only ownership via `Arc::clone`:" msgstr "" -#: src/std-traits/closures.md -#, fuzzy -msgid "\"Calling function on {input}\"" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āĻĢāĻžāĻ‚āĻļāύ āĻĄāĻžāĻ•āĻž" +#: src/concurrency/shared-state/arc.md +msgid "/// A struct that prints which thread drops it.\n" +msgstr "" -#: src/std-traits/closures.md -msgid "\"add_3: {}\"" +#: src/concurrency/shared-state/arc.md +msgid "\"Dropped by {:?}\"" msgstr "" -#: src/std-traits/closures.md -msgid "\"accumulate: {}\"" +#: src/concurrency/shared-state/arc.md +msgid "// Sleep for 0-500ms.\n" msgstr "" -#: src/std-traits/closures.md -msgid "\"multiply_sum: {}\"" +#: src/concurrency/shared-state/arc.md +msgid "\"{thread_id:?}: {v:?}\"" msgstr "" -#: src/std-traits/closures.md -msgid "" -"An `Fn` (e.g. `add_3`) neither consumes nor mutates captured values, or " -"perhaps captures nothing at all. It can be called multiple times " -"concurrently." +#: src/concurrency/shared-state/arc.md +msgid "// Now only the spawned threads will hold clones of `v`.\n" msgstr "" -#: src/std-traits/closures.md +#: src/concurrency/shared-state/arc.md msgid "" -"An `FnMut` (e.g. `accumulate`) might mutate captured values. You can call it " -"multiple times, but not concurrently." +"// When the last spawned thread finishes, it will drop `v`'s contents.\n" msgstr "" -#: src/std-traits/closures.md +#: src/concurrency/shared-state/arc.md msgid "" -"If you have an `FnOnce` (e.g. `multiply_sum`), you may only call it once. It " -"might consume captured values." +"`Arc` stands for \"Atomic Reference Counted\", a thread safe version of `Rc` " +"that uses atomic operations." msgstr "" -#: src/std-traits/closures.md +#: src/concurrency/shared-state/arc.md msgid "" -"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. " -"I.e. you can use an `FnMut` wherever an `FnOnce` is called for, and you can " -"use an `Fn` wherever an `FnMut` or `FnOnce` is called for." +"`Arc` implements `Clone` whether or not `T` does. It implements `Send` " +"and `Sync` if and only if `T` implements them both." msgstr "" -#: src/std-traits/closures.md +#: src/concurrency/shared-state/arc.md msgid "" -"When you define a function that takes a closure, you should take `FnOnce` if " -"you can (i.e. you call it once), or `FnMut` else, and last `Fn`. This allows " -"the most flexibility for the caller." +"`Arc::clone()` has the cost of atomic operations that get executed, but " +"after that the use of the `T` is free." msgstr "" -#: src/std-traits/closures.md +#: src/concurrency/shared-state/arc.md msgid "" -"In contrast, when you have a closure, the most flexible you can have is `Fn` " -"(it can be passed everywhere), then `FnMut`, and lastly `FnOnce`." +"Beware of reference cycles, `Arc` does not use a garbage collector to detect " +"them." msgstr "" -#: src/std-traits/closures.md -msgid "" -"The compiler also infers `Copy` (e.g. for `add_3`) and `Clone` (e.g. " -"`multiply_sum`), depending on what the closure captures." +#: src/concurrency/shared-state/arc.md +msgid "`std::sync::Weak` can help." msgstr "" -#: src/std-traits/closures.md +#: src/concurrency/shared-state/mutex.md msgid "" -"By default, closures will capture by reference if they can. The `move` " -"keyword makes them capture by value." +"[`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) ensures " +"mutual exclusion _and_ allows mutable access to `T` behind a read-only " +"interface (another form of [interior mutability](../../borrowing/interior-" +"mutability.md)):" msgstr "" -#: src/std-traits/closures.md src/smart-pointers/trait-objects.md -msgid "\"{} {}\"" +#: src/concurrency/shared-state/mutex.md +msgid "\"v: {:?}\"" msgstr "" -#: src/std-traits/closures.md -msgid "\"Hi\"" +#: src/concurrency/shared-state/mutex.md +msgid "" +"Notice how we have a [`impl Sync for Mutex`](https://doc.rust-" +"lang.org/std/sync/struct.Mutex.html#impl-Sync-for-Mutex%3CT%3E) blanket " +"implementation." msgstr "" -#: src/std-traits/closures.md -msgid "\"Greg\"" +#: src/concurrency/shared-state/mutex.md +msgid "" +"`Mutex` in Rust looks like a collection with just one element --- the " +"protected data." msgstr "" -#: src/std-traits/exercise.md +#: src/concurrency/shared-state/mutex.md msgid "" -"In this example, you will implement the classic [\"ROT13\" cipher](https://" -"en.wikipedia.org/wiki/ROT13). Copy this code to the playground, and " -"implement the missing bits. Only rotate ASCII alphabetic characters, to " -"ensure the result is still valid UTF-8." +"It is not possible to forget to acquire the mutex before accessing the " +"protected data." msgstr "" -#: src/std-traits/exercise.md -msgid "// Implement the `Read` trait for `RotDecoder`." +#: src/concurrency/shared-state/mutex.md +msgid "" +"You can get an `&mut T` from an `&Mutex` by taking the lock. The " +"`MutexGuard` ensures that the `&mut T` doesn't outlive the lock being held." msgstr "" -#: src/std-traits/exercise.md src/std-traits/solution.md -msgid "\"Gb trg gb gur bgure fvqr!\"" +#: src/concurrency/shared-state/mutex.md +msgid "" +"`Mutex` implements both `Send` and `Sync` if and only if `T` implements " +"`Send`." msgstr "" -#: src/std-traits/exercise.md src/std-traits/solution.md -msgid "\"To get to the other side!\"" +#: src/concurrency/shared-state/mutex.md +msgid "A read-write lock counterpart: `RwLock`." msgstr "" -#: src/std-traits/exercise.md +#: src/concurrency/shared-state/mutex.md +msgid "Why does `lock()` return a `Result`?" +msgstr "" + +#: src/concurrency/shared-state/mutex.md msgid "" -"What happens if you chain two `RotDecoder` instances together, each rotating " -"by 13 characters?" +"If the thread that held the `Mutex` panicked, the `Mutex` becomes " +"\"poisoned\" to signal that the data it protected might be in an " +"inconsistent state. Calling `lock()` on a poisoned mutex fails with a " +"[`PoisonError`](https://doc.rust-lang.org/std/sync/struct.PoisonError.html). " +"You can call `into_inner()` on the error to recover the data regardless." msgstr "" -#: src/std-traits/solution.md -msgid "'A'" +#: src/concurrency/shared-state/example.md +msgid "Let us see `Arc` and `Mutex` in action:" msgstr "" -#: src/welcome-day-3.md -msgid "Welcome to Day 3" +#: src/concurrency/shared-state/example.md +msgid "// use std::sync::{Arc, Mutex};\n" msgstr "" -#: src/welcome-day-3.md -msgid "Today, we will cover:" +#: src/concurrency/shared-state/example.md +msgid "\"v: {v:?}\"" msgstr "" -#: src/welcome-day-3.md -msgid "" -"Memory management, lifetimes, and the borrow checker: how Rust ensures " -"memory safety." +#: src/concurrency/shared-state/example.md +msgid "Possible solution:" msgstr "" -#: src/welcome-day-3.md -msgid "Smart pointers: standard library pointer types." +#: src/concurrency/shared-state/example.md +msgid "Notable parts:" msgstr "" -#: src/welcome-day-3.md -msgid "[Welcome](./welcome-day-3.md) (3 minutes)" +#: src/concurrency/shared-state/example.md +msgid "" +"`v` is wrapped in both `Arc` and `Mutex`, because their concerns are " +"orthogonal." msgstr "" -#: src/welcome-day-3.md -msgid "[Memory Management](./memory-management.md) (1 hour)" +#: src/concurrency/shared-state/example.md +msgid "" +"Wrapping a `Mutex` in an `Arc` is a common pattern to share mutable state " +"between threads." msgstr "" -#: src/welcome-day-3.md -msgid "[Smart Pointers](./smart-pointers.md) (55 minutes)" +#: src/concurrency/shared-state/example.md +msgid "" +"`v: Arc<_>` needs to be cloned to make a new reference for each new spawned " +"thread. Note `move` was added to the lambda signature." msgstr "" -#: src/welcome-day-3.md +#: src/concurrency/shared-state/example.md msgid "" -"Including 10 minute breaks, this session should take about 2 hours and 20 " -"minutes" +"Blocks are introduced to narrow the scope of the `LockGuard` as much as " +"possible." msgstr "" -#: src/memory-management.md -msgid "[Review of Program Memory](./memory-management/review.md) (5 minutes)" +#: src/concurrency/sync-exercises.md src/concurrency/async-exercises.md +#: src/unsafe-deep-dive/introduction.md +msgid "This segment should take about 1 hour and 10 minutes. It contains:" msgstr "" -#: src/memory-management.md -msgid "" -"[Approaches to Memory Management](./memory-management/approaches.md) (10 " -"minutes)" +#: src/concurrency/sync-exercises/dining-philosophers.md +msgid "The dining philosophers problem is a classic problem in concurrency:" msgstr "" -#: src/memory-management.md -msgid "[Ownership](./memory-management/ownership.md) (5 minutes)" +#: src/concurrency/sync-exercises/dining-philosophers.md +msgid "" +"Five philosophers dine together at the same table. Each philosopher has " +"their own place at the table. There is a chopstick between each plate. The " +"dish served is spaghetti which requires two chopsticks to eat. Each " +"philosopher can only alternately think and eat. Moreover, a philosopher can " +"only eat their spaghetti when they have both a left and right chopstick. " +"Thus two chopsticks will only be available when their two nearest neighbors " +"are thinking, not eating. After an individual philosopher finishes eating, " +"they will put down both chopsticks." msgstr "" -#: src/memory-management.md -msgid "[Move Semantics](./memory-management/move.md) (5 minutes)" +#: src/concurrency/sync-exercises/dining-philosophers.md +msgid "" +"You will need a local [Cargo installation](../../cargo/running-locally.md) " +"for this exercise. Copy the code below to a file called `src/main.rs`, fill " +"out the blanks, and test that `cargo run` does not deadlock:" msgstr "" -#: src/memory-management.md -msgid "[Clone](./memory-management/clone.md) (2 minutes)" +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/dining-philosophers.md +msgid "" +"// left_chopstick: ...\n" +" // right_chopstick: ...\n" +" // thoughts: ...\n" msgstr "" -#: src/memory-management.md -msgid "[Copy Types](./memory-management/copy-types.md) (5 minutes)" +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/solutions.md +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "\"Eureka! {} has a new idea!\"" msgstr "" -#: src/memory-management.md -msgid "[Drop](./memory-management/drop.md) (10 minutes)" +#: src/concurrency/sync-exercises/dining-philosophers.md +msgid "// Pick up chopsticks...\n" msgstr "" -#: src/memory-management.md -msgid "[Exercise: Builder Type](./memory-management/exercise.md) (20 minutes)" +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/solutions.md +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "\"{} is eating...\"" msgstr "" -#: src/memory-management/review.md -msgid "Programs allocate memory in two ways:" +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/solutions.md +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "\"Socrates\"" msgstr "" -#: src/memory-management/review.md -msgid "Stack: Continuous area of memory for local variables." +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/solutions.md +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "\"Hypatia\"" msgstr "" -#: src/memory-management/review.md -msgid "Values have fixed sizes known at compile time." +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"Plato\"" msgstr "" -#: src/memory-management/review.md -msgid "Extremely fast: just move a stack pointer." +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"Aristotle\"" msgstr "" -#: src/memory-management/review.md -msgid "Easy to manage: follows function calls." +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"Pythagoras\"" msgstr "" -#: src/memory-management/review.md -msgid "Great memory locality." +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "// Create chopsticks\n" msgstr "" -#: src/memory-management/review.md -msgid "Heap: Storage of values outside of function calls." +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "// Create philosophers\n" msgstr "" -#: src/memory-management/review.md -msgid "Values have dynamic sizes determined at runtime." +#: src/concurrency/sync-exercises/dining-philosophers.md +msgid "// Make each of them think and eat 100 times\n" msgstr "" -#: src/memory-management/review.md -msgid "Slightly slower than the stack: some book-keeping needed." +#: src/concurrency/sync-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "// Output their thoughts\n" msgstr "" -#: src/memory-management/review.md -msgid "No guarantee of memory locality." +#: src/concurrency/sync-exercises/dining-philosophers.md +msgid "You can use the following `Cargo.toml`:" msgstr "" -#: src/memory-management/review.md +#: src/concurrency/sync-exercises/dining-philosophers.md msgid "" -"Creating a `String` puts fixed-sized metadata on the stack and dynamically " -"sized data, the actual string, on the heap:" +"```toml\n" +"[package]\n" +"name = \"dining-philosophers\"\n" +"version = \"0.1.0\"\n" +"edition = \"2024\"\n" +"```" msgstr "" -#: src/memory-management/review.md +#: src/concurrency/sync-exercises/dining-philosophers.md msgid "" -"Mention that a `String` is backed by a `Vec`, so it has a capacity and " -"length and can grow if mutable via reallocation on the heap." +"Encourage students to focus first on implementing a solution that \"mostly\" " +"works." msgstr "" -#: src/memory-management/review.md +#: src/concurrency/sync-exercises/dining-philosophers.md msgid "" -"If students ask about it, you can mention that the underlying memory is heap " -"allocated using the [System Allocator](https://doc.rust-lang.org/std/alloc/" -"struct.System.html) and custom allocators can be implemented using the " -"[Allocator API](https://doc.rust-lang.org/std/alloc/index.html)" +"The deadlock in the simplest solution is a general concurrency problem and " +"highlights that Rust does not automatically prevent this sort of bug." msgstr "" -#: src/memory-management/review.md +#: src/concurrency/sync-exercises/link-checker.md msgid "" -"We can inspect the memory layout with `unsafe` Rust. However, you should " -"point out that this is rightfully unsafe!" +"Let us use our new knowledge to create a multi-threaded link checker. It " +"should start at a webpage and check that links on the page are valid. It " +"should recursively check other pages on the same domain and keep doing this " +"until all pages have been validated." msgstr "" -#: src/memory-management/review.md src/testing/unit-tests.md -msgid "' '" +#: src/concurrency/sync-exercises/link-checker.md +msgid "" +"For this, you will need an HTTP client such as [`reqwest`](https://docs.rs/" +"reqwest/). You will also need a way to find links, we can use [`scraper`]" +"(https://docs.rs/scraper/). Finally, we'll need some way of handling errors, " +"we will use [`thiserror`](https://docs.rs/thiserror/)." msgstr "" -#: src/memory-management/review.md -msgid "\"world\"" +#: src/concurrency/sync-exercises/link-checker.md +msgid "Create a new Cargo project and `reqwest` it as a dependency with:" msgstr "" -#: src/memory-management/review.md -msgid "// DON'T DO THIS AT HOME! For educational purposes only." +#: src/concurrency/sync-exercises/link-checker.md +msgid "" +"If `cargo add` fails with `error: no such subcommand`, then please edit the " +"`Cargo.toml` file by hand. Add the dependencies listed below." msgstr "" -#: src/memory-management/review.md +#: src/concurrency/sync-exercises/link-checker.md msgid "" -"// String provides no guarantees about its layout, so this could lead to" +"The `cargo add` calls will update the `Cargo.toml` file to look like this:" msgstr "" -#: src/memory-management/review.md -#, fuzzy -msgid "// undefined behavior." -msgstr "āϰāĻžāύāϟāĻžāχāĻŽā§‡ āϕ⧋āύ āĻ…āύāĻŋāĻ°ā§āϧāĻžāϰāĻŋāϤ āφāϚāϰāĻŖ āύ⧇āχ:" - -#: src/memory-management/review.md -msgid "\"capacity = {capacity}, ptr = {ptr:#x}, len = {len}\"" +#: src/concurrency/sync-exercises/link-checker.md +msgid "" +"```toml\n" +"[package]\n" +"name = \"link-checker\"\n" +"version = \"0.1.0\"\n" +"edition = \"2024\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"reqwest = { version = \"0.13.1\", features = [\"blocking\"] }\n" +"scraper = \"0.25.0\"\n" +"thiserror = \"2.0.18\"\n" +"```" msgstr "" -#: src/memory-management/approaches.md -msgid "Traditionally, languages have fallen into two broad categories:" +#: src/concurrency/sync-exercises/link-checker.md +msgid "" +"You can now download the start page. Try with a small site such as `https://" +"www.google.org/`." msgstr "" -#: src/memory-management/approaches.md -msgid "Full control via manual memory management: C, C++, Pascal, ..." +#: src/concurrency/sync-exercises/link-checker.md +msgid "Your `src/main.rs` file should look something like this:" msgstr "" -#: src/memory-management/approaches.md -msgid "Programmer decides when to allocate or free heap memory." +#: src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"request error: {0}\"" msgstr "" -#: src/memory-management/approaches.md -msgid "" -"Programmer must determine whether a pointer still points to valid memory." +#: src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"bad http response: {0}\"" msgstr "" -#: src/memory-management/approaches.md -msgid "Studies show, programmers make mistakes." +#: src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"Checking {:#}\"" msgstr "" -#: src/memory-management/approaches.md -msgid "" -"Full safety via automatic memory management at runtime: Java, Python, Go, " -"Haskell, ..." +#: src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"href\"" msgstr "" -#: src/memory-management/approaches.md -msgid "" -"A runtime system ensures that memory is not freed until it can no longer be " -"referenced." +#: src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"On {base_url:#}: ignored unparsable {href:?}: {err}\"" msgstr "" -#: src/memory-management/approaches.md -msgid "" -"Typically implemented with reference counting, garbage collection, or RAII." +#: src/concurrency/sync-exercises/link-checker.md +#: src/concurrency/sync-exercises/solutions.md +msgid "\"https://www.google.org\"" msgstr "" -#: src/memory-management/approaches.md -msgid "Rust offers a new mix:" +#: src/concurrency/sync-exercises/link-checker.md +msgid "\"Links: {links:#?}\"" msgstr "" -#: src/memory-management/approaches.md -msgid "" -"Full control _and_ safety via compile time enforcement of correct memory " -"management." +#: src/concurrency/sync-exercises/link-checker.md +msgid "\"Could not extract links: {err:#}\"" msgstr "" -#: src/memory-management/approaches.md -msgid "It does this with an explicit ownership concept." +#: src/concurrency/sync-exercises/link-checker.md +msgid "Run the code in `src/main.rs` with" msgstr "" -#: src/memory-management/approaches.md +#: src/concurrency/sync-exercises/link-checker.md msgid "" -"This slide is intended to help students coming from other languages to put " -"Rust in context." +"Use threads to check the links in parallel: send the URLs to be checked to a " +"channel and let a few threads check the URLs in parallel." msgstr "" -#: src/memory-management/approaches.md +#: src/concurrency/sync-exercises/link-checker.md msgid "" -"C must manage heap manually with `malloc` and `free`. Common errors include " -"forgetting to call `free`, calling it multiple times for the same pointer, " -"or dereferencing a pointer after the memory it points to has been freed." +"Extend this to recursively extract links from all pages on the `www.google." +"org` domain. Put an upper limit of 100 pages or so so that you don't end up " +"being blocked by the site." msgstr "" -#: src/memory-management/approaches.md +#: src/concurrency/sync-exercises/link-checker.md msgid "" -"C++ has tools like smart pointers (`unique_ptr`, `shared_ptr`) that take " -"advantage of language guarantees about calling destructors to ensure memory " -"is freed when a function returns. It is still quite easy to mis-use these " -"tools and create similar bugs to C." +"This is a complex exercise and intended to give students an opportunity to " +"work on a larger project than others. A success condition for this exercise " +"is to get stuck on some \"real\" issue and work through it with the support " +"of other students or the instructor." msgstr "" -#: src/memory-management/approaches.md -msgid "" -"Java, Go, and Python rely on the garbage collector to identify memory that " -"is no longer reachable and discard it. This guarantees that any pointer can " -"be dereferenced, eliminating use-after-free and other classes of bugs. But, " -"GC has a runtime cost and is difficult to tune properly." +#: src/concurrency/sync-exercises/solutions.md +msgid "\"{} is trying to eat\"" msgstr "" -#: src/memory-management/approaches.md +#: src/concurrency/sync-exercises/solutions.md msgid "" -"Rust's ownership and borrowing model can, in many cases, get the performance " -"of C, with alloc and free operations precisely where they are required -- " -"zero cost. It also provides tools similar to C++'s smart pointers. When " -"required, other options such as reference counting are available, and there " -"are even third-party crates available to support runtime garbage collection " -"(not covered in this class)." +"// To avoid a deadlock, we have to break the symmetry\n" +" // somewhere. This will swap the chopsticks without deinitializing\n" +" // either of them.\n" msgstr "" -#: src/memory-management/ownership.md -msgid "" -"All variable bindings have a _scope_ where they are valid and it is an error " -"to use a variable outside its scope:" +#: src/concurrency/sync-exercises/solutions.md +msgid "\"{thought}\"" msgstr "" -#: src/memory-management/ownership.md -msgid "" -"We say that the variable _owns_ the value. Every Rust value has precisely " -"one owner at all times." +#: src/concurrency/sync-exercises/solutions.md +msgid "Link Checker" msgstr "" -#: src/memory-management/ownership.md +#: src/concurrency/sync-exercises/solutions.md msgid "" -"At the end of the scope, the variable is _dropped_ and the data is freed. A " -"destructor can run here to free up resources." +"/// Determine whether links within the given page should be extracted.\n" msgstr "" -#: src/memory-management/ownership.md +#: src/concurrency/sync-exercises/solutions.md msgid "" -"Students familiar with garbage-collection implementations will know that a " -"garbage collector starts with a set of \"roots\" to find all reachable " -"memory. Rust's \"single owner\" principle is a similar idea." +"/// Mark the given page as visited, returning false if it had already\n" +" /// been visited.\n" msgstr "" -#: src/memory-management/move.md -msgid "An assignment will transfer _ownership_ between variables:" +#: src/concurrency/sync-exercises/solutions.md +msgid "// To multiplex the non-cloneable Receiver, wrap it in Arc>.\n" msgstr "" -#: src/memory-management/move.md -#, fuzzy -msgid "\"Hello!\"" -msgstr "Hello World!" - -#: src/memory-management/move.md src/slices-and-lifetimes/str.md -msgid "\"s2: {s2}\"" +#: src/concurrency/sync-exercises/solutions.md +msgid "// The sender got dropped. No more commands coming in.\n" msgstr "" -#: src/memory-management/move.md -msgid "// println!(\"s1: {s1}\");" +#: src/concurrency/sync-exercises/solutions.md +msgid "\"Got crawling error: {:#}\"" msgstr "" -#: src/memory-management/move.md -msgid "The assignment of `s1` to `s2` transfers ownership." +#: src/concurrency/sync-exercises/solutions.md +msgid "\"Bad URLs: {:#?}\"" msgstr "" -#: src/memory-management/move.md -msgid "When `s1` goes out of scope, nothing happens: it does not own anything." +#: src/concurrency/welcome-async.md +msgid "" +"\"Async\" is a concurrency model where multiple tasks are executed " +"concurrently by executing each task until it would block, then switching to " +"another task that is ready to make progress. The model allows running a " +"larger number of tasks on a limited number of threads. This is because the " +"per-task overhead is typically very low and operating systems provide " +"primitives for efficiently identifying I/O that is able to proceed." msgstr "" -#: src/memory-management/move.md -msgid "When `s2` goes out of scope, the string data is freed." +#: src/concurrency/welcome-async.md +msgid "" +"Rust's asynchronous operation is based on \"futures\", which represent work " +"that may be completed in the future. Futures are \"polled\" until they " +"signal that they are complete." msgstr "" -#: src/memory-management/move.md -msgid "Before move to `s2`:" +#: src/concurrency/welcome-async.md +msgid "" +"Futures are polled by an async runtime, and several different runtimes are " +"available." msgstr "" -#: src/memory-management/move.md -msgid "After move to `s2`:" +#: src/concurrency/welcome-async.md +msgid "" +"Python has a similar model in its `asyncio`. However, its `Future` type is " +"callback-based, and not polled. Async Python programs require a \"loop\", " +"similar to a runtime in Rust." msgstr "" -#: src/memory-management/move.md +#: src/concurrency/welcome-async.md msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 \"(inaccessible)\" : : :\n" -": +-----------+-------+ : : +----+----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" -": | len | 4 | : | : +----+----+----+----+ :\n" -": | capacity | 4 | : | : :\n" -": +-----------+-------+ : | : :\n" -": : | `- - - - - - - - - - - - - -'\n" -": s2 : |\n" -": +-----------+-------+ : |\n" -": | ptr | o---+---+--'\n" -": | len | 4 | :\n" -": | capacity | 4 | :\n" -": +-----------+-------+ :\n" -": :\n" -"`- - - - - - - - - - - - - -'\n" -"```" +"JavaScript's `Promise` is similar, but again callback-based. The language " +"runtime implements the event loop, so the majority of the details of Promise " +"resolution are hidden." msgstr "" -#: src/memory-management/move.md +#: src/concurrency/welcome-async.md msgid "" -"When you pass a value to a function, the value is assigned to the function " -"parameter. This transfers ownership:" +"Including 10 minute breaks, this session should take about 3 hours and 30 " +"minutes. It contains:" msgstr "" -#: src/memory-management/move.md -msgid "\"Hello {name}\"" +#: src/concurrency/async.md +msgid "async/await" msgstr "" -#: src/memory-management/move.md src/android/interoperability/java.md -#, fuzzy -msgid "\"Alice\"" -msgstr "Slices" +#: src/concurrency/async/async-await.md +msgid "" +"At a high level, async Rust code looks very much like \"normal\" sequential " +"code:" +msgstr "" -#: src/memory-management/move.md -msgid "// say_hello(name);" +#: src/concurrency/async/async-await.md +msgid "\"Count is: {i}!\"" +msgstr "" + +#: src/concurrency/async/async-await.md +msgid "" +"Note that this is a simplified example to show the syntax. There is no long " +"running operation or any real concurrency in it!" msgstr "" -#: src/memory-management/move.md +#: src/concurrency/async/async-await.md msgid "" -"Mention that this is the opposite of the defaults in C++, which copies by " -"value unless you use `std::move` (and the move constructor is defined!)." +"The \"async\" keyword is syntactic sugar. The compiler replaces the return " +"type with a future." msgstr "" -#: src/memory-management/move.md +#: src/concurrency/async/async-await.md msgid "" -"It is only the ownership that moves. Whether any machine code is generated " -"to manipulate the data itself is a matter of optimization, and such copies " -"are aggressively optimized away." +"You cannot make `main` async, without additional instructions to the " +"compiler on how to use the returned future." msgstr "" -#: src/memory-management/move.md +#: src/concurrency/async/async-await.md msgid "" -"Simple values (such as integers) can be marked `Copy` (see later slides)." +"You need an executor to run async code. `block_on` blocks the current thread " +"until the provided future has run to completion." msgstr "" -#: src/memory-management/move.md -msgid "In Rust, clones are explicit (by using `clone`)." +#: src/concurrency/async/async-await.md +msgid "" +"`.await` asynchronously waits for the completion of another operation. " +"Unlike `block_on`, `.await` doesn't block the current thread." msgstr "" -#: src/memory-management/move.md -msgid "In the `say_hello` example:" +#: src/concurrency/async/async-await.md +msgid "" +"`.await` can only be used inside an `async` function (or block; these are " +"introduced later)." msgstr "" -#: src/memory-management/move.md +#: src/concurrency/async/futures.md msgid "" -"With the first call to `say_hello`, `main` gives up ownership of `name`. " -"Afterwards, `name` cannot be used anymore within `main`." +"[`Future`](https://doc.rust-lang.org/std/future/trait.Future.html) is a " +"trait, implemented by objects that represent an operation that may not be " +"complete yet. A future can be polled, and `poll` returns a [`Poll`](https://" +"doc.rust-lang.org/std/task/enum.Poll.html)." msgstr "" -#: src/memory-management/move.md +#: src/concurrency/async/futures.md msgid "" -"The heap memory allocated for `name` will be freed at the end of the " -"`say_hello` function." +"An async function returns an `impl Future`. It's also possible (but " +"uncommon) to implement `Future` for your own types. For example, the " +"`JoinHandle` returned from `tokio::spawn` implements `Future` to allow " +"joining to it." msgstr "" -#: src/memory-management/move.md +#: src/concurrency/async/futures.md msgid "" -"`main` can retain ownership if it passes `name` as a reference (`&name`) and " -"if `say_hello` accepts a reference as a parameter." +"The `.await` keyword, applied to a Future, causes the current async function " +"to pause until that Future is ready, and then evaluates to its output." msgstr "" -#: src/memory-management/move.md +#: src/concurrency/async/futures.md msgid "" -"Alternatively, `main` can pass a clone of `name` in the first call (`name." -"clone()`)." +"The `Future` and `Poll` types are implemented exactly as shown; click the " +"links to show the implementations in the docs." msgstr "" -#: src/memory-management/move.md +#: src/concurrency/async/futures.md msgid "" -"Rust makes it harder than C++ to inadvertently create copies by making move " -"semantics the default, and by forcing programmers to make clones explicit." +"`Context` allows a Future to schedule itself to be polled again when an " +"event such as a timeout occurs." msgstr "" -#: src/memory-management/move.md -#, fuzzy -msgid "Defensive Copies in Modern C++" -msgstr "āφāϧ⧁āύāĻŋāĻ• C++ āĻ āĻĄāĻŦāϞ āĻŽā§āĻ•ā§āϤ" - -#: src/memory-management/move.md -msgid "Modern C++ solves this differently:" +#: src/concurrency/async/futures.md +msgid "" +"`Pin` ensures that the Future isn't moved in memory, so that pointers into " +"that future remain valid. This is required to allow references to remain " +"valid after an `.await`. We will address `Pin` in the \"Pitfalls\" segment." msgstr "" -#: src/memory-management/move.md -msgid "\"Cpp\"" +#: src/concurrency/async/state-machine.md +msgid "" +"Rust transforms an async function or block to a hidden type that implements " +"`Future`, using a state machine to track the function's progress. The " +"details of this transform are complex, but it is beneficial to have a " +"schematic understanding of what is happening. The following function" msgstr "" -#: src/memory-management/move.md -msgid "// Duplicate the data in s1." +#: src/concurrency/async/state-machine.md +msgid "/// Sum two D10 rolls plus a modifier.\n" msgstr "" -#: src/memory-management/move.md -msgid "" -"The heap data from `s1` is duplicated and `s2` gets its own independent copy." +#: src/concurrency/async/state-machine.md +msgid "is transformed to something like" msgstr "" -#: src/memory-management/move.md -msgid "When `s1` and `s2` go out of scope, they each free their own memory." +#: src/concurrency/async/state-machine.md +msgid "// Function has not begun yet.\n" msgstr "" -#: src/memory-management/move.md -msgid "Before copy-assignment:" +#: src/concurrency/async/state-machine.md +msgid "// Waiting for first `.await` to complete.\n" msgstr "" -#: src/memory-management/move.md -msgid "After copy-assignment:" +#: src/concurrency/async/state-machine.md +msgid "// Waiting for second `.await` to complete.\n" msgstr "" -#: src/memory-management/move.md -msgid "" -"C++ has made a slightly different choice than Rust. Because `=` copies data, " -"the string data has to be cloned. Otherwise we would get a double-free when " -"either string goes out of scope." +#: src/concurrency/async/state-machine.md +msgid "// Create future for first dice roll.\n" msgstr "" -#: src/memory-management/move.md -msgid "" -"C++ also has [`std::move`](https://en.cppreference.com/w/cpp/utility/move), " -"which is used to indicate when a value may be moved from. If the example had " -"been `s2 = std::move(s1)`, no heap allocation would take place. After the " -"move, `s1` would be in a valid but unspecified state. Unlike Rust, the " -"programmer is allowed to keep using `s1`." +#: src/concurrency/async/state-machine.md +msgid "// Poll sub-future for first dice roll.\n" msgstr "" -#: src/memory-management/move.md -msgid "" -"Unlike Rust, `=` in C++ can run arbitrary code as determined by the type " -"which is being copied or moved." +#: src/concurrency/async/state-machine.md +msgid "// Create future for second roll.\n" msgstr "" -#: src/memory-management/clone.md -msgid "Clone" +#: src/concurrency/async/state-machine.md +msgid "// Poll sub-future for second dice roll.\n" msgstr "" -#: src/memory-management/clone.md +#: src/concurrency/async/state-machine.md msgid "" -"Sometimes you _want_ to make a copy of a value. The `Clone` trait " -"accomplishes this." +"This example is illustrative, and isn't an accurate representation of the " +"Rust compiler's transformation. The important things to notice here are:" msgstr "" -#: src/memory-management/clone.md +#: src/concurrency/async/state-machine.md msgid "" -"The idea of `Clone` is to make it easy to spot where heap allocations are " -"occurring. Look for `.clone()` and a few others like `Vec::new` or `Box::" -"new`." +"Calling an async function does nothing but construct and return a future." msgstr "" -#: src/memory-management/clone.md +#: src/concurrency/async/state-machine.md msgid "" -"It's common to \"clone your way out\" of problems with the borrow checker, " -"and return later to try to optimize those clones away." +"All local variables are stored in the function's future, using an enum to " +"identify where execution is currently suspended." msgstr "" -#: src/memory-management/copy-types.md +#: src/concurrency/async/state-machine.md msgid "" -"While move semantics are the default, certain types are copied by default:" +"An `.await` in the async function is translated into an a new state " +"containing all live variables and the awaited future. The `loop` then " +"handles that updated state, polling the future until it returns `Poll::" +"Ready`." msgstr "" -#: src/memory-management/copy-types.md -msgid "These types implement the `Copy` trait." +#: src/concurrency/async/state-machine.md +msgid "" +"Execution continues eagerly until a `Poll::Pending` occurs. In this simple " +"example, every future is ready immediately." msgstr "" -#: src/memory-management/copy-types.md -msgid "You can opt-in your own types to use copy semantics:" +#: src/concurrency/async/state-machine.md +msgid "" +"`main` contains a naïve executor, which just busy-loops until the future is " +"ready. We will discuss real executors shortly." msgstr "" -#: src/memory-management/copy-types.md -msgid "After the assignment, both `p1` and `p2` own their own data." +#: src/concurrency/async/state-machine.md +msgid "" +"Imagine the `Future` data structure for a deeply nested stack of async " +"functions. Each function's `Future` contains the `Future` structures for the " +"functions it calls. This can result in unexpectedly large compiler-generated " +"`Future` types." msgstr "" -#: src/memory-management/copy-types.md -msgid "We can also use `p1.clone()` to explicitly copy the data." +#: src/concurrency/async/state-machine.md +msgid "" +"This also means that recursive async functions are challenging. Compare to " +"the common error of building recursive type, such as" msgstr "" -#: src/memory-management/copy-types.md -msgid "Copying and cloning are not the same thing:" +#: src/concurrency/async/state-machine.md +msgid "" +"The fix for a recursive type is to add a layer of indrection, such as with " +"`Box`. Similarly, a recursive async function must box the recursive future:" msgstr "" -#: src/memory-management/copy-types.md -msgid "" -"Copying refers to bitwise copies of memory regions and does not work on " -"arbitrary objects." +#: src/concurrency/async/state-machine.md +msgid "\"{n}\"" msgstr "" -#: src/memory-management/copy-types.md +#: src/concurrency/async/runtimes.md msgid "" -"Copying does not allow for custom logic (unlike copy constructors in C++)." +"A _runtime_ provides support for performing operations asynchronously (a " +"_reactor_) and is responsible for executing futures (an _executor_). Rust " +"does not have a \"built-in\" runtime, but several options are available:" msgstr "" -#: src/memory-management/copy-types.md +#: src/concurrency/async/runtimes.md msgid "" -"Cloning is a more general operation and also allows for custom behavior by " -"implementing the `Clone` trait." +"[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." msgstr "" -#: src/memory-management/copy-types.md -msgid "Copying does not work on types that implement the `Drop` trait." +#: src/concurrency/async/runtimes.md +msgid "[smol](https://docs.rs/smol/latest/smol/): simple and lightweight" msgstr "" -#: src/memory-management/copy-types.md -msgid "In the above example, try the following:" +#: src/concurrency/async/runtimes.md +msgid "" +"Several larger applications have their own runtimes. For example, [Fuchsia]" +"(https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/lib/fuchsia-" +"async/src/lib.rs) already has one." msgstr "" -#: src/memory-management/copy-types.md +#: src/concurrency/async/runtimes.md msgid "" -"Add a `String` field to `struct Point`. It will not compile because `String` " -"is not a `Copy` type." +"Note that of the listed runtimes, only Tokio is supported in the Rust " +"playground. The playground also does not permit any I/O, so most interesting " +"async things can't run in the playground." msgstr "" -#: src/memory-management/copy-types.md +#: src/concurrency/async/runtimes.md msgid "" -"Remove `Copy` from the `derive` attribute. The compiler error is now in the " -"`println!` for `p1`." +"Futures are \"inert\" in that they do not do anything (not even start an I/O " +"operation) unless there is an executor polling them. This differs from JS " +"Promises, for example, which will run to completion even if they are never " +"used." msgstr "" -#: src/memory-management/copy-types.md -msgid "Show that it works if you clone `p1` instead." +#: src/concurrency/async/runtimes/tokio.md +msgid "Tokio provides:" msgstr "" -#: src/memory-management/drop.md -msgid "The `Drop` Trait" +#: src/concurrency/async/runtimes/tokio.md +msgid "A multi-threaded runtime for executing asynchronous code." msgstr "" -#: src/memory-management/drop.md -msgid "" -"Values which implement [`Drop`](https://doc.rust-lang.org/std/ops/trait.Drop." -"html) can specify code to run when they go out of scope:" +#: src/concurrency/async/runtimes/tokio.md +msgid "An asynchronous version of the standard library." msgstr "" -#: src/memory-management/drop.md -msgid "\"Dropping {}\"" +#: src/concurrency/async/runtimes/tokio.md +msgid "A large ecosystem of libraries." msgstr "" -#: src/memory-management/drop.md src/exercises/concurrency/link-checker.md -#: src/exercises/concurrency/solutions-morning.md -msgid "\"a\"" +#: src/concurrency/async/runtimes/tokio.md +msgid "\"Count in task: {i}!\"" msgstr "" -#: src/memory-management/drop.md src/testing/googletest.md -msgid "\"b\"" +#: src/concurrency/async/runtimes/tokio.md +msgid "\"Main task: {i}\"" msgstr "" -#: src/memory-management/drop.md -msgid "\"c\"" +#: src/concurrency/async/runtimes/tokio.md +msgid "With the `tokio::main` macro we can now make `main` async." msgstr "" -#: src/memory-management/drop.md -msgid "\"d\"" +#: src/concurrency/async/runtimes/tokio.md +msgid "The `spawn` function creates a new, concurrent \"task\"." msgstr "" -#: src/memory-management/drop.md -msgid "\"Exiting block B\"" +#: src/concurrency/async/runtimes/tokio.md +msgid "Note: `spawn` takes a `Future`, you don't call `.await` on `count_to`." msgstr "" -#: src/memory-management/drop.md -msgid "\"Exiting block A\"" +#: src/concurrency/async/runtimes/tokio.md +msgid "**Further exploration:**" msgstr "" -#: src/memory-management/drop.md -msgid "\"Exiting main\"" +#: src/concurrency/async/runtimes/tokio.md +msgid "" +"Why does `count_to` not get to 10? This is an example of async cancellation. " +"`tokio::spawn` returns a handle which can be awaited to wait until it " +"finishes." msgstr "" -#: src/memory-management/drop.md -msgid "Note that `std::mem::drop` is not the same as `std::ops::Drop::drop`." +#: src/concurrency/async/runtimes/tokio.md +msgid "Try `count_to(10).await` instead of spawning." msgstr "" -#: src/memory-management/drop.md -msgid "Values are automatically dropped when they go out of scope." +#: src/concurrency/async/runtimes/tokio.md +msgid "Try awaiting the task returned from `tokio::spawn`." msgstr "" -#: src/memory-management/drop.md -msgid "" -"When a value is dropped, if it implements `std::ops::Drop` then its `Drop::" -"drop` implementation will be called." +#: src/concurrency/async/tasks.md +msgid "Rust has a task system, which is a form of lightweight threading." msgstr "" -#: src/memory-management/drop.md +#: src/concurrency/async/tasks.md msgid "" -"All its fields will then be dropped too, whether or not it implements `Drop`." +"A task has a single top-level future which the executor polls to make " +"progress. That future may have one or more nested futures that its `poll` " +"method polls, corresponding loosely to a call stack. Concurrency within a " +"task is possible by polling multiple child futures, such as racing a timer " +"and an I/O operation." msgstr "" -#: src/memory-management/drop.md -msgid "" -"`std::mem::drop` is just an empty function that takes any value. The " -"significance is that it takes ownership of the value, so at the end of its " -"scope it gets dropped. This makes it a convenient way to explicitly drop " -"values earlier than they would otherwise go out of scope." +#: src/concurrency/async/tasks.md +msgid "\"127.0.0.1:0\"" msgstr "" -#: src/memory-management/drop.md -msgid "" -"This can be useful for objects that do some work on `drop`: releasing locks, " -"closing files, etc." +#: src/concurrency/async/tasks.md +msgid "\"listening on port {}\"" msgstr "" -#: src/memory-management/drop.md -msgid "Why doesn't `Drop::drop` take `self`?" +#: src/concurrency/async/tasks.md +msgid "\"connection from {addr:?}\"" msgstr "" -#: src/memory-management/drop.md -msgid "" -"Short-answer: If it did, `std::mem::drop` would be called at the end of the " -"block, resulting in another call to `Drop::drop`, and a stack overflow!" +#: src/concurrency/async/tasks.md +msgid "b\"Who are you?\\n\"" msgstr "" -#: src/memory-management/drop.md -msgid "Try replacing `drop(a)` with `a.drop()`." +#: src/concurrency/async/tasks.md +msgid "\"socket error\"" msgstr "" -#: src/memory-management/exercise.md +#: src/concurrency/async/tasks.md +msgid "\"Thanks for dialing in, {name}!\\n\"" +msgstr "" + +#: src/concurrency/async/tasks.md src/concurrency/async-control-flow/join.md msgid "" -"In this example, we will implement a complex data type that owns all of its " -"data. We will use the \"builder pattern\" to support building a new value " -"piece-by-piece, using convenience functions." +"Copy this example into your prepared `src/main.rs` and run it from there." msgstr "" -#: src/memory-management/exercise.md -msgid "Fill in the missing pieces." +#: src/concurrency/async/tasks.md +msgid "" +"Try connecting to it with a TCP connection tool like [nc](https://www.unix." +"com/man-page/linux/1/nc/) or [telnet](https://www.unix.com/man-page/linux/1/" +"telnet/)." msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "/// A representation of a software package.\n" +#: src/concurrency/async/tasks.md +msgid "" +"Ask students to visualize what the state of the example server would be with " +"a few connected clients. What tasks exist? What are their Futures?" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md +#: src/concurrency/async/tasks.md msgid "" -"/// Return a representation of this package as a dependency, for use in\n" -" /// building other packages.\n" +"This is the first time we've seen an `async` block. This is similar to a " +"closure, but does not take any arguments. Its return value is a Future, " +"similar to an `async fn`." msgstr "" -#: src/memory-management/exercise.md -msgid "\"1\"" +#: src/concurrency/async/tasks.md +msgid "" +"Refactor the async block into a function, and improve the error handling " +"using `?`." msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md +#: src/concurrency/async-control-flow/channels.md msgid "" -"/// A builder for a Package. Use `build()` to create the `Package` itself.\n" +"Several crates have support for asynchronous channels. For instance `tokio`:" msgstr "" -#: src/memory-management/exercise.md -msgid "\"2\"" +#: src/concurrency/async-control-flow/channels.md +msgid "\"Received {count} pings so far.\"" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "/// Set the package version.\n" +#: src/concurrency/async-control-flow/channels.md +msgid "\"ping_handler complete\"" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "/// Set the package authors.\n" +#: src/concurrency/async-control-flow/channels.md +msgid "\"Failed to send ping.\"" msgstr "" -#: src/memory-management/exercise.md -msgid "\"3\"" +#: src/concurrency/async-control-flow/channels.md +msgid "\"Sent {} pings so far.\"" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "/// Add an additional dependency.\n" +#: src/concurrency/async-control-flow/channels.md +msgid "\"Something went wrong in ping handler task.\"" msgstr "" -#: src/memory-management/exercise.md -msgid "\"4\"" +#: src/concurrency/async-control-flow/channels.md +msgid "Change the channel size to `3` and see how it affects the execution." msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "/// Set the language. If not set, language defaults to None.\n" +#: src/concurrency/async-control-flow/channels.md +msgid "" +"Overall, the interface is similar to the `sync` channels as seen in the " +"[morning class](../channels.md)." msgstr "" -#: src/memory-management/exercise.md -msgid "\"5\"" +#: src/concurrency/async-control-flow/channels.md +msgid "Try removing the `std::mem::drop` call. What happens? Why?" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"base64\"" +#: src/concurrency/async-control-flow/channels.md +msgid "" +"The [Flume](https://docs.rs/flume/latest/flume/) crate has channels that " +"implement both `sync` and `async` `send` and `recv`. This can be convenient " +"for complex applications with both IO and heavy CPU processing tasks." msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"0.13\"" +#: src/concurrency/async-control-flow/channels.md +msgid "" +"What makes working with `async` channels preferable is the ability to " +"combine them with other `future`s to combine them and create complex control " +"flow." msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"base64: {base64:?}\"" +#: src/concurrency/async-control-flow/join.md +msgid "" +"A join operation waits until all of a set of futures are ready, and returns " +"a collection of their results. This is similar to `Promise.all` in " +"JavaScript or `asyncio.gather` in Python." msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"log\"" +#: src/concurrency/async-control-flow/join.md +msgid "\"https://google.com\"" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"0.4\"" +#: src/concurrency/async-control-flow/join.md +msgid "\"https://httpbin.org/ip\"" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"log: {log:?}\"" +#: src/concurrency/async-control-flow/join.md +msgid "\"https://play.rust-lang.org/\"" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"serde\"" +#: src/concurrency/async-control-flow/join.md +msgid "\"BAD_URL\"" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"djmitche\"" +#: src/concurrency/async-control-flow/join.md +msgid "\"{page_sizes_dict:?}\"" msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"4.0\"" +#: src/concurrency/async-control-flow/join.md +msgid "" +"For multiple futures of disjoint types, you can use `std::future::join!` but " +"you must know how many futures you will have at compile time. This is " +"currently in the `futures` crate, soon to be stabilised in `std::future`." msgstr "" -#: src/memory-management/exercise.md src/memory-management/solution.md -msgid "\"serde: {serde:?}\"" +#: src/concurrency/async-control-flow/join.md +msgid "" +"The risk of `join` is that one of the futures may never resolve, this would " +"cause your program to stall." msgstr "" -#: src/memory-management/solution.md -msgid "\"0.1\"" +#: src/concurrency/async-control-flow/join.md +msgid "" +"You can also combine `join_all` with `join!` for instance to join all " +"requests to an http service as well as a database query. Try adding a " +"`tokio::time::sleep` to the future, using `futures::join!`. This is not a " +"timeout (that requires `select!`, explained in the next chapter), but " +"demonstrates `join!`." msgstr "" -#: src/smart-pointers.md -msgid "[Box" +#: src/concurrency/async-control-flow/select.md +msgid "" +"A select operation waits until any of a set of futures is ready, and " +"responds to that future's result. In JavaScript, this is similar to `Promise." +"race`. In Python, it compares to `asyncio.wait(task_set, return_when=asyncio." +"FIRST_COMPLETED)`." msgstr "" -#: src/smart-pointers.md -msgid "](./smart-pointers/box.md) (10 minutes)" +#: src/concurrency/async-control-flow/select.md +msgid "" +"Similar to a match statement, the body of `select!` has a number of arms, " +"each of the form `pattern = future => statement`. When a `future` is ready, " +"its return value is destructured by the `pattern`. The `statement` is then " +"run with the resulting variables. The `statement` result becomes the result " +"of the `select!` macro." msgstr "" -#: src/smart-pointers.md -msgid "[Rc](./smart-pointers/rc.md) (5 minutes)" +#: src/concurrency/async-control-flow/select.md +msgid "\"got: {msg}\"" msgstr "" -#: src/smart-pointers.md -msgid "[Trait Objects](./smart-pointers/trait-objects.md) (10 minutes)" +#: src/concurrency/async-control-flow/select.md +msgid "\"timeout\"" msgstr "" -#: src/smart-pointers.md -msgid "[Exercise: Binary Tree](./smart-pointers/exercise.md) (30 minutes)" +#: src/concurrency/async-control-flow/select.md +msgid "\"Failed to send greeting\"" msgstr "" -#: src/smart-pointers.md src/error-handling.md -msgid "This segment should take about 55 minutes" +#: src/concurrency/async-control-flow/select.md +msgid "\"Listener failed\"" msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-control-flow/select.md msgid "" -"[`Box`](https://doc.rust-lang.org/std/boxed/struct.Box.html) is an owned " -"pointer to data on the heap:" +"The `listener` async block here is a common form: wait for some async event, " +"or for a timeout. Change the `sleep` to sleep longer to see it fail. Why " +"does the `send` also fail in this situation?" msgstr "" -#: src/smart-pointers/box.md -msgid "\"five: {}\"" +#: src/concurrency/async-control-flow/select.md +msgid "" +"`select!` is also frequently used in a loop in \"actor\" architectures, " +"where a task reacts to events in a loop. That has some pitfalls, which will " +"be discussed in the next segment." msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-pitfalls.md msgid "" -"`Box` implements `Deref`, which means that you can [call " -"methods from `T` directly on a `Box`](https://doc.rust-lang.org/std/ops/" -"trait.Deref.html#more-on-deref-coercion)." +"Async / await provides convenient and efficient abstraction for concurrent " +"asynchronous programming. However, the async/await model in Rust also comes " +"with its share of pitfalls and footguns. We illustrate some of them in this " +"chapter." msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-pitfalls.md +msgid "Pin" +msgstr "" + +#: src/concurrency/async-pitfalls/blocking-executor.md +msgid "Blocking the executor" +msgstr "" + +#: src/concurrency/async-pitfalls/blocking-executor.md msgid "" -"Recursive data types or data types with dynamic sizes need to use a `Box`:" +"Most async runtimes only allow IO tasks to run concurrently. This means that " +"CPU blocking tasks will block the executor and prevent other tasks from " +"being executed. An easy workaround is to use async equivalent methods where " +"possible." msgstr "" -#: src/smart-pointers/box.md -msgid "/// A non-empty list: first element and the rest of the list." +#: src/concurrency/async-pitfalls/blocking-executor.md +msgid "\"future {id} slept for {duration_ms}ms, finished after {}ms\"" msgstr "" -#: src/smart-pointers/box.md -msgid "/// An empty list." +#: src/concurrency/async-pitfalls/blocking-executor.md +msgid "\"current_thread\"" msgstr "" -#: src/smart-pointers/box.md -msgid "\"{list:?}\"" +#: src/concurrency/async-pitfalls/blocking-executor.md +msgid "" +"Run the code and see that the sleeps happen consecutively rather than " +"concurrently." msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-pitfalls/blocking-executor.md msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - - . .- - - - - - - - - - - - - - - - - - - - " -"- - - - -.\n" -": : : :\n" -": " -"list : : :\n" -": +---------+----+----+ : : +---------+----+----+ +------+----" -"+----+ :\n" -": | Element | 1 | o--+----+-----+--->| Element | 2 | o--+--->| Nil | // " -"| // | :\n" -": +---------+----+----+ : : +---------+----+----+ +------+----" -"+----+ :\n" -": : : :\n" -": : : :\n" -"'- - - - - - - - - - - - - - ' '- - - - - - - - - - - - - - - - - - - - " -"- - - - -'\n" -"```" +"The `\"current_thread\"` flavor puts all tasks on a single thread. This " +"makes the effect more obvious, but the bug is still present in the multi-" +"threaded flavor." msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-pitfalls/blocking-executor.md msgid "" -"`Box` is like `std::unique_ptr` in C++, except that it's guaranteed to be " -"not null." +"Switch the `std::thread::sleep` to `tokio::time::sleep` and await its result." msgstr "" -#: src/smart-pointers/box.md -msgid "A `Box` can be useful when you:" +#: src/concurrency/async-pitfalls/blocking-executor.md +msgid "" +"Another fix would be to `tokio::task::spawn_blocking` which spawns an actual " +"thread and transforms its handle into a future without blocking the executor." msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-pitfalls/blocking-executor.md msgid "" -"have a type whose size that can't be known at compile time, but the Rust " -"compiler wants to know an exact size." +"You should not think of tasks as OS threads. They do not map 1 to 1 and " +"executors will allow multiple tasks to run on a single OS thread. This is " +"particularly problematic when interacting with other libraries via FFI, " +"where that library might depend on thread-local storage or map to specific " +"OS threads (e.g., CUDA). Prefer `tokio::task::spawn_blocking` in such " +"situations." msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-pitfalls/blocking-executor.md msgid "" -"want to transfer ownership of a large amount of data. To avoid copying large " -"amounts of data on the stack, instead store the data on the heap in a `Box` " -"so only the pointer is moved." +"Use sync mutexes with care. Holding a mutex over an `.await` may cause " +"another task to block, and that task may be running on the same thread." msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-pitfalls/pin.md msgid "" -"If `Box` was not used and we attempted to embed a `List` directly into the " -"`List`, the compiler would not be able to compute a fixed size for the " -"struct in memory (the `List` would be of infinite size)." +"Recall an async function or block creates a type implementing `Future` and " +"containing all of the local variables. Some of those variables can hold " +"references (pointers) to other local variables. To ensure those remain " +"valid, the future can never be moved to a different memory location." msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-pitfalls/pin.md msgid "" -"`Box` solves this problem as it has the same size as a regular pointer and " -"just points at the next element of the `List` in the heap." +"To prevent moving the future type in memory, it can only be polled through a " +"pinned pointer. `Pin` is a wrapper around a reference that disallows all " +"operations that would move the instance it points to into a different memory " +"location." msgstr "" -#: src/smart-pointers/box.md +#: src/concurrency/async-pitfalls/pin.md msgid "" -"Remove the `Box` in the List definition and show the compiler error. We get " -"the message \"recursive without indirection\", because for data recursion, " -"we have to use indirection, a Box or reference of some kind, instead of " -"storing the value directly." +"// A work item. In this case, just sleep for the given time and respond\n" +"// with a message on the `respond_on` channel.\n" msgstr "" -#: src/smart-pointers/box.md -msgid "Niche Optimization" -msgstr "Niche āĻ…āĻĒāϟāĻŋāĻŽāĻžāχāĻœā§‡āĻļāύ" +#: src/concurrency/async-pitfalls/pin.md +msgid "// A worker which listens for work on a queue and performs it.\n" +msgstr "" -#: src/smart-pointers/box.md -msgid "" -"A `Box` cannot be empty, so the pointer is always valid and non-`null`. This " -"allows the compiler to optimize the memory layout:" +#: src/concurrency/async-pitfalls/pin.md +msgid "// Pretend to work.\n" msgstr "" -#: src/smart-pointers/box.md -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - - . .- - - - - - - - - - - - - -.\n" -": : : :\n" -": list : : :\n" -": +---------+----+----+ : : +---------+----+----+ :\n" -": | Element | 1 | o--+----+-----+--->| Element | 2 | // | :\n" -": +---------+----+----+ : : +---------+----+----+ :\n" -": : : :\n" -": : : :\n" -"'- - - - - - - - - - - - - - ' '- - - - - - - - - - - - - -'\n" -"```" +#: src/concurrency/async-pitfalls/pin.md +msgid "\"failed to send response\"" msgstr "" -#: src/smart-pointers/rc.md -msgid "" -"[`Rc`](https://doc.rust-lang.org/std/rc/struct.Rc.html) is a reference-" -"counted shared pointer. Use this when you need to refer to the same data " -"from multiple places:" +#: src/concurrency/async-pitfalls/pin.md +msgid "// TODO: report number of iterations every 100ms\n" msgstr "" -#: src/smart-pointers/rc.md -msgid "\"a: {a}\"" +#: src/concurrency/async-pitfalls/pin.md +msgid "// A requester which requests work and waits for it to complete.\n" msgstr "" -#: src/smart-pointers/rc.md -msgid "\"b: {b}\"" +#: src/concurrency/async-pitfalls/pin.md +msgid "\"failed to send on work queue\"" msgstr "" -#: src/smart-pointers/rc.md +#: src/concurrency/async-pitfalls/pin.md +msgid "\"failed waiting for response\"" +msgstr "" + +#: src/concurrency/async-pitfalls/pin.md +msgid "\"work result for iteration {i}: {resp}\"" +msgstr "" + +#: src/concurrency/async-pitfalls/pin.md msgid "" -"See [`Arc`](../concurrency/shared_state/arc.md) and [`Mutex`](https://doc." -"rust-lang.org/std/sync/struct.Mutex.html) if you are in a multi-threaded " -"context." +"You may recognize this as an example of the actor pattern. Actors typically " +"call `select!` in a loop." msgstr "" -#: src/smart-pointers/rc.md +#: src/concurrency/async-pitfalls/pin.md msgid "" -"You can _downgrade_ a shared pointer into a [`Weak`](https://doc.rust-lang." -"org/std/rc/struct.Weak.html) pointer to create cycles that will get dropped." +"This serves as a summation of a few of the previous lessons, so take your " +"time with it." msgstr "" -#: src/smart-pointers/rc.md +#: src/concurrency/async-pitfalls/pin.md msgid "" -"`Rc`'s count ensures that its contained value is valid for as long as there " -"are references." +"Naively add a `_ = sleep(Duration::from_millis(100)) => { println!(..) }` to " +"the `select!`. This will never execute. Why?" msgstr "" -#: src/smart-pointers/rc.md -msgid "`Rc` in Rust is like `std::shared_ptr` in C++." +#: src/concurrency/async-pitfalls/pin.md +msgid "" +"Instead, add a `timeout_fut` containing that future outside of the `loop`:" msgstr "" -#: src/smart-pointers/rc.md +#: src/concurrency/async-pitfalls/pin.md msgid "" -"`Rc::clone` is cheap: it creates a pointer to the same allocation and " -"increases the reference count. Does not make a deep clone and can generally " -"be ignored when looking for performance issues in code." +"This still doesn't work. Follow the compiler errors, adding `&mut` to the " +"`timeout_fut` in the `select!` to work around the move, then using `Box::" +"pin`:" msgstr "" -#: src/smart-pointers/rc.md +#: src/concurrency/async-pitfalls/pin.md msgid "" -"`make_mut` actually clones the inner value if necessary (\"clone-on-write\") " -"and returns a mutable reference." +"This compiles, but once the timeout expires it is `Poll::Ready` on every " +"iteration (a fused future would help with this). Update to reset " +"`timeout_fut` every time it expires:" msgstr "" -#: src/smart-pointers/rc.md -msgid "Use `Rc::strong_count` to check the reference count." +#: src/concurrency/async-pitfalls/pin.md +msgid "" +"Box allocates on the heap. In some cases, `std::pin::pin!` (only recently " +"stabilized, with older code often using `tokio::pin!`) is also an option, " +"but that is difficult to use for a future that is reassigned." msgstr "" -#: src/smart-pointers/rc.md +#: src/concurrency/async-pitfalls/pin.md msgid "" -"`Rc::downgrade` gives you a _weakly reference-counted_ object to create " -"cycles that will be dropped properly (likely in combination with `RefCell`)." +"Another alternative is to not use `pin` at all but spawn another task that " +"will send to a `oneshot` channel every 100ms." msgstr "" -#: src/smart-pointers/trait-objects.md +#: src/concurrency/async-pitfalls/pin.md +msgid "" +"Data that contains pointers to itself is called self-referential. Normally, " +"the Rust borrow checker would prevent self-referential data from being " +"moved, as the references cannot outlive the data they point to. However, the " +"code transformation for async blocks and functions is not verified by the " +"borrow checker." +msgstr "" + +#: src/concurrency/async-pitfalls/pin.md msgid "" -"Trait objects allow for values of different types, for instance in a " -"collection:" +"`Pin` is a wrapper around a reference. An object cannot be moved from its " +"place using a pinned pointer. However, it can still be moved through an " +"unpinned pointer." msgstr "" -#: src/smart-pointers/trait-objects.md -msgid "\"Miau!\"" +#: src/concurrency/async-pitfalls/pin.md +msgid "" +"The `poll` method of the `Future` trait uses `Pin<&mut Self>` instead of " +"`&mut Self` to refer to the instance. That's why it can only be called on a " +"pinned pointer." msgstr "" -#: src/smart-pointers/trait-objects.md -msgid "\"Hello, who are you? {}\"" +#: src/concurrency/async-pitfalls/async-traits.md +msgid "" +"Async methods in traits were stabilized in the 1.75 release. This required " +"support for using return-position `impl Trait` in traits, as the desugaring " +"for `async fn` includes `-> impl Future`." msgstr "" -#: src/smart-pointers/trait-objects.md -msgid "Memory layout after allocating `pets`:" +#: src/concurrency/async-pitfalls/async-traits.md +msgid "" +"However, even with the native support, there are specific pitfalls around " +"`async fn`:" msgstr "" -#: src/smart-pointers/trait-objects.md +#: src/concurrency/async-pitfalls/async-traits.md msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - " -"- -.\n" -": : : :\n" -": pets : : +----+----+----+----" -"+ :\n" -": +-----------+-------+ : : +-----+-----+ .->| F | i | d | o " -"| :\n" -": | ptr | o---+---+-----+-->| o o | o o | | +----+----+----+----" -"+ :\n" -": | len | 2 | : : +-|-|-+-|-|-+ " -"`---------. :\n" -": | capacity | 2 | : : | | | | data " -"| :\n" -": +-----------+-------+ : : | | | | +-------+--|-------" -"+ :\n" -": : : | | | '-->| name | o, 4, 4 " -"| :\n" -": : : | | | | age | 5 " -"| :\n" -"`- - - - - - - - - - - - - -' : | | | +-------+----------" -"+ :\n" -" : | | " -"| :\n" -" : | | | " -"vtable :\n" -" : | | | +----------------------" -"+ :\n" -" : | | '---->| \"::talk\" " -"| :\n" -" : | | +----------------------" -"+ :\n" -" : | " -"| :\n" -" : | | " -"data :\n" -" : | | +-------+-------" -"+ :\n" -" : | '-->| lives | 9 " -"| :\n" -" : | +-------+-------" -"+ :\n" -" : " -"| :\n" -" : | " -"vtable :\n" -" : | +----------------------" -"+ :\n" -" : '---->| \"::talk\" " -"| :\n" -" : +----------------------" -"+ :\n" -" : :\n" -" '- - - - - - - - - - - - - - - - - - - - - " -"- -'\n" -"```" +"Return-position `impl Trait` captures all in-scope lifetimes (so certain " +"patterns of borrowing cannot be expressed)." msgstr "" -#: src/smart-pointers/trait-objects.md +#: src/concurrency/async-pitfalls/async-traits.md msgid "" -"Types that implement a given trait may be of different sizes. This makes it " -"impossible to have things like `Vec` in the example above." +"Async traits cannot be used with [trait objects](../../smart-pointers/trait-" +"objects.md) (`dyn Trait` support)." msgstr "" -#: src/smart-pointers/trait-objects.md +#: src/concurrency/async-pitfalls/async-traits.md msgid "" -"`dyn Pet` is a way to tell the compiler about a dynamically sized type that " -"implements `Pet`." +"The [async_trait](https://docs.rs/async-trait/) crate provides a workaround " +"for `dyn` support through a macro, with specific caveats:" msgstr "" -#: src/smart-pointers/trait-objects.md -msgid "" -"In the example, `pets` is allocated on the stack and the vector data is on " -"the heap. The two vector elements are _fat pointers_:" +#: src/concurrency/async-pitfalls/async-traits.md +msgid "\"Running all sleepers...\"" msgstr "" -#: src/smart-pointers/trait-objects.md -msgid "" -"A fat pointer is a double-width pointer. It has two components: a pointer to " -"the actual object and a pointer to the [virtual method table](https://en." -"wikipedia.org/wiki/Virtual_method_table) (vtable) for the `Pet` " -"implementation of that particular object." +#: src/concurrency/async-pitfalls/async-traits.md +msgid "\"Slept for {} ms\"" msgstr "" -#: src/smart-pointers/trait-objects.md +#: src/concurrency/async-pitfalls/async-traits.md msgid "" -"The data for the `Dog` named Fido is the `name` and `age` fields. The `Cat` " -"has a `lives` field." +"`async_trait` is easy to use, but note that it's using heap allocations to " +"achieve this. This heap allocation has performance overhead." msgstr "" -#: src/smart-pointers/trait-objects.md -msgid "Compare these outputs in the above example:" +#: src/concurrency/async-pitfalls/async-traits.md +msgid "" +"The challenges in language support for `async trait` are too deep to " +"describe in-depth in this class. See [this blog post](https://" +"smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-" +"hard/) by Niko Matsakis if you are interested in digging deeper. See also " +"these keywords:" msgstr "" -#: src/smart-pointers/exercise.md +#: src/concurrency/async-pitfalls/async-traits.md msgid "" -"A binary tree is a tree-type data structure where every node has two " -"children (left and right). We will create a tree where each node stores a " -"value. For a given node N, all nodes in a N's left subtree contain smaller " -"values, and all nodes in N's right subtree will contain larger values." +"[RPIT](https://doc.rust-lang.org/reference/types/impl-trait.html#abstract-" +"return-types): short for [return-position `impl Trait`](../../generics/impl-" +"trait.md)." msgstr "" -#: src/smart-pointers/exercise.md -msgid "Implement the following types, so that the given tests pass." +#: src/concurrency/async-pitfalls/async-traits.md +msgid "" +"[RPITIT](https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits." +"html): short for return-position `impl Trait` in trait (RPIT in trait)." msgstr "" -#: src/smart-pointers/exercise.md +#: src/concurrency/async-pitfalls/async-traits.md msgid "" -"Extra Credit: implement an iterator over a binary tree that returns the " -"values in order." +"Try creating a new sleeper struct that will sleep for a random amount of " +"time and adding it to the `Vec`." msgstr "" -#: src/smart-pointers/exercise.md src/smart-pointers/solution.md -msgid "/// A node in the binary tree.\n" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "" +"Dropping a future implies it can never be polled again. This is called " +"_cancellation_ and it can occur at any `await` point. Care is needed to " +"ensure the system works correctly even when futures are cancelled. For " +"example, it shouldn't deadlock or lose data." msgstr "" -#: src/smart-pointers/exercise.md src/smart-pointers/solution.md -msgid "/// A possibly-empty subtree.\n" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "\"not UTF-8\"" msgstr "" -#: src/smart-pointers/exercise.md src/smart-pointers/solution.md -msgid "" -"/// A container storing a set of values, using a binary tree.\n" -"///\n" -"/// If the same value is added multiple times, it is only stored once.\n" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "\"hi\\nthere\\n\"" msgstr "" -#: src/smart-pointers/exercise.md -msgid "// Implement `new`, `insert`, `len`, and `has`." +#: src/concurrency/async-pitfalls/cancellation.md +msgid "\"tick!\"" msgstr "" -#: src/smart-pointers/exercise.md src/smart-pointers/solution.md -msgid "// not a unique item\n" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "" +"The compiler doesn't help with cancellation-safety. You need to read API " +"documentation and consider what state your `async fn` holds." msgstr "" -#: src/smart-pointers/solution.md src/testing/googletest.md -msgid "\"bar\"" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "" +"Unlike `panic` and `?`, cancellation is part of normal control flow (vs " +"error-handling)." msgstr "" -#: src/welcome-day-3-afternoon.md -msgid "[Borrowing](./borrowing.md) (50 minutes)" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "The example loses parts of the string." msgstr "" -#: src/welcome-day-3-afternoon.md +#: src/concurrency/async-pitfalls/cancellation.md msgid "" -"[Slices and Lifetimes](./slices-and-lifetimes.md) (1 hour and 10 minutes)" +"Whenever the `tick()` branch finishes first, `next()` and its `buf` are " +"dropped." msgstr "" -#: src/borrowing.md -msgid "[Borrowing a Value](./borrowing/shared.md) (10 minutes)" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "" +"`LinesReader` can be made cancellation-safe by making `buf` part of the " +"struct:" msgstr "" -#: src/borrowing.md -msgid "[Borrow Checking](./borrowing/borrowck.md) (10 minutes)" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "// prefix buf and bytes with self.\n" msgstr "" -#: src/borrowing.md -msgid "[Interior Mutability](./borrowing/interior-mutability.md) (10 minutes)" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "" +"[`Interval::tick`](https://docs.rs/tokio/latest/tokio/time/struct.Interval." +"html#method.tick) is cancellation-safe because it keeps track of whether a " +"tick has been 'delivered'." msgstr "" -#: src/borrowing.md -msgid "[Exercise: Health Statistics](./borrowing/exercise.md) (20 minutes)" +#: src/concurrency/async-pitfalls/cancellation.md +msgid "" +"[`AsyncReadExt::read`](https://docs.rs/tokio/latest/tokio/io/trait." +"AsyncReadExt.html#method.read) is cancellation-safe because it either " +"returns or doesn't read data." msgstr "" -#: src/borrowing/shared.md +#: src/concurrency/async-pitfalls/cancellation.md msgid "" -"As we saw before, instead of transferring ownership when calling a function, " -"you can let a function _borrow_ the value:" +"[`AsyncBufReadExt::read_line`](https://docs.rs/tokio/latest/tokio/io/trait." +"AsyncBufReadExt.html#method.read_line) is similar to the example and _isn't_ " +"cancellation-safe. See its documentation for details and alternatives." msgstr "" -#: src/borrowing/shared.md -msgid "The `add` function _borrows_ two points and returns a new point." +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "Dining Philosophers --- Async" msgstr "" -#: src/borrowing/shared.md -msgid "The caller retains ownership of the inputs." +#: src/concurrency/async-exercises/dining-philosophers.md +msgid "" +"See [dining philosophers](../sync-exercises/dining-philosophers.md) for a " +"description of the problem." msgstr "" -#: src/borrowing/shared.md +#: src/concurrency/async-exercises/dining-philosophers.md msgid "" -"This slide is a review of the material on references from day 1, expanding " -"slightly to include function arguments and return values." +"As before, you will need a local [Cargo installation](../../cargo/running-" +"locally.md) for this exercise. Copy the code below to a file called `src/" +"main.rs`, fill out the blanks, and test that `cargo run` does not deadlock:" msgstr "" -#: src/borrowing/shared.md -msgid "Notes on stack returns:" +#: src/concurrency/async-exercises/dining-philosophers.md +msgid "// Keep trying until we have both chopsticks\n" msgstr "" -#: src/borrowing/shared.md -msgid "" -"Demonstrate that the return from `add` is cheap because the compiler can " -"eliminate the copy operation. Change the above code to print stack addresses " -"and run it on the [Playground](https://play.rust-lang.org/?" -"version=stable&mode=release&edition=2021&gist=0cb13be1c05d7e3446686ad9947c4671) " -"or look at the assembly in [Godbolt](https://rust.godbolt.org/). In the " -"\"DEBUG\" optimization level, the addresses should change, while they stay " -"the same when changing to the \"RELEASE\" setting:" +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "// tokio scheduler doesn't deadlock with 5 philosophers, so have 2.\n" msgstr "" -#: src/borrowing/shared.md -msgid "The Rust compiler can do return value optimization (RVO)." +#: src/concurrency/async-exercises/dining-philosophers.md +#: src/concurrency/async-exercises/solutions.md +msgid "// Make them think and eat\n" msgstr "" -#: src/borrowing/shared.md +#: src/concurrency/async-exercises/dining-philosophers.md msgid "" -"In C++, copy elision has to be defined in the language specification because " -"constructors can have side effects. In Rust, this is not an issue at all. If " -"RVO did not happen, Rust will always perform a simple and efficient `memcpy` " -"copy." +"Since this time you are using Async Rust, you'll need a `tokio` dependency. " +"You can use the following `Cargo.toml`:" msgstr "" -#: src/borrowing/borrowck.md +#: src/concurrency/async-exercises/dining-philosophers.md msgid "" -"Rust's _borrow checker_ puts constraints on the ways you can borrow values. " -"For a given value, at any time:" +"```toml\n" +"[package]\n" +"name = \"dining-philosophers-async-dine\"\n" +"version = \"0.1.0\"\n" +"edition = \"2024\"\n" +"\n" +"[dependencies]\n" +"tokio = { version = \"1.26.0\", features = [\"sync\", \"time\", \"macros\", " +"\"rt-multi-thread\"] }\n" +"```" msgstr "" -#: src/borrowing/borrowck.md -msgid "You can have one or more shared references to the value, _or_" +#: src/concurrency/async-exercises/dining-philosophers.md +msgid "" +"Also note that this time you have to use the `Mutex` and the `mpsc` module " +"from the `tokio` crate." msgstr "" -#: src/borrowing/borrowck.md -msgid "You can have exactly one exclusive reference to the value." +#: src/concurrency/async-exercises/dining-philosophers.md +msgid "Can you make your implementation single-threaded?" msgstr "" -#: src/borrowing/borrowck.md +#: src/concurrency/async-exercises/chat-app.md msgid "" -"Note that the requirement is that conflicting references not _exist_ at the " -"same point. It does not matter where the reference is dereferenced." +"In this exercise, we want to use our new knowledge to implement a broadcast " +"chat application. We have a chat server that the clients connect to and " +"publish their messages. The client reads user messages from the standard " +"input, and sends them to the server. The chat server broadcasts each message " +"that it receives to all the clients." msgstr "" -#: src/borrowing/borrowck.md +#: src/concurrency/async-exercises/chat-app.md msgid "" -"The above code does not compile because `a` is borrowed as mutable (through " -"`c`) and as immutable (through `b`) at the same time." +"For this, we use [a broadcast channel](https://docs.rs/tokio/latest/tokio/" +"sync/broadcast/fn.channel.html) on the server, and [`tokio_websockets`]" +"(https://docs.rs/tokio-websockets/) for the communication between the client " +"and the server." msgstr "" -#: src/borrowing/borrowck.md -msgid "" -"Move the `println!` statement for `b` before the scope that introduces `c` " -"to make the code compile." +#: src/concurrency/async-exercises/chat-app.md +msgid "Create a new Cargo project and add the following dependencies:" msgstr "" -#: src/borrowing/borrowck.md -msgid "" -"After that change, the compiler realizes that `b` is only ever used before " -"the new mutable borrow of `a` through `c`. This is a feature of the borrow " -"checker called \"non-lexical lifetimes\"." +#: src/concurrency/async-exercises/chat-app.md +msgid "_Cargo.toml_:" msgstr "" -#: src/borrowing/borrowck.md +#: src/concurrency/async-exercises/chat-app.md msgid "" -"The exclusive reference constraint is quite strong. Rust uses it to ensure " -"that data races do not occur. Rust also _relies_ on this constraint to " -"optimize code. For example, a value behind a shared reference can be safely " -"cached in a register for the lifetime of that reference." +"```toml\n" +"[package]\n" +"name = \"chat-async\"\n" +"version = \"0.1.0\"\n" +"edition = \"2024\"\n" +"\n" +"[dependencies]\n" +"futures-util = { version = \"0.3.32\", features = [\"sink\"] }\n" +"http = \"1.4.0\"\n" +"tokio = { version = \"1.49.0\", features = [\"full\"] }\n" +"tokio-websockets = { version = \"0.13.1\", features = [\"client\", " +"\"fastrand\", \"server\", \"sha1_smol\"] }\n" +"```" msgstr "" -#: src/borrowing/borrowck.md -msgid "" -"The borrow checker is designed to accommodate many common patterns, such as " -"taking exclusive references to different fields in a struct at the same " -"time. But, there are some situations where it doesn't quite \"get it\" and " -"this often results in \"fighting with the borrow checker.\"" +#: src/concurrency/async-exercises/chat-app.md +msgid "The required APIs" msgstr "" -#: src/borrowing/interior-mutability.md +#: src/concurrency/async-exercises/chat-app.md msgid "" -"In some situations, it's necessary to modify data behind a shared (read-" -"only) reference. For example, a shared data structure might have an internal " -"cache, and wish to update that cache from read-only methods." +"You are going to need the following functions from `tokio` and " +"[`tokio_websockets`](https://docs.rs/tokio-websockets/). Take time to " +"familiarize yourself with the API." msgstr "" -#: src/borrowing/interior-mutability.md +#: src/concurrency/async-exercises/chat-app.md msgid "" -"The \"interior mutability\" pattern allows exclusive (mutable) access behind " -"a shared reference. The standard library provides several ways to do this, " -"all while still ensuring safety, typically by performing a runtime check." +"[StreamExt::next()](https://docs.rs/futures-util/0.3.28/futures_util/stream/" +"trait.StreamExt.html#method.next) implemented by `WebSocketStream`: for " +"asynchronously reading messages from a Websocket Stream." msgstr "" -#: src/borrowing/interior-mutability.md -msgid "`RefCell`" +#: src/concurrency/async-exercises/chat-app.md +msgid "" +"[SinkExt::send()](https://docs.rs/futures-util/0.3.28/futures_util/sink/" +"trait.SinkExt.html#method.send) implemented by `WebSocketStream`: for " +"asynchronously sending messages on a Websocket Stream." msgstr "" -#: src/borrowing/interior-mutability.md -msgid "\"graph: {root:#?}\"" +#: src/concurrency/async-exercises/chat-app.md +msgid "" +"[Lines::next_line()](https://docs.rs/tokio/latest/tokio/io/struct.Lines." +"html#method.next_line): for asynchronously reading user messages from the " +"standard input." msgstr "" -#: src/borrowing/interior-mutability.md -msgid "\"graph sum: {}\"" +#: src/concurrency/async-exercises/chat-app.md +msgid "" +"[Sender::subscribe()](https://docs.rs/tokio/latest/tokio/sync/broadcast/" +"struct.Sender.html#method.subscribe): for subscribing to a broadcast channel." msgstr "" -#: src/borrowing/interior-mutability.md -msgid "`Cell`" +#: src/concurrency/async-exercises/chat-app.md +msgid "Two binaries" msgstr "" -#: src/borrowing/interior-mutability.md +#: src/concurrency/async-exercises/chat-app.md msgid "" -"`Cell` wraps a value and allows getting or setting the value, even with a " -"shared reference to the `Cell`. However, it does not allow any references to " -"the value. Since there are no references, borrowing rules cannot be broken." +"Normally in a Cargo project, you can have only one binary, and one `src/main." +"rs` file. In this project, we need two binaries. One for the client, and one " +"for the server. You could potentially make them two separate Cargo projects, " +"but we are going to put them in a single Cargo project with two binaries. " +"For this to work, the client and the server code should go under `src/bin` " +"(see the [documentation](https://doc.rust-lang.org/cargo/reference/cargo-" +"targets.html#binaries))." msgstr "" -#: src/borrowing/interior-mutability.md +#: src/concurrency/async-exercises/chat-app.md msgid "" -"The main thing to take away from this slide is that Rust provides _safe_ " -"ways to modify data behind a shared reference. There are a variety of ways " -"to ensure that safety, and `RefCell` and `Cell` are two of them." +"Copy the following server and client code into `src/bin/server.rs` and `src/" +"bin/client.rs`, respectively. Your task is to complete these files as " +"described below." msgstr "" -#: src/borrowing/interior-mutability.md -msgid "" -"`RefCell` enforces Rust's usual borrowing rules (either multiple shared " -"references or a single exclusive reference) with a runtime check. In this " -"case, all borrows are very short and never overlap, so the checks always " -"succeed." +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md +msgid "_src/bin/server.rs_:" msgstr "" -#: src/borrowing/interior-mutability.md -msgid "" -"`Rc` only allows shared (read-only) access to its contents, since its " -"purpose is to allow (and count) many references. But we want to modify the " -"value, so we need interior mutability." +#: src/concurrency/async-exercises/chat-app.md +msgid "// TODO: For a hint, see the description of the task below.\n" msgstr "" -#: src/borrowing/interior-mutability.md -msgid "" -"`Cell` is a simpler means to ensure safety: it has a `set` method that takes " -"`&self`. This needs no runtime check, but requires moving values, which can " -"have its own cost." +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md +msgid "\"127.0.0.1:2000\"" msgstr "" -#: src/borrowing/interior-mutability.md -msgid "" -"Demonstrate that reference loops can be created by adding `root` to `subtree." -"children`." +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md +msgid "\"listening on port 2000\"" msgstr "" -#: src/borrowing/interior-mutability.md -msgid "" -"To demonstrate a runtime panic, add a `fn inc(&mut self)` that increments " -"`self.value` and calls the same method on its children. This will panic in " -"the presence of the reference loop, with `thread 'main' panicked at 'already " -"borrowed: BorrowMutError'`." +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md +msgid "\"New connection from {addr:?}\"" msgstr "" -#: src/borrowing/exercise.md -msgid "" -"You're working on implementing a health-monitoring system. As part of that, " -"you need to keep track of users' health statistics." +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md +msgid "// Wrap the raw TCP stream into a websocket.\n" msgstr "" -#: src/borrowing/exercise.md -msgid "" -"You'll start with a stubbed function in an `impl` block as well as a `User` " -"struct definition. Your goal is to implement the stubbed out method on the " -"`User` `struct` defined in the `impl` block." +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md +msgid "_src/bin/client.rs_:" msgstr "" -#: src/borrowing/exercise.md -msgid "" -"Copy the code below to and fill in the missing " -"method:" +#: src/concurrency/async-exercises/chat-app.md +#: src/concurrency/async-exercises/solutions.md +msgid "\"ws://127.0.0.1:2000\"" +msgstr "" + +#: src/concurrency/async-exercises/chat-app.md +msgid "Running the binaries" msgstr "" -#: src/borrowing/exercise.md -msgid "" -"\"Update a user's statistics based on measurements from a visit to the " -"doctor\"" +#: src/concurrency/async-exercises/chat-app.md +msgid "Run the server with:" msgstr "" -#: src/borrowing/exercise.md src/borrowing/solution.md -#: src/android/build-rules/library.md -#: src/android/aidl/example-service/client.md -msgid "\"Bob\"" +#: src/concurrency/async-exercises/chat-app.md +msgid "and the client with:" msgstr "" -#: src/borrowing/exercise.md src/borrowing/solution.md -msgid "\"I'm {} and my age is {}\"" +#: src/concurrency/async-exercises/chat-app.md +msgid "Implement the `handle_connection` function in `src/bin/server.rs`." msgstr "" -#: src/slices-and-lifetimes.md -msgid "[Slices: &\\[T\\]](./slices-and-lifetimes/slices.md) (10 minutes)" +#: src/concurrency/async-exercises/chat-app.md +msgid "" +"Hint: Use `tokio::select!` for concurrently performing two tasks in a " +"continuous loop. One task receives messages from the client and broadcasts " +"them. The other sends messages received by the server to the client." msgstr "" -#: src/slices-and-lifetimes.md -msgid "[String References](./slices-and-lifetimes/str.md) (10 minutes)" +#: src/concurrency/async-exercises/chat-app.md +msgid "Complete the main function in `src/bin/client.rs`." msgstr "" -#: src/slices-and-lifetimes.md +#: src/concurrency/async-exercises/chat-app.md msgid "" -"[Lifetime Annotations](./slices-and-lifetimes/lifetime-annotations.md) (10 " -"minutes)" +"Hint: As before, use `tokio::select!` in a continuous loop for concurrently " +"performing two tasks: (1) reading user messages from standard input and " +"sending them to the server, and (2) receiving messages from the server, and " +"displaying them for the user." msgstr "" -#: src/slices-and-lifetimes.md +#: src/concurrency/async-exercises/chat-app.md msgid "" -"[Lifetime Elision](./slices-and-lifetimes/lifetime-elision.md) (5 minutes)" +"Optional: Once you are done, change the code to broadcast messages to all " +"clients, but the sender of the message." msgstr "" -#: src/slices-and-lifetimes.md +#: src/concurrency/async-exercises/solutions.md msgid "" -"[Struct Lifetimes](./slices-and-lifetimes/struct-lifetimes.md) (5 minutes)" +"// Keep trying until we have both chopsticks\n" +" // Pick up chopsticks...\n" msgstr "" -#: src/slices-and-lifetimes.md -msgid "" -"[Exercise: Protobuf Parsing](./slices-and-lifetimes/exercise.md) (30 minutes)" +#: src/concurrency/async-exercises/solutions.md +msgid "// The locks are dropped here\n" msgstr "" -#: src/slices-and-lifetimes.md -msgid "This segment should take about 1 hour and 10 minutes" +#: src/concurrency/async-exercises/solutions.md +msgid "// tx is dropped here, so we don't need to explicitly drop it later\n" msgstr "" -#: src/slices-and-lifetimes/slices.md -msgid "Slices" -msgstr "Slices" +#: src/concurrency/async-exercises/solutions.md +msgid "\"Here is a thought: {thought}\"" +msgstr "" -#: src/slices-and-lifetimes/slices.md -msgid "A slice gives you a view into a larger collection:" +#: src/concurrency/async-exercises/solutions.md +msgid "\"Welcome to chat! Type a message\"" msgstr "" -#: src/slices-and-lifetimes/slices.md -msgid "Slices borrow data from the sliced type." +#: src/concurrency/async-exercises/solutions.md +msgid "" +"// A continuous loop for concurrently performing two tasks: (1) receiving\n" +" // messages from `ws_stream` and broadcasting them, and (2) receiving\n" +" // messages on `bcast_rx` and sending them to the client.\n" msgstr "" -#: src/slices-and-lifetimes/slices.md -msgid "Question: What happens if you modify `a[3]` right before printing `s`?" +#: src/concurrency/async-exercises/solutions.md +msgid "\"From client {addr:?} {text:?}\"" msgstr "" -#: src/slices-and-lifetimes/slices.md -msgid "" -"We create a slice by borrowing `a` and specifying the starting and ending " -"indexes in brackets." +#: src/concurrency/async-exercises/solutions.md +msgid "// Continuous loop for concurrently sending and receiving messages.\n" msgstr "" -#: src/slices-and-lifetimes/slices.md -msgid "" -"If the slice starts at index 0, Rust’s range syntax allows us to drop the " -"starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are " -"identical." +#: src/concurrency/async-exercises/solutions.md +msgid "\"From server: {}\"" msgstr "" -#: src/slices-and-lifetimes/slices.md -msgid "" -"The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are " -"identical." +#: src/idiomatic/welcome.md +msgid "Welcome to Idiomatic Rust" msgstr "" -#: src/slices-and-lifetimes/slices.md +#: src/idiomatic/welcome.md msgid "" -"To easily create a slice of the full array, we can therefore use `&a[..]`." +"[Rust Fundamentals](../welcome-day-1.md) introduced Rust syntax and core " +"concepts. We now want to go one step further: how do you use Rust " +"_effectively_ in your projects? What does _idiomatic_ Rust look like?" msgstr "" -#: src/slices-and-lifetimes/slices.md +#: src/idiomatic/welcome.md msgid "" -"`s` is a reference to a slice of `i32`s. Notice that the type of `s` " -"(`&[i32]`) no longer mentions the array length. This allows us to perform " -"computation on slices of different sizes." +"This course is opinionated: we will nudge you towards some patterns, and " +"away from others. Nonetheless, we do recognize that some projects may have " +"different needs. We always provide the necessary information to help you " +"make informed decisions within the context and constraints of your own " +"projects." msgstr "" -#: src/slices-and-lifetimes/slices.md -msgid "" -"Slices always borrow from another object. In this example, `a` has to remain " -"'alive' (in scope) for at least as long as our slice." +#: src/idiomatic/welcome.md +msgid "âš ī¸ This course is under **active development**." msgstr "" -#: src/slices-and-lifetimes/slices.md +#: src/idiomatic/welcome.md msgid "" -"The question about modifying `a[3]` can spark an interesting discussion, but " -"the answer is that for memory safety reasons you cannot do it through `a` at " -"this point in the execution, but you can read the data from both `a` and `s` " -"safely. It works before you created the slice, and again after the " -"`println`, when the slice is no longer used." +"The material may change frequently and there might be errors that have not " +"yet been spotted. Nonetheless, we encourage you to browse through and " +"provide early feedback!" msgstr "" -#: src/slices-and-lifetimes/str.md +#: src/idiomatic/welcome.md msgid "" -"We can now understand the two string types in Rust: `&str` is almost like " -"`&[char]`, but with its data stored in a variable-length encoding (UTF-8)." +"Including 10 minute breaks, this session should take about 14 hours and 25 " +"minutes. It contains:" msgstr "" -#: src/slices-and-lifetimes/str.md -msgid "\"s1: {s1}\"" +#: src/idiomatic/welcome.md +msgid "" +"The course will cover the topics listed below. Each topic may be covered in " +"one or more slides, depending on its complexity and relevance." msgstr "" -#: src/slices-and-lifetimes/str.md -#, fuzzy -msgid "\"Hello \"" -msgstr "Hello World!" +#: src/idiomatic/welcome.md +msgid "Target Audience" +msgstr "" -#: src/slices-and-lifetimes/str.md -msgid "\"s3: {s3}\"" +#: src/idiomatic/welcome.md +msgid "" +"Engineers with at least 2-3 years of coding experience in C, C++11 or newer, " +"Java 7 or newer, Python 2 or 3, Go or any other similar imperative " +"programming language. We have no expectation of experience with more modern " +"or feature-rich languages like Swift, Kotlin, C#, or TypeScript." msgstr "" -#: src/slices-and-lifetimes/str.md -msgid "Rust terminology:" +#: src/idiomatic/welcome.md +msgid "Foundations of API design" msgstr "" -#: src/slices-and-lifetimes/str.md -msgid "`&str` an immutable reference to a string slice." +#: src/idiomatic/welcome.md +msgid "" +"Golden rule: prioritize clarity and readability at the callsite. People will " +"spend much more time reading the call sites than declarations of the " +"functions being called." msgstr "" -#: src/slices-and-lifetimes/str.md -msgid "`String` a mutable string buffer." +#: src/idiomatic/welcome.md +msgid "Make your API predictable" msgstr "" -#: src/slices-and-lifetimes/str.md +#: src/idiomatic/welcome.md msgid "" -"`&str` introduces a string slice, which is an immutable reference to UTF-8 " -"encoded string data stored in a block of memory. String literals " -"(`”Hello”`), are stored in the program’s binary." +"Follow naming conventions (case conventions, prefer vocabulary precedented " +"in the standard library - e.g., methods should be called \"push\" not " +"\"push_back\", \"is_empty\" not \"empty\" etc.)" msgstr "" -#: src/slices-and-lifetimes/str.md +#: src/idiomatic/welcome.md msgid "" -"Rust’s `String` type is a wrapper around a vector of bytes. As with a " -"`Vec`, it is owned." +"Know the vocabulary types and traits in the standard library, and use them " +"in your APIs. If something feels like a basic type/algorithm, check in the " +"standard library first." msgstr "" -#: src/slices-and-lifetimes/str.md +#: src/idiomatic/welcome.md msgid "" -"As with many other types `String::from()` creates a string from a string " -"literal; `String::new()` creates a new empty string, to which string data " -"can be added using the `push()` and `push_str()` methods." +"Use well-established API design patterns that we will discuss later in this " +"class (e.g., newtype, owned/view type pairs, error handling)" msgstr "" -#: src/slices-and-lifetimes/str.md +#: src/idiomatic/welcome.md msgid "" -"The `format!()` macro is a convenient way to generate an owned string from " -"dynamic values. It accepts the same format specification as `println!()`." +"Write meaningful and effective doc comments (e.g., don't merely repeat the " +"method name with spaces instead of underscores, don't repeat the same " +"information just to fill out every markdown tag, provide usage examples)" msgstr "" -#: src/slices-and-lifetimes/str.md -msgid "" -"You can borrow `&str` slices from `String` via `&` and optionally range " -"selection. If you select a byte range that is not aligned to character " -"boundaries, the expression will panic. The `chars` iterator iterates over " -"characters and is preferred over trying to get character boundaries right." +#: src/idiomatic/welcome.md +msgid "Leveraging the type system" msgstr "" -#: src/slices-and-lifetimes/str.md -msgid "" -"For C++ programmers: think of `&str` as `std::string_view` from C++, but the " -"one that always points to a valid string in memory. Rust `String` is a rough " -"equivalent of `std::string` from C++ (main difference: it can only contain " -"UTF-8 encoded bytes and will never use a small-string optimization)." +#: src/idiomatic/welcome.md +msgid "Short recap on enums, structs and type aliases" msgstr "" -#: src/slices-and-lifetimes/str.md -#, fuzzy -msgid "Byte strings literals allow you to create a `&[u8]` value directly:" -msgstr "Byte strings allow you to create a `&[u8]` value directly:" +#: src/idiomatic/welcome.md +msgid "Newtype pattern and encapsulation: parse, don't validate" +msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md +#: src/idiomatic/welcome.md msgid "" -"A reference has a _lifetime_, which must not \"outlive\" the value it refers " -"to. This is verified by the borrow checker." +"Extension traits: avoid the newtype pattern when you want to provide " +"additional behaviour" msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md +#: src/idiomatic/welcome.md msgid "" -"The lifetime can be implicit - this is what we have seen so far. Lifetimes " -"can also be explicit: `&'a Point`, `&'document str`. Lifetimes start with " -"`'` and `'a` is a typical default name. Read `&'a Point` as \"a borrowed " -"`Point` which is valid for at least the lifetime `a`\"." +"RAII, scope guards and drop bombs: using `Drop` to clean up resources, " +"trigger actions or enforce invariants" msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md +#: src/idiomatic/welcome.md msgid "" -"Lifetimes are always inferred by the compiler: you cannot assign a lifetime " -"yourself. Explicit lifetime annotations create constraints where there is " -"ambiguity; the compiler verifies that there is a valid solution." +"\"Token\" types: force users to prove they've performed a specific action" msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md +#: src/idiomatic/welcome.md msgid "" -"Lifetimes become more complicated when considering passing values to and " -"returning values from functions." +"The typestate pattern: enforce correct state transitions at compile-time" msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md -msgid "// What is the lifetime of p3?" +#: src/idiomatic/welcome.md +msgid "" +"Using the borrow checker to enforce invariants that have nothing to do with " +"memory ownership" msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md -msgid "\"p3: {p3:?}\"" +#: src/idiomatic/welcome.md +msgid "OwnedFd/BorrowedFd in the standard library" msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md -msgid "" -"In this example, the the compiler does not know what lifetime to infer for " -"`p3`. Looking inside the function body shows that it can only safely assume " -"that `p3`'s lifetime is the shorter of `p1` and `p2`. But just like types, " -"Rust requires explicit annotations of lifetimes on function arguments and " -"return values." +#: src/idiomatic/welcome.md +msgid "[Branded types](https://plv.mpi-sws.org/rustbelt/ghostcell/paper.pdf)" msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md -msgid "Add `'a` appropriately to `left_most`:" +#: src/idiomatic/welcome.md +msgid "Don't fight the borrow checker" msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md +#: src/idiomatic/welcome.md msgid "" -"This says, \"given p1 and p2 which both outlive `'a`, the return value lives " -"for at least `'a`." +"\"Owned\" types and \"view\" types: `&str` and `String`, `Path` and " +"`PathBuf`, etc." msgstr "" -#: src/slices-and-lifetimes/lifetime-annotations.md +#: src/idiomatic/welcome.md msgid "" -"In common cases, lifetimes can be elided, as described on the next slide." +"Don't hide ownership requirements: avoid hidden `.clone()`, learn to love " +"`Cow`" msgstr "" -#: src/slices-and-lifetimes/lifetime-elision.md -msgid "Lifetimes in Function Calls" -msgstr "āĻĢāĻžāĻ‚āĻļāύ āĻ•āϞ āĻ āĻœā§€āĻŦāύāĻ•āĻžāϞ" - -#: src/slices-and-lifetimes/lifetime-elision.md -msgid "" -"Lifetimes for function arguments and return values must be fully specified, " -"but Rust allows lifetimes to be elided in most cases with [a few simple " -"rules](https://doc.rust-lang.org/nomicon/lifetime-elision.html). This is not " -"inference -- it is just a syntactic shorthand." +#: src/idiomatic/welcome.md +msgid "Split types along ownership boundaries" msgstr "" -#: src/slices-and-lifetimes/lifetime-elision.md -msgid "Each argument which does not have a lifetime annotation is given one." +#: src/idiomatic/welcome.md +msgid "Structure your ownership hierarchy like a tree" msgstr "" -#: src/slices-and-lifetimes/lifetime-elision.md +#: src/idiomatic/welcome.md msgid "" -"If there is only one argument lifetime, it is given to all un-annotated " -"return values." +"Strategies to manage circular dependencies: reference counting, using " +"indexes instead of references" msgstr "" -#: src/slices-and-lifetimes/lifetime-elision.md -msgid "" -"If there are multiple argument lifetimes, but the first one is for `self`, " -"that lifetime is given to all un-annotated return values." +#: src/idiomatic/welcome.md +msgid "Interior mutability (Cell, RefCell)" msgstr "" -#: src/slices-and-lifetimes/lifetime-elision.md -msgid "In this example, `cab_distance` is trivially elided." +#: src/idiomatic/welcome.md +msgid "Working with lifetime parameters on user-defined data types" msgstr "" -#: src/slices-and-lifetimes/lifetime-elision.md -msgid "" -"The `nearest` function provides another example of a function with multiple " -"references in its arguments that requires explicit annotation." +#: src/idiomatic/welcome.md +msgid "Polymorphism in Rust" msgstr "" -#: src/slices-and-lifetimes/lifetime-elision.md -msgid "Try adjusting the signature to \"lie\" about the lifetimes returned:" +#: src/idiomatic/welcome.md +msgid "A quick refresher on traits and generic functions" msgstr "" -#: src/slices-and-lifetimes/lifetime-elision.md -msgid "" -"This won't compile, demonstrating that the annotations are checked for " -"validity by the compiler. Note that this is not the case for raw pointers " -"(unsafe), and this is a common source of errors with unsafe Rust." +#: src/idiomatic/welcome.md +msgid "Rust has no inheritance: what are the implications?" msgstr "" -#: src/slices-and-lifetimes/lifetime-elision.md -msgid "" -"Students may ask when to use lifetimes. Rust borrows _always_ have " -"lifetimes. Most of the time, elision and type inference mean these don't " -"need to be written out. In more complicated cases, lifetime annotations can " -"help resolve ambiguity. Often, especially when prototyping, it's easier to " -"just work with owned data by cloning values where necessary." +#: src/idiomatic/welcome.md +msgid "Using enums for polymorphism" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "Lifetimes in Data Structures" -msgstr "āĻĄā§‡āϟāĻž āĻ¸ā§āĻŸā§āϰāĻžāĻ•āϚāĻžāϰ āĻ āĻœā§€āĻŦāύāĻ•āĻžāϞ" - -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "" -"If a data type stores borrowed data, it must be annotated with a lifetime:" +#: src/idiomatic/welcome.md +msgid "Using traits for polymorphism" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "\"Bye {text}!\"" +#: src/idiomatic/welcome.md +msgid "Using composition" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "\"The quick brown fox jumps over the lazy dog.\"" +#: src/idiomatic/welcome.md +msgid "How do I pick the most appropriate pattern?" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "// erase(text);" +#: src/idiomatic/welcome.md +msgid "Working with generics" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "\"{fox:?}\"" +#: src/idiomatic/welcome.md +msgid "Generic type parameter in a function or trait object as an argument?" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "\"{dog:?}\"" +#: src/idiomatic/welcome.md +msgid "Trait bounds don't have to refer to the generic parameter" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md +#: src/idiomatic/welcome.md msgid "" -"In the above example, the annotation on `Highlight` enforces that the data " -"underlying the contained `&str` lives at least as long as any instance of " -"`Highlight` that uses that data." +"Type parameters in traits: should it be a generic parameter or an associated " +"type?" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md +#: src/idiomatic/welcome.md msgid "" -"If `text` is consumed before the end of the lifetime of `fox` (or `dog`), " -"the borrow checker throws an error." +"Macros: a valuable tool to DRY up code when traits are not enough (or too " +"complex)" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "" -"Types with borrowed data force users to hold on to the original data. This " -"can be useful for creating lightweight views, but it generally makes them " -"somewhat harder to use." +#: src/idiomatic/welcome.md +msgid "What is the purpose of errors? Recovery vs. reporting." msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "When possible, make data structures own their data directly." +#: src/idiomatic/welcome.md +msgid "Result vs. Option" msgstr "" -#: src/slices-and-lifetimes/struct-lifetimes.md -msgid "" -"Some structs with multiple references inside can have more than one lifetime " -"annotation. This can be necessary if there is a need to describe lifetime " -"relationships between the references themselves, in addition to the lifetime " -"of the struct itself. Those are very advanced use cases." +#: src/idiomatic/welcome.md +msgid "Designing good errors:" msgstr "" -#: src/slices-and-lifetimes/exercise.md -msgid "" -"In this exercise, you will build a parser for the [protobuf binary encoding]" -"(https://protobuf.dev/programming-guides/encoding/). Don't worry, it's " -"simpler than it seems! This illustrates a common parsing pattern, passing " -"slices of data. The underlying data itself is never copied." +#: src/idiomatic/welcome.md +msgid "Determine the error scope." msgstr "" -#: src/slices-and-lifetimes/exercise.md +#: src/idiomatic/welcome.md msgid "" -"Fully parsing a protobuf message requires knowing the types of the fields, " -"indexed by their field numbers. That is typically provided in a `proto` " -"file. In this exercise, we'll encode that information into `match` " -"statements in functions that get called for each field." +"Capture additional context as the error flows upwards, crossing scope " +"boundaries." msgstr "" -#: src/slices-and-lifetimes/exercise.md -msgid "We'll use the following proto:" +#: src/idiomatic/welcome.md +msgid "Leverage the `Error` trait to keep track of the full error chain." msgstr "" -#: src/slices-and-lifetimes/exercise.md -msgid "" -"A proto message is encoded as a series of fields, one after the next. Each " -"is implemented as a \"tag\" followed by the value. The tag contains a field " -"number (e.g., `2` for the `id` field of a `Person` message) and a wire type " -"defining how the payload should be determined from the byte stream." +#: src/idiomatic/welcome.md +msgid "Leverage `thiserror` to reduce boilerplate when defining error types." msgstr "" -#: src/slices-and-lifetimes/exercise.md +#: src/idiomatic/welcome.md msgid "" -"Integers, including the tag, are represented with a variable-length encoding " -"called VARINT. Luckily, `parse_varint` is defined for you below. The given " -"code also defines callbacks to handle `Person` and `PhoneNumber` fields, and " -"to parse a message into a series of calls to those callbacks." +"Distinguish fatal errors from recoverable errors using `Result, FatalError>`." msgstr "" -#: src/slices-and-lifetimes/exercise.md -msgid "" -"What remains for you is to implement the `parse_field` function and the " -"`ProtoMessage` trait for `Person` and `PhoneNumber`." +#: src/idiomatic/foundations-api-design.md +msgid "This segment should take about 3 hours and 30 minutes. It contains:" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "\"Invalid varint\"" +#: src/idiomatic/foundations-api-design.md +msgid "1 hour and 25 minutes" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "\"Invalid wire-type\"" +#: src/idiomatic/foundations-api-design.md +msgid "2 hours and 5 minutes" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "\"Unexpected EOF\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments.md +msgid "/// API for the client // ❌ Lacks detail\n" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "\"Invalid length\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments.md +msgid "/// Function from A to B // ❌ Redundant\n" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "\"Unexpected wire-type)\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments.md +msgid "/// Connects to the database. // ❌ Lacks detail\n" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "\"Invalid string (not UTF-8)\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments.md +msgid "" +"Doc comments are the most common form of documentation developers engage " +"with." msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "/// A wire type as seen on the wire.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments.md +msgid "" +"Good doc comments provide information that the code, names, and types " +"cannot, without restating the obvious information." msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "/// The Varint WireType indicates the value is a single VARINT.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +msgid "Who are you writing for?" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +msgid "Colleagues, collaborators, largely-silent API users, or just yourself?" +msgstr "" + +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md msgid "" -"//I64, -- not needed for this exercise\n" -" /// The Len WireType indicates that the value is a length represented as " -"a\n" -" /// VARINT followed by exactly that number of bytes.\n" +"// expert writes for experts\n" +"/// Canonicalizes the MIR for the borrow checker. \n" +"/// \n" +"/// This pass ensures that all borrows conform to the NLL-Polonius " +"constraints \n" +"/// before we proceed to MIR-to-LLVM-IR translation. \n" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md msgid "" -"/// The I32 WireType indicates that the value is precisely 4 bytes in\n" -" /// little-endian order containing a 32-bit signed integer.\n" +"// expert writes for newcomers\n" +"/// Prepares the Mid-level IR (MIR) for borrow checking. \n" +"/// \n" +"/// The borrow checker operates on a simplified, \"canonical\" form of the " +"MIR. \n" +"/// This function performs that transformation. It is a prerequisite for " +"the \n" +"/// final stages of code generation. \n" +"/// \n" +"/// For more about Rust's intermediate representations, see the \n" +"/// [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/mir/index." +"html). \n" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "/// A field's value, typed based on the wire type.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +msgid "" +"Background: The [curse of knowledge](https://en.wikipedia.org/wiki/" +"Curse_of_knowledge) is a cognitive bias where experts assume that others " +"have the same level of expertise and perspective." msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "//I64(i64), -- not needed for this exercise\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +msgid "" +"Motivation: Your reader does not have the same level of expertise and the " +"same perspective as you. Don't write for people like yourself, write for " +"others." msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "/// A field, containing the field number and its value.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +msgid "" +"Unintentionally writing for yourself can lead to people not understanding a " +"point you're trying to make or the concept you're trying to articulate." msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "//1 => WireType::I64, -- not needed for this exercise\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +msgid "" +"Imagine a version of you, or others you've known, struggling to find " +"practical information while going through documentation." msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md msgid "" -"/// Parse a VARINT, returning the parsed value and the remaining bytes.\n" +"Keep this idea of a person in mind when thinking about what areas of a " +"codebase need attention for doc comments." msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md msgid "" -"// This is the last byte of the VARINT, so convert it to\n" -" // a u64 and return it.\n" +"Also imagine a version of you, or others you've known, who is struggling to " +"find the important details in winding, extensive doc comments. Don't give " +"too much information." msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "// More than 7 bytes is invalid.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +msgid "" +"Always ask: Is this documentation making it difficult for the API user? Are " +"they able to quickly grasp what they need or find out where they could need " +"it?" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "/// Convert a tag into a field number and a WireType.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md +msgid "" +"Always consider: Experts also read API level documentation. Doc comments " +"might not be the right place to educate your audience about the basics of " +"your domain. In that case, signpost and name-drop. Divert people to long-" +"form documentation." msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "/// Parse a field, returning the remaining bytes\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "Library vs application docs" msgstr "" -#: src/slices-and-lifetimes/exercise.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md msgid "" -"\"Based on the wire type, build a Field, consuming as many bytes as " -"necessary.\"" +"You might see elaborate documentation for fundamental APIs that repeats the " +"names and type signatures. Stable and highly reusable code can afford this " +"with a positive RoI." msgstr "" -#: src/slices-and-lifetimes/exercise.md -msgid "\"Return the field, and any un-consumed bytes.\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "Library code:" msgstr "" -#: src/slices-and-lifetimes/exercise.md src/slices-and-lifetimes/solution.md -msgid "" -"/// Parse a message in the given data, calling `T::add_field` for each field " -"in\n" -"/// the message.\n" -"///\n" -"/// The entire input is consumed.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "has a high number of users," msgstr "" -#: src/slices-and-lifetimes/exercise.md -msgid "// TODO: Implement ProtoMessage for Person and PhoneNumber." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "solves a whole range of related problems," msgstr "" -#: src/slices-and-lifetimes/solution.md -msgid "// Unwrap error because `value` is definitely 4 bytes long.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "often has stable APIs." msgstr "" -#: src/slices-and-lifetimes/solution.md -msgid "// skip everything else\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "Application code is the opposite:" msgstr "" -#: src/slices-and-lifetimes/solution.md -msgid "b\"hello\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "few users," msgstr "" -#: src/welcome-day-4.md -#, fuzzy -msgid "Welcome to Day 4" -msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύ⧇ āφāĻĒāύāĻžāϕ⧇ āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ" - -#: src/welcome-day-4.md -msgid "" -"Today we will cover topics relating to building large-scale software in Rust:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "solves a specific problem," msgstr "" -#: src/welcome-day-4.md -msgid "Iterators: a deep dive on the `Iterator` trait." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "changes often." msgstr "" -#: src/welcome-day-4.md -msgid "Modules and visibility." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "" +"You might have seen elaborate documentation that repeats code, looks at the " +"same API multiple times with many examples and case studies. Context is key: " +"who wrote it, for whom, and what material it is covering, and what resources " +"did they have." msgstr "" -#: src/welcome-day-4.md -#, fuzzy -msgid "Testing." -msgstr "āĻŸā§‡āĻ¸ā§āϟāĻŋāĻ‚" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "" +"Fundamental library code often has Elaborate documentation, for example, the " +"standard library, highly reusable frameworks like serde and tokio. Teams " +"responsible for this code often have appropriate resources to write and " +"maintain elaborate documentation." +msgstr "" -#: src/welcome-day-4.md -msgid "Error handling: panics, `Result`, and the try operator `?`." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md +msgid "" +"Library code is often stable, so the community is going to extract a " +"significant benefit from elaborate documentation before it needs to be " +"reworked." msgstr "" -#: src/welcome-day-4.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md msgid "" -"Unsafe Rust: the escape hatch when you can't express yourself in safe Rust." +"Application code has the opposite traits: it has few users, solves a " +"specific problem, and changes often. For application code elaborate " +"documentation quickly becomes outdated and misleading. It is also difficult " +"to extract a positive RoI from boilerplate docs even while they are up to " +"date, because there are only a few users." msgstr "" -#: src/welcome-day-4.md -msgid "[Welcome](./welcome-day-4.md) (3 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +msgid "The Anatomy of a Doc Comment" msgstr "" -#: src/welcome-day-4.md -msgid "[Iterators](./iterators.md) (45 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +msgid "A brief, one-sentence summary." msgstr "" -#: src/welcome-day-4.md -msgid "[Modules](./modules.md) (40 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +msgid "A more detailed explanation." msgstr "" -#: src/welcome-day-4.md -msgid "[Testing](./testing.md) (1 hour)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +msgid "Special sections: code examples, panics, errors, safety preconditions." msgstr "" -#: src/iterators.md -msgid "[Iterator](./iterators/iterator.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +msgid "" +"/// Parses a key-value pair from a string.\n" +"///\n" +"/// The input string must be in the format `key=value`. Everything before " +"the\n" +"/// first '=' is treated as the key, and everything after is the value.\n" +"///\n" +"/// # Examples\n" +"///\n" +"/// ```\n" +"/// use my_crate::parse_key_value;\n" +"/// let (key, value) = parse_key_value(\"lang=rust\").unwrap();\n" +"/// assert_eq!(key, \"lang\");\n" +"/// assert_eq!(value, \"rust\");\n" +"/// ```\n" +"///\n" +"/// # Panics\n" +"///\n" +"/// Panics if the input is empty.\n" +"///\n" +"/// # Errors\n" +"///\n" +"/// Returns a `ParseError::Malformed` if the string does not contain `=`.\n" +"///\n" +"/// # Safety\n" +"///\n" +"/// Triggers undefined behavior if...\n" msgstr "" -#: src/iterators.md -msgid "[IntoIterator](./iterators/intoiterator.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +msgid "" +"Idiomatic Rust doc comments follow a conventional structure that makes them " +"easier for developers to read." msgstr "" -#: src/iterators.md -msgid "[FromIterator](./iterators/fromiterator.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +msgid "" +"The first line of a doc comment is a single-sentence summary of the " +"function. Keep it concise. `rustdoc` and other tools have a strong " +"expectation about that: it is used as a short summary in module-level " +"documentation and search results." msgstr "" -#: src/iterators.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md msgid "" -"[Exercise: Iterator Method Chaining](./iterators/exercise.md) (30 minutes)" +"Next, you can provide a long, multi-paragraph description of the \"why\" and " +"\"what\" of the function. Use Markdown." msgstr "" -#: src/iterators/iterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md msgid "" -"The [`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) " -"trait supports iterating over values in a collection. It requires a `next` " -"method and provides lots of methods. Many standard library types implement " -"`Iterator`, and you can implement it yourself, too:" +"Finally, you can use top-level section headers to organize your content. Doc " +"comments commonly use `# Examples`, `# Panics`, `# Errors`, and `# Safety` " +"as section titles. The Rust community expects to see relevant aspects of " +"your API documented in these sections." msgstr "" -#: src/iterators/iterator.md -msgid "\"fib({i}): {n}\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +msgid "" +"Rust heavily focuses on safety and correctness. Documenting behavior of your " +"code in case of errors is critical for writing reliable software." msgstr "" -#: src/iterators/iterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md msgid "" -"The `Iterator` trait implements many common functional programming " -"operations over collections (e.g. `map`, `filter`, `reduce`, etc). This is " -"the trait where you can find all the documentation about them. In Rust these " -"functions should produce the code as efficient as equivalent imperative " -"implementations." +"`# Panics`: If your function may panic, you must document the specific " +"conditions when that might happen. Callers need to know what to avoid." msgstr "" -#: src/iterators/iterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md msgid "" -"`IntoIterator` is the trait that makes for loops work. It is implemented by " -"collection types such as `Vec` and references to them such as `&Vec` " -"and `&[T]`. Ranges also implement it. This is why you can iterate over a " -"vector with `for i in some_vec { .. }` but `some_vec.next()` doesn't exist." +"`# Errors`: For functions returning a `Result`, this section explains what " +"kind of errors can occur and under what circumstances. Callers need this " +"information to write robust error handling logic." msgstr "" -#: src/iterators/intoiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md msgid "" -"The `Iterator` trait tells you how to _iterate_ once you have created an " -"iterator. The related trait [`IntoIterator`](https://doc.rust-lang.org/std/" -"iter/trait.IntoIterator.html) defines how to create an iterator for a type. " -"It is used automatically by the `for` loop." +"**Question:** Ask the class why documenting panics is so important in a " +"language that prefers returning `Result`." msgstr "" -#: src/iterators/intoiterator.md -msgid "\"point = {x}, {y}\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md +msgid "" +"**Answer:** Panics are for unrecoverable, programming errors. A library " +"should not panic unless a contract is violated by the caller. Documenting " +"these contracts is essential." msgstr "" -#: src/iterators/intoiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md msgid "" -"Click through to the docs for `IntoIterator`. Every implementation of " -"`IntoIterator` must declare two types:" +"`# Safety` comments document safety preconditions on unsafe functions that " +"must be satisfied, or else undefined behavior might result. They are " +"discussed in detail in the Unsafe Rust deep dive." msgstr "" -#: src/iterators/intoiterator.md -msgid "`Item`: the type to iterate over, such as `i8`," +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +msgid "Name-dropping keywords and signposting topics" msgstr "" -#: src/iterators/intoiterator.md -msgid "`IntoIter`: the `Iterator` type returned by the `into_iter` method." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +msgid "" +"/// A parsed representation of a MARC 21 record\n" +"/// [leader](//www.loc.gov/marc/bibliographic/bdleader.html). \n" +"/// A MARC leader contains metadata that dictates how to interpret the " +"rest \n" +"/// of the record.\n" msgstr "" -#: src/iterators/intoiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"Note that `IntoIter` and `Item` are linked: the iterator must have the same " -"`Item` type, which means that it returns `Option`" +"/// Determines the schema and the set of valid subsequent data fields. \n" +" ///\n" +" /// Encoded in byte 6 of the leader. \n" msgstr "" -#: src/iterators/intoiterator.md -msgid "The example iterates over all combinations of x and y coordinates." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +msgid "" +"/// Indicates whether to parse relationship fields, such as a \"773 Host \n" +" /// Item Entry\" for an article within a larger work. \n" +" /// \n" +" /// Encoded in byte 7 of the leader. \n" msgstr "" -#: src/iterators/intoiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +msgid "// ... other fields\n" +msgstr "" + +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"Try iterating over the grid twice in `main`. Why does this fail? Note that " -"`IntoIterator::into_iter` takes ownership of `self`." +"/// Parses the [leader of a MARC 21 record](https://www.loc.gov/marc/" +"bibliographic/bdleader.html). \n" +"/// \n" +"/// The leader is encoded as a fixed-length 24-byte field, containing " +"metadata \n" +"/// that determines the semantic interpretation of the rest of the " +"record. \n" msgstr "" -#: src/iterators/intoiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"Fix this issue by implementing `IntoIterator` for `&Grid` and storing a " -"reference to the `Grid` in `GridIter`." +"Motivation: Readers of documentation will not be closely reading most of " +"your doc comments like they would dialogue in a novel they love." msgstr "" -#: src/iterators/intoiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"The same problem can occur for standard library types: `for e in " -"some_vector` will take ownership of `some_vector` and iterate over owned " -"elements from that vector. Use `for e in &some_vector` instead, to iterate " -"over references to elements of `some_vector`." +"Users will most likely be skimming and scan-reading to find the part of the " +"documentation that is relevant to whatever problem they're trying to solve " +"in the moment." +msgstr "" + +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +msgid "" +"Once a user has found a keyword or potential signpost that's relevant to " +"them they will begin to search for context surrounding what is being " +"documented." +msgstr "" + +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +msgid "" +"Ask the class: What do you look for in documentation? Focus on the moment-to-" +"moment searching for information here, not general values in documentation." msgstr "" -#: src/iterators/fromiterator.md -msgid "FromIterator" -msgstr "FromIterator" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +msgid "Name-drop keywords close to the beginning of a paragraph." +msgstr "" -#: src/iterators/fromiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"[`FromIterator`](https://doc.rust-lang.org/std/iter/trait.FromIterator.html) " -"lets you build a collection from an [`Iterator`](https://doc.rust-lang.org/" -"std/iter/trait.Iterator.html)." +"This aids skimming and scanning, as the first few words of a paragraph stand " +"out the most." msgstr "" -"[`FromIterator`](https://doc.rust-lang.org/std/iter/trait.FromIterator.html) " -"āφāĻĒāύāĻžāϕ⧇ [`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) " -"āĻĨ⧇āϕ⧇ āĻāĻ•āϟāĻŋ āϏāĻ‚āĻ—ā§āϰāĻš āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āĻĻ⧇āϝāĻŧ|" - -#: src/iterators/fromiterator.md -msgid "\"prime_squares: {prime_squares:?}\"" -msgstr "\"prime_squares: {prime_squares:?}\"" -#: src/iterators/fromiterator.md -msgid "`Iterator` implements" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +msgid "" +"Skimming and scanning lets users quickly navigate a text, keeping keywords " +"as close to the beginning of a paragraph as possible lets a user determine " +"if they've found relevant information faster." msgstr "" -#: src/iterators/fromiterator.md -msgid "There are two ways to specify `B` for this method:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md +msgid "Signpost, but don't over-explain." msgstr "" -#: src/iterators/fromiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"With the \"turbofish\": `some_iterator.collect::()`, as " -"shown. The `_` shorthand used here lets Rust infer the type of the `Vec` " -"elements." +"Users will not necessarily have the same domain expertise as an API designer." msgstr "" -#: src/iterators/fromiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"With type inference: `let prime_squares: Vec<_> = some_iterator.collect()`. " -"Rewrite the example to use this form." +"If a tangential, specialist term or acronym is mentioned try to bring in " +"enough context such that a novice could quickly do more research." msgstr "" -#: src/iterators/fromiterator.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"There are basic implementations of `FromIterator` for `Vec`, `HashMap`, etc. " -"There are also more specialized implementations which let you do cool things " -"like convert an `Iterator>` into a `Result, E>`." +"Signposting often happens organically, consider a networking library that " +"mentions various protocols. But when it doesn't happen organically, it can " +"be difficult to choose what to mention." msgstr "" -#: src/iterators/exercise.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"In this exercise, you will need to find and use some of the provided methods " -"in the [`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) " -"trait to implement a complex calculation." +"Rule of thumb: API developers should be asking themselves \"if a novice ran " +"into what they are documenting, what sources would they look up and are " +"there any red herrings they might end up following\"?" msgstr "" -#: src/iterators/exercise.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"Copy the following code to and make the tests " -"pass. Use an iterator expression and `collect` the result to construct the " -"return value." +"Users should be given enough information to look up subjects on their own." msgstr "" -#: src/iterators/exercise.md src/iterators/solution.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md msgid "" -"/// Calculate the differences between elements of `values` offset by " -"`offset`,\n" -"/// wrapping around from the end of `values` to the beginning.\n" -"///\n" -"/// Element `n` of the result is `values[(n+offset)%len] - values[n]`.\n" +"What we've already covered, predictability of an API including the naming " +"conventions, is a form of signposting." msgstr "" -#: src/modules.md -msgid "[Modules](./modules/modules.md) (3 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "Avoiding Redundancy" msgstr "" -#: src/modules.md -msgid "[Filesystem Hierarchy](./modules/filesystem.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"Names and type signatures communicate a lot of information, don't repeat it " +"in comments!" msgstr "" -#: src/modules.md -msgid "[Visibility](./modules/visibility.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"// Repeats name/type information. Can omit!\n" +"/// Parses an ipv4 from a str. Returns an option for failure modes.\n" msgstr "" -#: src/modules.md -msgid "[use, super, self](./modules/paths.md) (10 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "// Repeats information obvious from the field name. Can omit!\n" msgstr "" -#: src/modules.md -msgid "" -"[Exercise: Modules for a GUI Library](./modules/exercise.md) (15 minutes)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "/// The customer id.\n" msgstr "" -#: src/modules/modules.md -msgid "We have seen how `impl` blocks let us namespace functions to a type." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"// Mentions the type name first thing, don't do this!\n" +"/// `ServerSynchronizer` is an orchestrator that sends local edits [...]\n" msgstr "" -#: src/modules/modules.md -msgid "Similarly, `mod` lets us namespace types and functions:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"// Better! Focuses on purpose.\n" +"/// Sends local edits [...]\n" msgstr "" -#: src/modules/modules.md -msgid "\"In the foo module\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"// Mentions the function name first thing, don't do this!\n" +"/// `sync_to_server` sends local edits [...]\n" msgstr "" -#: src/modules/modules.md -msgid "\"In the bar module\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"// Better! Focuses on function.\n" +"/// Sends local edits [...]\n" msgstr "" -#: src/modules/modules.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md msgid "" -"Packages provide functionality and include a `Cargo.toml` file that " -"describes how to build a bundle of 1+ crates." +"Motivation: Documentation that merely repeats name/signature information " +"provides nothing new to the API user." msgstr "" -#: src/modules/modules.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md msgid "" -"Crates are a tree of modules, where a binary crate creates an executable and " -"a library crate compiles to a library." +"Additionally, signature information may change over time without the " +"documentation being updated accordingly!" msgstr "" -#: src/modules/modules.md -msgid "Modules define organization, scope, and are the focus of this section." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "This is an understandable pattern to fall into!" msgstr "" -#: src/modules/filesystem.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md msgid "" -"Omitting the module content will tell Rust to look for it in another file:" +"Naive approach to \"always document your code,\" follows this advice " +"literally but does not follow the intent." msgstr "" -#: src/modules/filesystem.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md msgid "" -"This tells rust that the `garden` module content is found at `src/garden." -"rs`. Similarly, a `garden::vegetables` module can be found at `src/garden/" -"vegetables.rs`." +"Some tools might enforce documentation coverage, this kind of documentation " +"is an easy fix." msgstr "" -#: src/modules/filesystem.md -msgid "The `crate` root is in:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "Be aware of the purpose of different modes of documentation:" msgstr "" -#: src/modules/filesystem.md -msgid "`src/lib.rs` (for a library crate)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"Library code will need to be documented in ways that understand the scope of " +"what it is used for and the breadth of people who are trying to use it." msgstr "" -#: src/modules/filesystem.md -msgid "`src/main.rs` (for a binary crate)" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"Application code has a more narrow purpose, it can afford to be more simple " +"and direct." msgstr "" -#: src/modules/filesystem.md -msgid "" -"Modules defined in files can be documented, too, using \"inner doc " -"comments\". These document the item that contains them -- in this case, a " -"module." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "The name of an item is part of the documentation of that item." msgstr "" -#: src/modules/filesystem.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md msgid "" -"//! This module implements the garden, including a highly performant " -"germination" +"Similarly, the signature of a function is part of the documentation of that " +"function." msgstr "" -#: src/modules/filesystem.md -#, fuzzy -msgid "//! implementation." -msgstr "āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ" - -#: src/modules/filesystem.md -msgid "// Re-export types from this module." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"Therefore: Some aspects of the item are already covered when you start " +"writing doc comments!" msgstr "" -#: src/modules/filesystem.md -msgid "/// Sow the given seed packets." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "Do not repeat information for the sake of an itemized list." msgstr "" -#: src/modules/filesystem.md -msgid "/// Harvest the produce in the garden that is ready." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"Many areas of the standard library have minimal documentation because the " +"name and types do give enough information." msgstr "" -#: src/modules/filesystem.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md msgid "" -"Before Rust 2018, modules needed to be located at `module/mod.rs` instead of " -"`module.rs`, and this is still a working alternative for editions after 2018." +"Rule of Thumb: What information is missing from a user's perspective? Other " +"than name, signature, and irrelevant details of the implementation." msgstr "" -#: src/modules/filesystem.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md msgid "" -"The main reason to introduce `filename.rs` as alternative to `filename/mod." -"rs` was because many files named `mod.rs` can be hard to distinguish in IDEs." +"Don't explain the basics of Rust or the standard library. Assume the reader " +"of doc comments has an intermediate understanding of the language itself. " +"Focus on documenting your API." msgstr "" -#: src/modules/filesystem.md -msgid "Deeper nesting can use folders, even if the main module is a file:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"For example, if your function returns `Result`, you don't need to explain " +"how `Result` or the question mark operators work." msgstr "" -#: src/modules/filesystem.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md msgid "" -"The place rust will look for modules can be changed with a compiler " -"directive:" +"If there is a complex topic involved with the functions and types you're " +"documenting, signpost to a \"source of truth\" if one exists such as an " +"internal document, a paper, a blog post etc." msgstr "" -#: src/modules/filesystem.md -msgid "\"some/path.rs\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"Collaborate with Students: Go through the methods in the slide and discuss " +"what might be relevant to an API user." msgstr "" -#: src/modules/filesystem.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md msgid "" -"This is useful, for example, if you would like to place tests for a module " -"in a file named `some_module_test.rs`, similar to the convention in Go." +"The `#![warn(missing_docs)]` lint can be helpful for enforcing the existence " +"of doc comments, but puts a large burden on developers that could lead to " +"leaning onto these patterns of writing low-quality comments." msgstr "" -#: src/modules/visibility.md -msgid "Modules are a privacy boundary:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +msgid "" +"This kind of lint should only be enabled if the people maintaining a project " +"can afford to keep up with its demands, and usually only for library-style " +"crates rather than application code." msgstr "" -#: src/modules/visibility.md -msgid "Module items are private by default (hides implementation details)." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "Names and Signatures are not full documentation" msgstr "" -#: src/modules/visibility.md -msgid "Parent and sibling items are always visible." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "" +"// bad\n" +"/// Returns a future that resolves when operation completes. \n" msgstr "" -#: src/modules/visibility.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md msgid "" -"In other words, if an item is visible in module `foo`, it's visible in all " -"the descendants of `foo`." +"// good\n" +"/// Sends local edits to the server, overwriting concurrent edits \n" +"/// if any happened. \n" msgstr "" -#: src/modules/visibility.md -msgid "\"outer::private\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "" +"// bad\n" +"/// Returns an error if sending the email fails. \n" msgstr "" -#: src/modules/visibility.md -msgid "\"outer::public\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "" +"// good\n" +"/// Queues the email for background delivery and returns immediately. \n" +"/// Returns an error immediately if the email is malformed. \n" msgstr "" -#: src/modules/visibility.md -msgid "\"outer::inner::private\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "" +"Motivation: API designers can over-commit to the idea that a function name " +"and signature is enough documentation." msgstr "" -#: src/modules/visibility.md -msgid "\"outer::inner::public\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "It's better than nothing, but it's worse than good documentation." msgstr "" -#: src/modules/visibility.md -msgid "Use the `pub` keyword to make modules public." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "" +"Again, names and types are _part_ of the documentation. They are not always " +"the full story!" msgstr "" -#: src/modules/visibility.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md msgid "" -"Additionally, there are advanced `pub(...)` specifiers to restrict the scope " -"of public visibility." +"Consider the behavior of functions that are not covered by the name, " +"parameter names, or signature of that function." msgstr "" -#: src/modules/visibility.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md msgid "" -"See the [Rust Reference](https://doc.rust-lang.org/reference/visibility-and-" -"privacy.html#pubin-path-pubcrate-pubsuper-and-pubself)." +"In the example on the slide it is not obvious that `sync_to_server()` could " +"overwrite something (leading to a data loss), so document that." msgstr "" -#: src/modules/visibility.md -msgid "Configuring `pub(crate)` visibility is a common pattern." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "" +"In the email example, it is not obvious that the function can return success " +"and still fail to deliver the email." msgstr "" -#: src/modules/visibility.md -msgid "Less commonly, you can give visibility to a specific path." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "" +"Use comments to disambiguate. Nuanced behaviors, behaviors that users of an " +"API could trip up on, should be documented." msgstr "" -#: src/modules/visibility.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md msgid "" -"In any case, visibility must be granted to an ancestor module (and all of " -"its descendants)." +"For example, consider a remove() method on a business entity: There are many " +"ways to remove an entity!" msgstr "" -#: src/modules/paths.md -msgid "use, super, self" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md +msgid "" +"Is it removing the entity from the database? From the parent collection in " +"memory (unlink vs erase)?" msgstr "" -#: src/modules/paths.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md msgid "" -"A module can bring symbols from another module into scope with `use`. You " -"will typically see something like this at the top of each module:" +"If it is removing the data in the database, is the data actually being " +"deleted, or merely marked as deleted, but still recoverable (soft vs hard " +"delete)?" msgstr "" -#: src/modules/paths.md -msgid "Paths" -msgstr "Paths" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +msgid "Why and What, not How and Where" +msgstr "" -#: src/modules/paths.md -msgid "Paths are resolved as follows:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +msgid "Avoid documenting irrelevant details that may frequently change." msgstr "" -#: src/modules/paths.md -msgid "As a relative path:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +msgid "/// Sorts a slice. Implemented using recursive quicksort.\n" msgstr "" -#: src/modules/paths.md -msgid "`foo` or `self::foo` refers to `foo` in the current module," +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "/* ... */" msgstr "" -#: src/modules/paths.md -msgid "`super::foo` refers to `foo` in the parent module." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +msgid "" +"// bad\n" +"/// Saves a `User` record to the Postgres database. \n" +"/// \n" +"/// This function opens a new connection and begins a transaction. It " +"checks \n" +"/// if a user with the given ID exists with a `SELECT` query. If a user " +"is \n" +"/// not found, performs an `INSERT`. \n" +"/// \n" +"/// # Errors \n" +"/// \n" +"/// Returns an error if any database operation fails. \n" msgstr "" -#: src/modules/paths.md -msgid "As an absolute path:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +msgid "" +"// good\n" +"/// Atomically saves a user record. \n" +"/// \n" +"/// # Errors \n" +"/// \n" +"/// Returns a `db::Error::DuplicateUsername` error if the user (keyed by \n" +"/// `user.username` field) already exists. \n" msgstr "" -#: src/modules/paths.md -msgid "`crate::foo` refers to `foo` in the root of the current crate," +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +msgid "" +"Motivation: Users want to know the contract of the API (what is guaranteed " +"about this function), rather than implementation details." msgstr "" -#: src/modules/paths.md -msgid "`bar::foo` refers to `foo` in the `bar` crate." +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +msgid "" +"Motivation: Doc comments that explain implementation details become outdated " +"faster than comments that explain the contract." msgstr "" -#: src/modules/paths.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md msgid "" -"It is common to \"re-export\" symbols at a shorter path. For example, the " -"top-level `lib.rs` in a crate might have" +"Internal information is likely irrelevant to a user. Imagine explaining in a " +"doc comment for a function that you're using for loops to solve a problem, " +"what is the point of this information?" msgstr "" -#: src/modules/paths.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md msgid "" -"making `DiskStorage` and `NetworkStorage` available to other crates with a " -"convenient, short path." +"Consider the `sort_quickly` function above. Its documentation calls out that " +"it uses quicksort, but is this necessary?" msgstr "" -#: src/modules/paths.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md msgid "" -"For the most part, only items that appear in a module need to be `use`'d. " -"However, a trait must be in scope to call any methods on that trait, even if " -"a type implementing that trait is already in scope. For example, to use the " -"`read_to_string` method on a type implementing the `Read` trait, you need to " -"`use std::io::Read`." +"It could be that another sorting function is used in the future, if that " +"were the case then this comment would need to be updated too. This is a " +"point of failure in documentation." msgstr "" -#: src/modules/paths.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md msgid "" -"The `use` statement can have a wildcard: `use std::io::*`. This is " -"discouraged because it is not clear which items are imported, and those " -"might change over time." +"It could be that the implementation is necessary to explain, but this is " +"likely due to whatever effects or invariants the user of that API needs to " +"be aware of instead." msgstr "" -#: src/modules/exercise.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md msgid "" -"In this exercise, you will reorganize a small GUI Library implementation. " -"This library defines a `Widget` trait and a few implementations of that " -"trait, as well as a `main` function." +"Focus on those effects and invariants instead of instead of the " +"implementation details themselves." msgstr "" -#: src/modules/exercise.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md msgid "" -"It is typical to put each type or set of closely-related types into its own " -"module, so each widget type should get its own module." +"Reiterate: Implementation details can and will change, so do not explain " +"these details." msgstr "" -#: src/modules/exercise.md -#, fuzzy -msgid "Cargo Setup" -msgstr "āϏ⧇āϟāφāĻĒ" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md +msgid "Don't talk about where something is used for the sake of it." +msgstr "" -#: src/modules/exercise.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md msgid "" -"The Rust playground only supports one file, so you will need to make a Cargo " -"project on your local filesystem:" +"This is another instance where this information can become stale quickly." msgstr "" -#: src/modules/exercise.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md msgid "" -"Edit the resulting `src/main.rs` to add `mod` statements, and add additional " -"files in the `src` directory." +"Focus on what the function does (not how it is implemented) for a user " +"trying to reach this practical information as quickly as possible." msgstr "" -#: src/modules/exercise.md -msgid "Source" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +msgid "Exercise: Dialog on Details" msgstr "" -#: src/modules/exercise.md -msgid "Here's the single-module implementation of the GUI library:" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +msgid "" +"Unnecessary details can sometimes be indicative of something that does need " +"documentation." msgstr "" -#: src/modules/exercise.md -msgid "/// Natural width of `self`.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +msgid "" +"Consider the example here, we discussed in [what and why, not how and where]" +"(what-why-not-how-where.md) that internal details are unlikely relevant to " +"someone reading documentation." msgstr "" -#: src/modules/exercise.md -msgid "/// Draw the widget into a buffer.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +msgid "Here we're discussing a counterexample." msgstr "" -#: src/modules/exercise.md -msgid "/// Draw the widget on standard output.\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +msgid "Ask the class: Is this comment necessary for this function?" msgstr "" -#: src/modules/exercise.md src/modules/solution.md -msgid "\"{buffer}\"" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +msgid "" +"Narrative: Playing the part of an intermediary between the class and the " +"author, such as a PM, manager, etc. tell the class that the author of this " +"function is pushing back." msgstr "" -#: src/modules/exercise.md -msgid "// Add 4 paddings for borders\n" +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md +msgid "Ask the class: Why would an author of this kind of comment push back?" msgstr "" -#: src/modules/exercise.md +#: src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md msgid "" -"// TODO: Change draw_into to return Result<(), std::fmt::Error>. Then use " -"the\n" -" // ?-operator here instead of .unwrap().\n" +"If the class asks why the author is pushing back, do not give details yet." msgstr "" -#: src/modules/exercise.md src/modules/solution.md -msgid "\"+-{:-. Then use" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/mut.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md +msgid "// Simplified\n" msgstr "" -#: src/modules/solution.md -msgid "// the ?-operator here instead of .unwrap()." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/mut.md +msgid "Suffix that signifies the method gives access to a mutable reference." msgstr "" -#: src/modules/solution.md -msgid "// ---- src/main.rs ----" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/mut.md +msgid "Requires mutable access to the value you're calling this method on." msgstr "" -#: src/testing.md -msgid "[Test Modules](./testing/unit-tests.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +msgid "`with` as constructor" msgstr "" -#: src/testing.md -msgid "[Other Types of Tests](./testing/other.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +msgid "" +"`with` as a constructor sets one value among a type while using default " +"values for the rest." msgstr "" -#: src/testing.md -msgid "[Useful Crates](./testing/useful-crates.md) (3 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +msgid "`with` as in \"`` with specific setting.\"" msgstr "" -#: src/testing.md -msgid "[GoogleTest](./testing/googletest.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +msgid "// Initializes memory for at least N elements, len is still 0.\n" msgstr "" -#: src/testing.md -msgid "[Mocking](./testing/mocking.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +msgid "" +"`with` can appear as a constructor prefix, most commonly when initializing " +"heap memory for container types." msgstr "" -#: src/testing.md -msgid "[Compiler Lints and Clippy](./testing/lints.md) (3 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +msgid "" +"In this case, it's distinct from `new` constructors because it specifies the " +"value for something that is not usually cared about by API users." msgstr "" -#: src/testing.md -msgid "[Exercise: Luhn Algorithm](./testing/exercise.md) (30 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +msgid "Ask the class: Why not `from_capacity`?" msgstr "" -#: src/testing/unit-tests.md -msgid "Unit Tests" -msgstr "āχāωāύāĻŋāϟ āĻŸā§‡āĻ¸ā§āϟ" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md +msgid "" +"Answer: `Vec::with_capacity` as a method call scans well as creating a \"Vec " +"with capacity\". Consider how `Vec::new_capacity` or `Vec::from_capacity` " +"scan when written down, they do not communicate what's going on well." +msgstr "" -#: src/testing/unit-tests.md -msgid "Rust and Cargo come with a simple unit test framework:" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md +msgid "`with` as copy-and-set" msgstr "" -#: src/testing/unit-tests.md -msgid "Unit tests are supported throughout your code." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md +msgid "" +"`with` appears when a value is being copied, but also changed in a specific " +"way." msgstr "" -#: src/testing/unit-tests.md -msgid "Integration tests are supported via the `tests/` directory." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md +msgid "`with` as in \"like ``, but with something different.\"" msgstr "" -#: src/testing/unit-tests.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md msgid "" -"Tests are marked with `#[test]`. Unit tests are often put in a nested " -"`tests` module, using `#[cfg(test)]` to conditionally compile them only when " -"building tests." +"// Simplified. \"/home/me/mortgage.pdf\".with_extension(\"mov\") =>\n" +" // \"/home/me/mortgage.mov\"\n" msgstr "" -#: src/testing/unit-tests.md -#, fuzzy -msgid "\"Hello World\"" -msgstr "Hello World!" - -#: src/testing/unit-tests.md -msgid "This lets you unit test private helpers." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md +msgid "" +"`with` can be used for methods that copy a value, but then change a specific " +"part of that value." msgstr "" -#: src/testing/unit-tests.md -msgid "The `#[cfg(test)]` attribute is only active when you run `cargo test`." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md +msgid "" +"In the example here, `with_extension` copies the data of a `&Path` into a " +"new `PathBuf`, but changes the extension to something else." msgstr "" -#: src/testing/unit-tests.md -msgid "Run the tests in the playground in order to show their results." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md +msgid "The original `Path` is unchanged." msgstr "" -#: src/testing/other.md -msgid "Integration Tests" -msgstr "āχāĻ¨ā§āϟāĻŋāĻ—ā§āϰ⧇āĻļāύ āĻŸā§‡āĻ¸ā§āϟ" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md +msgid "`with`: Working with Closures" +msgstr "" -#: src/testing/other.md -msgid "If you want to test your library as a client, use an integration test." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md +msgid "`with` as in \"do X, but with this specific way of computing things.\"" msgstr "" -#: src/testing/other.md -msgid "Create a `.rs` file under `tests/`:" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md +msgid "" +"// Simplified. If the resize is larger than the current vec size, use the\n" +" // closure to populate elements.\n" msgstr "" -#: src/testing/other.md -msgid "// tests/my_library.rs" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md +msgid "// Create an infinite, lazy iterator using a closure.\n" msgstr "" -#: src/testing/other.md -msgid "These tests only have access to the public API of your crate." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md +msgid "" +"`with` can appear as a suffix to communicate there is a specific function or " +"closure that can be used instead of a \"sensible default\" for a computation." msgstr "" -#: src/testing/other.md -msgid "Documentation Tests" -msgstr "āĻĄāϕ⧁āĻŽā§‡āĻ¨ā§āĻŸā§‡āĻļāύ āĻŸā§‡āĻ¸ā§āϟ" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md +msgid "Similar to [`by`](./by.md)." +msgstr "" -#: src/testing/other.md -msgid "Rust has built-in support for documentation tests:" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +msgid "`with` in normal use" msgstr "" -#: src/testing/other.md -msgid "/// Shortens a string to the given length." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +msgid "Sometimes a `with` is just a `with`." msgstr "" -#: src/testing/other.md -msgid "/// ```" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +msgid "`with` when used in common English contexts." msgstr "" -#: src/testing/other.md -msgid "/// # use playground::shorten_string;" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +msgid "// impl block for slices\n" msgstr "" -#: src/testing/other.md -msgid "/// assert_eq!(shorten_string(\"Hello World\", 5), \"Hello\");" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +msgid "" +"// A condition, but doesn't start with `is`, and uses `with` as a normal " +"word.\n" msgstr "" -#: src/testing/other.md -msgid "/// assert_eq!(shorten_string(\"Hello World\", 20), \"Hello World\");" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +msgid "" +"Name fragments are not hard rules, they are guidance. Sometimes a method's " +"name will include words that break its pattern." msgstr "" -#: src/testing/other.md -msgid "Code blocks in `///` comments are automatically seen as Rust code." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +msgid "" +"In this example with have `starts_with`, which is a boolean condition that " +"does not start with \"is\" and is suffixed by \"with\"." msgstr "" -#: src/testing/other.md -msgid "The code will be compiled and executed as part of `cargo test`." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md +msgid "" +"If naming conventions were to be treated as hard rules, this would fail as a " +"case." msgstr "" -#: src/testing/other.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md msgid "" -"Adding `#` in the code will hide it from the docs, but will still compile/" -"run it." +"This is a good name for understanding what is going on at the callsite. We " +"end up writing `.starts_with()` which scans well for " +"authors and readers of code." msgstr "" -#: src/testing/other.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md msgid "" -"Test the above code on the [Rust Playground](https://play.rust-lang.org/?" -"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." +"Remember: the point of naming conventions is predictability, and how " +"predictability is in service of callsite clarity and readability." msgstr "" -#: src/testing/useful-crates.md -msgid "Rust comes with only basic support for writing tests." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md +msgid "`try_[method]`: Fallible methods with Specific Errors" msgstr "" -#: src/testing/useful-crates.md -msgid "Here are some additional crates which we recommend for writing tests:" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md +msgid "Prefix for fallible methods that return a `Result`." msgstr "" -#: src/testing/useful-crates.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md msgid "" -"[googletest](https://docs.rs/googletest): Comprehensive test assertion " -"library in the tradition of GoogleTest for C++." +"`TryFrom` is a `From`\\-like trait for types whose single-value constructors " +"might fail in some way." msgstr "" -#: src/testing/useful-crates.md -msgid "[proptest](https://docs.rs/proptest): Property-based testing for Rust." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md +msgid "Ask: Why aren't `Vec::get` and other similar methods called `try_get`?" msgstr "" -#: src/testing/useful-crates.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md msgid "" -"[rstest](https://docs.rs/rstest): Support for fixtures and parameterised " -"tests." +"Methods are named `get` if they return a reference to an existing value and " +"return an `Option` instead of `Result` because there is only one failure " +"mode. For example, only \"index out of bounds\" for `Vec::get`, and \"key " +"does not exist\" for `HashMap::get`." msgstr "" -#: src/testing/googletest.md -msgid "" -"The [GoogleTest](https://docs.rs/googletest/) crate allows for flexible test " -"assertions using _matchers_:" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md +msgid "`from`" msgstr "" -#: src/testing/googletest.md -msgid "\"baz\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md +msgid "A constructor function, strongly implying \"type conversion\"." msgstr "" -#: src/testing/googletest.md -msgid "\"xyz\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md +msgid "" +"These functions can take multiple arguments, but usually imply the user is " +"doing more of the work than a usual constructor would." msgstr "" -#: src/testing/googletest.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md msgid "" -"If we change the last element to `\"!\"`, the test fails with a structured " -"error message pin-pointing the error:" +"`new` is still preferred for most constructor-style functions, the " +"implication for `from` is transformation of one data type to another." msgstr "" -#: src/testing/googletest.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md msgid "" -"GoogleTest is not part of the Rust Playground, so you need to run this " -"example in a local environment. Use `cargo add googletest` to quickly add it " -"to an existing Cargo project." +"Ask: Without looking at the standard library documentation, what would the " +"argument type of `u32::from_be` be?" msgstr "" -#: src/testing/googletest.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md msgid "" -"The `use googletest::prelude::*;` line imports a number of [commonly used " -"macros and types](https://docs.rs/googletest/latest/googletest/prelude/index." -"html)." +"Answer guidance: we already see `u32::from_le_bytes` on the slide, it takes " +"a slice of bytes. So from_le must be simpler, taking not bytes. Think about " +"the contrast between `u32` and `be`. The argument must be a big-endian `u32`!" msgstr "" -#: src/testing/googletest.md -msgid "This just scratches the surface, there are many builtin matchers." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md +msgid "Follow-up question: How about `str::from_utf8`?" msgstr "" -#: src/testing/googletest.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md msgid "" -"A particularly nice feature is that mismatches in multi-line strings are " -"shown as a diff:" +"Answer guidance: `str` vs `utf8`. The argument can't be a `str` because " +"every `str` is valid UTF-8. So what is the simplest way to provide UTF-8 " +"data? A slice of bytes." msgstr "" -#: src/testing/googletest.md -msgid "" -"\"Memory safety found,\\n\\\n" -" Rust's strong typing guides the way,\\n\\\n" -" Secure code you'll write.\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md +msgid "Follow-up: Why not `str::from_utf8_bytes`?" msgstr "" -#: src/testing/googletest.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md msgid "" -"\"Memory safety found,\\n\\\n" -" Rust's silly humor guides the way,\\n\\\n" -" Secure code you'll write.\"" +"Answer: It could be in theory. However, the \"omit needless words\" " +"principle applies, the word \"bytes\" would merely repeat the obvious - " +"could a UTF-8 sequence ever be non-bytes?" msgstr "" -#: src/testing/googletest.md -msgid "shows a color-coded diff (colors not shown here):" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md +msgid "`into`" +msgstr "" + +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md +msgid "Prefix for methods that convert `self` into another type." msgstr "" -#: src/testing/googletest.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md +msgid "Consumes `self`, returns an owned value." +msgstr "" + +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md msgid "" -"The crate is a Rust port of [GoogleTest for C++](https://google.github.io/" -"googletest/)." +"Not reinterpret cast! The data can be rearranged, reallocated, changed in " +"any way, including losing information." msgstr "" -#: src/testing/googletest.md -msgid "GoogleTest is available for use in AOSP." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md +msgid "corollary to `From`" msgstr "" -#: src/testing/mocking.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md msgid "" -"For mocking, [Mockall](https://docs.rs/mockall/) is a widely used library. " -"You need to refactor your code to use traits, which you can then quickly " -"mock:" +"`into_iter` consumes a collection (like a vec, or a btreeset, or a hashmap) " +"and produces an iterator over owned values, unlike `iter` and `iter_mut` " +"which produce iterators over reference values." +msgstr "" + +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md +msgid "Ask the class: what will `Vec::into_raw_parts` do?" +msgstr "" + +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md +msgid "Aside: `into_inner`" msgstr "" -#: src/testing/mocking.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md msgid "" -"The advice here is for Android (AOSP) where Mockall is the recommended " -"mocking library. There are other [mocking libraries available on crates.io]" -"(https://crates.io/keywords/mock), in particular in the area of mocking HTTP " -"services. The other mocking libraries work in a similar fashion as Mockall, " -"meaning that they make it easy to get a mock implementation of a given trait." +"Special case of `into`: for exclusive pointer types or newtypes, extract the " +"internal value." msgstr "" -#: src/testing/mocking.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md msgid "" -"Note that mocking is somewhat _controversial_: mocks allow you to completely " -"isolate a test from its dependencies. The immediate result is faster and " -"more stable test execution. On the other hand, the mocks can be configured " -"wrongly and return output different from what the real dependencies would do." +"`into_inner` is a method usually found on newtypes: types whose main purpose " +"is to wrap around an existing type and be semantically distinct from other " +"uses of that inner type." msgstr "" -#: src/testing/mocking.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md msgid "" -"If at all possible, it is recommended that you use the real dependencies. As " -"an example, many databases allow you to configure an in-memory backend. This " -"means that you get the correct behavior in your tests, plus they are fast " -"and will automatically clean up after themselves." +"This kind of method is also found on types like `Cell`, which exclusively " +"own the internal data." msgstr "" -#: src/testing/mocking.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md msgid "" -"Similarly, many web frameworks allow you to start an in-process server which " -"binds to a random port on `localhost`. Always prefer this over mocking away " -"the framework since it helps you test your code in the real environment." +"The purpose of this kind of method is to consume the \"wrapper\" type and " +"return the \"contained\" value." msgstr "" -#: src/testing/mocking.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md msgid "" -"Mockall is not part of the Rust Playground, so you need to run this example " -"in a local environment. Use `cargo add mockall` to quickly add Mockall to an " -"existing Cargo project." +"When defining a type with exactly one field, consider if it makes sense to " +"implement an `into_inner` method that consumes `self` and returns the field " +"as an owned value." msgstr "" -#: src/testing/mocking.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md msgid "" -"Mockall has a lot more functionality. In particular, you can set up " -"expectations which depend on the arguments passed. Here we use this to mock " -"a cat which becomes hungry 3 hours after the last time it was fed:" +"Don't write a method like this if more fields will be added in the future." +msgstr "" + +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md +msgid "`by`: custom comparator or projection" msgstr "" -#: src/testing/mocking.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md msgid "" -"You can use `.times(n)` to limit the number of times a mock method can be " -"called to `n` --- the mock will automatically panic when dropped if this " -"isn't satisfied." +"Component for methods that take a custom projection or comparison function." msgstr "" -#: src/testing/lints.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md msgid "" -"The Rust compiler produces fantastic error messages, as well as helpful " -"built-in lints. [Clippy](https://doc.rust-lang.org/clippy/) provides even " -"more lints, organized into groups that can be enabled per-project." +"// Uses a predicate to determine what items end up in non-overlapping " +"chunks.\n" msgstr "" -#: src/testing/lints.md -msgid "\"X probably fits in a u16, right? {}\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md +msgid "// Provided method of Iterator. Simplified.\n" msgstr "" -#: src/testing/lints.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md msgid "" -"Run the code sample and examine the error message. There are also lints " -"visible here, but those will not be shown once the code compiles. Switch to " -"the Playground site to show those lints." +"A projection function here being a function that, given a reference to a " +"value that exists in the data structure, will compute a value to perform the " +"principle computation with." msgstr "" -#: src/testing/lints.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md msgid "" -"After resolving the lints, run `clippy` on the playground site to show " -"clippy warnings. Clippy has extensive documentation of its lints, and adds " -"new lints (including default-deny lints) all the time." +"Methods like `sort_by_key` allow us to sort by _the hash function I've " +"passed to the method_ or sort by _this specific field of the data in the " +"slice_." msgstr "" -#: src/testing/lints.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md msgid "" -"Note that errors or warnings with `help: ...` can be fixed with `cargo fix` " -"or via your editor." +"For example, if you have a slice of values of some data structure you might " +"want to sort them by a field of that data structure, or even a hash value of " +"that data." msgstr "" -#: src/testing/exercise.md -msgid "Luhn Algorithm" -msgstr "āϞ⧁āύ āĻ…ā§āϝāĻžāϞāĻ—āϰāĻŋāĻĻāĻŽ" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md +msgid "`sort_by` takes a comparator function directly." +msgstr "" -#: src/testing/exercise.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md msgid "" -"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used " -"to validate credit card numbers. The algorithm takes a string as input and " -"does the following to validate the credit card number:" +"Most often seen in methods that sort or otherwise manipulate a slice with a " +"custom sort or comparison function rather than by the `Ord` implementation " +"of the type itself." msgstr "" -#: src/testing/exercise.md -msgid "Ignore all spaces. Reject number with fewer than two digits." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md +msgid "Sometimes the \"by\" preposition is simply a preposition." msgstr "" -#: src/testing/exercise.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md msgid "" -"Moving from **right to left**, double every second digit: for the number " -"`1234`, we double `3` and `1`. For the number `98765`, we double `6` and `8`." +"\"by\", like some other name components, may end up in a method name for " +"normal linguistic reasons rather than holding specific naming convention " +"semantic weight." msgstr "" -#: src/testing/exercise.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md msgid "" -"After doubling a digit, sum the digits if the result is greater than 9. So " -"doubling `7` becomes `14` which becomes `1 + 4 = 5`." +"[`Read::by_ref()`](https://doc.rust-lang.org/std/io/trait.Read.html#method." +"by_ref)" msgstr "" -#: src/testing/exercise.md -msgid "Sum all the undoubled and doubled digits." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md +msgid "" +"[`Iterator::advance_by()`](https://doc.rust-lang.org/std/iter/trait.Iterator." +"html#method.advance_by) iterator method (nightly feature)" msgstr "" -#: src/testing/exercise.md -msgid "The credit card number is valid if the sum ends with `0`." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "`unchecked`: Unsafe" msgstr "" -#: src/testing/exercise.md -msgid "" -"The provided code provides a buggy implementation of the luhn algorithm, " -"along with two basic unit tests that confirm that most the algorithm is " -"implemented correctly." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "`unchecked` distinguishes the unsafe function in a safe/unsafe pair." msgstr "" -#: src/testing/exercise.md -msgid "" -"Copy the code below to and write additional " -"tests to uncover bugs in the provided implementation, fixing any bugs you " -"find." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "Don't add \"unchecked\" to the name of every unsafe function." msgstr "" -#: src/testing/exercise.md src/testing/solution.md -msgid "\"4263 9826 4026 9299\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "// A checked version of the constructor, `None` on null.\n" msgstr "" -#: src/testing/exercise.md src/testing/solution.md -msgid "\"4539 3195 0343 6467\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "// Unchecked constructor, you can violate the non-null invariant!\n" msgstr "" -#: src/testing/exercise.md src/testing/solution.md -msgid "\"7992 7398 713\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "// Panics on OOB, old API design.\n" msgstr "" -#: src/testing/exercise.md src/testing/solution.md -msgid "\"4223 9826 4026 9299\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "// Newer method, returns `None` if mid > len\n" msgstr "" -#: src/testing/exercise.md src/testing/solution.md -msgid "\"4539 3195 0343 6476\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "" +"// Unchecked split function, splitting out of bounds is undefined behavior!\n" msgstr "" -#: src/testing/exercise.md src/testing/solution.md -msgid "\"8273 1232 7352 0569\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "" +"Please take the Unsafe Rust deep dive if you want to learn more about unsafe " +"code. Briefly, unsafe functions transfer the responsibility for memory " +"safety from the compiler to the programmer. If misused, they can trigger " +"undefined behavior." msgstr "" -#: src/testing/solution.md -msgid "// This is the buggy version that appears in the problem.\n" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "" +"Rust does not overload functions on safety, so we use different names for " +"the functions in the pair. To make the names predictable for users, we use a " +"naming convention." msgstr "" -#: src/testing/solution.md -msgid "// This is the solution and passes all of the tests below.\n" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "" +"The safe function gets the short name. We add \"unchecked\" to the name of " +"the unsafe function." msgstr "" -#: src/testing/solution.md -msgid "\"1234 5678 1234 5670\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "We don't add \"unchecked\" to the name of every unsafe function." msgstr "" -#: src/testing/solution.md -msgid "\"Is {cc_number} a valid credit card number? {}\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "" +"In Rust we don't need a naming convention to highlight the danger of unsafe " +"code at the callsite: Rust already requires the caller to write an `unsafe {}" +"` block. This is different from other languages that don't have unsafe " +"blocks, for example, Swift naming convention is to add the word \"unsafe\" " +"to the type and function names." msgstr "" -#: src/testing/solution.md -msgid "\"yes\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md +msgid "" +"We only use this naming convention when we want to provide a function pair, " +"and therefore must use different names." msgstr "" -#: src/testing/solution.md -msgid "\"no\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "`to`: Non-consuming Conversion" msgstr "" -#: src/testing/solution.md -msgid "\"foo 0 0\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"Prefix to a function that takes a borrowed value and creates an owned value" msgstr "" -#: src/testing/solution.md -msgid "\" \"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "// &str is not consumed.\n" msgstr "" -#: src/testing/solution.md -msgid "\" \"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "// take an owned self because `u32` implements `Copy`\n" msgstr "" -#: src/testing/solution.md -msgid "\" \"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"This is not a borrow checker escape hatch, or an instance of unsafe code. A " +"new value is created, the original data is left alone." msgstr "" -#: src/testing/solution.md -msgid "\"0\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"Methods that start with \"to\" return a different type, and strongly imply a " +"non-trivial type conversion, or even a data transformation. For example, " +"`str::to_uppercase`." msgstr "" -#: src/testing/solution.md -msgid "\" 0 0 \"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"\"to\" methods most commonly take `&self`. However they can take `self` by " +"value if the type implements `Copy`: this also ensures that the conversion " +"method call does not consume `self`." msgstr "" -#: src/welcome-day-4-afternoon.md -msgid "[Error Handling](./error-handling.md) (55 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"If you simply want to define a method that takes `&self` and returns an " +"owned value of the same type, implement the `Clone` trait." msgstr "" -#: src/welcome-day-4-afternoon.md -msgid "[Unsafe Rust](./unsafe-rust.md) (1 hour and 5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"Example: to_uppercase creates a version of a string with all uppercase " +"letters." msgstr "" -#: src/error-handling.md -msgid "[Panics](./error-handling/panics.md) (3 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"If you want to define a method that consumes the source value, use the " +"\"into\" naming pattern." msgstr "" -#: src/error-handling.md -msgid "[Try Operator](./error-handling/try.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"Also seen in functions that convert the endianness of primitives, or copy " +"and expose the value of a newtype." msgstr "" -#: src/error-handling.md -msgid "[Try Conversions](./error-handling/try-conversions.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"Ask the class: What's the difference between `to_owned` and `into_owned`?" msgstr "" -#: src/error-handling.md -msgid "[Error Trait](./error-handling/error.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +msgid "" +"Answer: `to_owned` appears on reference values like `&str`, whereas " +"`into_owned` appears on owned values that hold reference types, like `Cow` " +"(copy-on-write)." msgstr "" -#: src/error-handling.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md msgid "" -"[thiserror and anyhow](./error-handling/thiserror-and-anyhow.md) (5 minutes)" +"Types like `Cow` can be owned while containing references that are borrowed, " +"so the owned value of `Cow` is consumed to create an owned value of the " +"reference type it was holding onto." msgstr "" -#: src/error-handling.md -msgid "" -"[Exercise: Rewriting with Result](./error-handling/exercise.md) (30 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "`as_` and `_ref`: reference conversions" msgstr "" -#: src/error-handling/panics.md -msgid "Rust handles fatal errors with a \"panic\"." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "" +"`as` is a prefix for methods that convert references. `ref` is a suffix (but " +"prefer `as`.)" msgstr "" -#: src/error-handling/panics.md -msgid "Rust will trigger a panic if a fatal error happens at runtime:" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "`as` methods borrow out the primary piece of data contained in `&self`." msgstr "" -#: src/error-handling/panics.md -msgid "\"v[100]: {}\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "" +"Most commonly return references, but can also return a custom borrowing type " +"or an unsafe pointer." msgstr "" -#: src/error-handling/panics.md -msgid "Panics are for unrecoverable and unexpected errors." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "// Very common on container types, see how it's also on Option.\n" +msgstr "" + +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "// Slices can be empty! So this is 0 or 1 elements.\n" msgstr "" -#: src/error-handling/panics.md -msgid "Panics are symptoms of bugs in the program." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "// Covered later.\n" msgstr "" -#: src/error-handling/panics.md -msgid "Runtime failures like failed bounds checks can panic" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "Method that returns a borrow of the primary piece of contained data." msgstr "" -#: src/error-handling/panics.md -msgid "Assertions (such as `assert!`) panic on failure" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "" +"The borrowing relationship is most often straightforward: the return value " +"is a reference that borrows `self`." msgstr "" -#: src/error-handling/panics.md -msgid "Purpose-specific panics can use the `panic!` macro." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "Borrowing can also be subtle, and merely implied." msgstr "" -#: src/error-handling/panics.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md msgid "" -"A panic will \"unwind\" the stack, dropping values just as if the functions " -"had returned." +"The returned value could be a custom borrowing type, fore example, " +"`BorrowedFd` borrows `OwnedFd` through an explicit lifetime." msgstr "" -#: src/error-handling/panics.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md msgid "" -"Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." +"We cover custom borrowing types later in this deep dive, [PhantomData: " +"OwnedFd & BorrowedFd](../../../leveraging-the-type-system/borrow-checker-" +"invariants/phantomdata-04-borrowedfd.md)." msgstr "" -#: src/error-handling/panics.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md msgid "" -"By default, a panic will cause the stack to unwind. The unwinding can be " -"caught:" +"The returned value could borrow `self` only logically, for example, " +"`as_ptr()` methods return an unsafe pointer. The borrow checker does not " +"track borrowing for pointers." msgstr "" -#: src/error-handling/panics.md -msgid "\"No problem here!\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "" +"The type implementing an \"as\" method should contain one primary piece of " +"data that is being borrowed out." msgstr "" -#: src/error-handling/panics.md -msgid "\"{result:?}\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "" +"The \"as\" naming convention does not work if the data type is an aggregate " +"of many fields without an obvious primary one. Think about the call site:" msgstr "" -#: src/error-handling/panics.md -msgid "\"oh no!\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "// OK\n" msgstr "" -#: src/error-handling/panics.md -msgid "" -"Catching is unusual; do not attempt to implement exceptions with " -"`catch_unwind`!" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md +msgid "// does not read right, don't use \"as_\"\n" msgstr "" -#: src/error-handling/panics.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md msgid "" -"This can be useful in servers which should keep running even if a single " -"request crashes." +"If you want to have two getters that you need to distinguish, one that " +"returns first name by value, and another one that returns it by reference, " +"use `_ref` suffix:" msgstr "" -#: src/error-handling/panics.md -msgid "This does not work if `panic = 'abort'` is set in your `Cargo.toml`." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md +msgid "`raw_parts`" msgstr "" -#: src/error-handling/try.md -msgid "" -"Runtime errors like connection-refused or file-not-found are handled with " -"the `Result` type, but matching this type on every call can be cumbersome. " -"The try-operator `?` is used to return errors to the caller. It lets you " -"turn the common" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md +msgid "Peeling back safe abstractions on heap data." msgstr "" -#: src/error-handling/try.md -msgid "into the much simpler" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md +msgid "// Note how this is an unsafe function\n" msgstr "" -#: src/error-handling/try.md -msgid "We can use this to simplify our error handling code:" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md +msgid "" +"`raw_parts` denotes methods that construct items from or decompose items " +"into underlying pointer data and its relevant layout information (capacity, " +"etc.)." msgstr "" -#: src/error-handling/try.md -msgid "//fs::write(\"config.dat\", \"alice\").unwrap();" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md +msgid "" +"These kinds of methods can be marked as `unsafe` if constructing new values " +"as trust is placed on the user to avoid conditions that might lead to " +"undefined behavior." msgstr "" -#: src/error-handling/try.md src/error-handling/try-conversions.md -#: src/error-handling/thiserror-and-anyhow.md -msgid "\"config.dat\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md +msgid "" +"Such a case might be passing a pointer of `sizeof T * 10` to `Vec::" +"from_raw_parts` but also passing `20` as the capacity argument, which would " +"lead to writing or accessing values 10 through 19 in the vector being " +"undefined behavior." msgstr "" -#: src/error-handling/try.md src/error-handling/try-conversions.md -msgid "\"username or error: {username:?}\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "What do these names imply they do?" msgstr "" -#: src/error-handling/try.md -msgid "Simplify the `read_username` function to use `?`." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "What should we name these signatures?" msgstr "" -#: src/error-handling/try.md -msgid "The `username` variable can be either `Ok(string)` or `Err(error)`." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "// What are the types of these methods?\n" msgstr "" -#: src/error-handling/try.md -msgid "" -"Use the `fs::write` call to test out the different scenarios: no file, empty " -"file, file with username." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "// ?\n" msgstr "" -#: src/error-handling/try.md -msgid "" -"Note that `main` can return a `Result<(), E>` as long as it implements `std::" -"process::Termination`. In practice, this means that `E` implements `Debug`. " -"The executable will print the `Err` variant and return a nonzero exit status " -"on error." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "// What should we name methods with these types?\n" msgstr "" -#: src/error-handling/try-conversions.md -msgid "" -"The effective expansion of `?` is a little more complicated than previously " -"indicated:" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "// details for InnerType do not matter.\n" msgstr "" -#: src/error-handling/try-conversions.md -msgid "works the same as" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "" +"Go through the methods in the example with the class and discuss what the " +"types of the functions should be." msgstr "" -#: src/error-handling/try-conversions.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md msgid "" -"The `From::from` call here means we attempt to convert the error type to the " -"type returned by the function. This makes it easy to encapsulate errors into " -"higher-level errors." +"Go through the unnamed methods and brainstorm what names those methods " +"should have." msgstr "" -#: src/error-handling/try-conversions.md -msgid "\"IO error: {e}\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "Answers for missing types:" msgstr "" -#: src/error-handling/try-conversions.md -msgid "\"Found no username in {path}\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "`Option::is_some(&self) -> bool`" msgstr "" -#: src/error-handling/try-conversions.md -#: src/error-handling/thiserror-and-anyhow.md -msgid "//fs::write(\"config.dat\", \"\").unwrap();" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "`slice::get(&self /* &[T] */, usize) -> Option<&T>`" msgstr "" -#: src/error-handling/try-conversions.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md msgid "" -"The `?` operator must return a value compatible with the return type of the " -"function. For `Result`, it means that the error types have to be compatible. " -"A function that returns `Result` can only use `?` on a value " -"of type `Result` if `ErrorOuter` and `ErrorInner` are the " -"same type or if `ErrorOuter` implements `From`." +"`slice::get_unchecked_mut(&self /* &[T] */, usize) -> &T` (unsafe and " +"simplified)" msgstr "" -#: src/error-handling/try-conversions.md -msgid "" -"A common alternative to a `From` implementation is `Result::map_err`, " -"especially when the conversion only happens in one place." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "`Option::as_ref(&self /* &Option */) -> Option<&T>`" msgstr "" -#: src/error-handling/try-conversions.md -msgid "" -"There is no compatibility requirement for `Option`. A function returning " -"`Option` can use the `?` operator on `Option` for arbitrary `T` and " -"`U` types." +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "`str::from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str` (unsafe)" msgstr "" -#: src/error-handling/try-conversions.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md msgid "" -"A function that returns `Result` cannot use `?` on `Option` and vice versa. " -"However, `Option::ok_or` converts `Option` to `Result` whereas `Result::ok` " -"turns `Result` into `Option`." +"`Rc::get_mut(&mut self /* &mut Rc */) -> Option<&mut T>` (simplified)" msgstr "" -#: src/error-handling/error.md -msgid "Dynamic Error Types" -msgstr "āĻĄāĻžāϝāĻŧāύāĻžāĻŽāĻŋāĻ• āĻ¤ā§āϰ⧁āϟāĻŋāϰ āϧāϰāύ" - -#: src/error-handling/error.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md msgid "" -"Sometimes we want to allow any type of error to be returned without writing " -"our own enum covering all the different possibilities. The `std::error::" -"Error` trait makes it easy to create a trait object that can contain any " -"error." +"`Vec::dedup_by_key(&mut self /* &mut Vec */, key: impl " +"FnMut(&mut T) -> K)` (simplified)" msgstr "" -#: src/error-handling/error.md -msgid "\"count.dat\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "Answers for missing names:" msgstr "" -#: src/error-handling/error.md -msgid "\"1i3\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "`fn from_string(String) -> Self`" msgstr "" -#: src/error-handling/error.md -msgid "\"Count: {count}\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "" +"`fn inner(&self) -> Option<&InnerType>` or `as_ref`, depending on context" msgstr "" -#: src/error-handling/error.md -msgid "\"Error: {err}\"" +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md +msgid "`fn with_string(self, String) -> Self`" msgstr "" -#: src/error-handling/error.md +#: src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md msgid "" -"The `read_count` function can return `std::io::Error` (from file operations) " -"or `std::num::ParseIntError` (from `String::parse`)." +"`fn inner_mut(&mut self) -> Option<&mut InnerType>` or `as_ref_mut`, " +"depending on context" msgstr "" -#: src/error-handling/error.md -msgid "" -"Boxing errors saves on code, but gives up the ability to cleanly handle " -"different error cases differently in the program. As such it's generally not " -"a good idea to use `Box` in the public API of a library, but it " -"can be a good option in a program where you just want to display the error " -"message somewhere." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits.md +msgid "Common Traits to Implement" msgstr "" -#: src/error-handling/error.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits.md msgid "" -"Make sure to implement the `std::error::Error` trait when defining a custom " -"error type so it can be boxed. But if you need to support the `no_std` " -"attribute, keep in mind that the `std::error::Error` trait is currently " -"compatible with `no_std` in [nightly](https://github.com/rust-lang/rust/" -"issues/103765) only." +"Traits should be liberally implemented on types you author, but there are " +"caveats!" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits.md msgid "" -"The [`thiserror`](https://docs.rs/thiserror/) and [`anyhow`](https://docs.rs/" -"anyhow/) crates are widely used to simplify error handling." +"Remember, many traits have the ability to be _derived_: to have a compiler " +"plugin (macro) write the implementation for you!" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits.md msgid "" -"`thiserror` is often used in libraries to create custom error types that " -"implement `From`." +"Authors of ecosystem traits (like De/Serialize) have made derive " +"implementations for traits available to users, leading to very little " +"commitment needed on the developer side for implementing these kinds of " +"traits!" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "" -"`anyhow` is often used by applications to help with error handling in " -"functions, including adding contextual information to your errors." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +msgid "\"Write to string\" trait, for debug purposes." msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "\"Found no username in {0}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md +msgid "Derivable: ✅" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "\"Failed to open {path}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +msgid "When to implement: Almost always" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "\"Failed to read\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +msgid "" +"// pub trait Debug {\n" +"// fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;\n" +"// }\n" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "\"Username: {username}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +msgid "\"PlainTextPassword\"" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "\"Error: {err:?}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +msgid "\"hint\"" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "`thiserror`" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +msgid "\"password\"" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "" -"The `Error` derive macro is provided by `thiserror`, and has lots of useful " -"attributes to help define error types in a compact way." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +msgid "\"[omitted]\"" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "The `std::error::Error` trait is derived automatically." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +msgid "\"{user:?}\"" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "The message from `#[error]` is used to derive the `Display` trait." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md +msgid "\"Password123\"" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md -msgid "`anyhow`" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md +msgid "\"Used it for years\"" msgstr "" -#: src/error-handling/thiserror-and-anyhow.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md msgid "" -"`anyhow::Error` is essentially a wrapper around `Box`. As such " -"it's again generally not a good choice for the public API of a library, but " -"is widely used in applications." -msgstr "" - -#: src/error-handling/thiserror-and-anyhow.md -msgid "`anyhow::Result` is a type alias for `Result`." +"Formatting for _debug information_ for programmers during , not appearance " +"or serialization." msgstr "" -#: src/error-handling/thiserror-and-anyhow.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md msgid "" -"Actual error type inside of it can be extracted for examination if necessary." +"Allows for use of `{:?}` and `{#?}` interpolation in string formatting " +"macros." msgstr "" -#: src/error-handling/thiserror-and-anyhow.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md msgid "" -"Functionality provided by `anyhow::Result` may be familiar to Go " -"developers, as it provides similar usage patterns and ergonomics to `(T, " -"error)` from Go." +"When to not derive/implement: If a struct holds sensitive data, investigate " +"if you should implement Debug for it." msgstr "" -#: src/error-handling/thiserror-and-anyhow.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md msgid "" -"`anyhow::Context` is a trait implemented for the standard `Result` and " -"`Option` types. `use anyhow::Context` is necessary to enable `.context()` " -"and `.with_context()` on those types." +"If Debug is needed, consider manually implementing Debug rather than " +"deriving it. Omit the sensitive data from the implementation." msgstr "" -#: src/error-handling/exercise.md -msgid "Exercise: Rewriting with Result" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "Partial equality & Total equality." msgstr "" -#: src/error-handling/exercise.md -msgid "" -"The following implements a very simple parser for an expression language. " -"However, it handles errors by panicking. Rewrite it to instead use idiomatic " -"error handling and propagate errors to a return from `main`. Feel free to " -"use `thiserror` and `anyhow`." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md +msgid "When to implement: Almost always." msgstr "" -#: src/error-handling/exercise.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md msgid "" -"HINT: start by fixing error handling in the `parse` function. Once that is " -"working correctly, update `Tokenizer` to implement " -"`Iterator>` and handle that in the parser." +"// pub trait PartialEq\n" +"//{\n" +"// // Required method\n" +"// fn eq(&self, other: &Rhs) -> bool;\n" +"// \n" +"// // Provided method\n" +"// fn ne(&self, other: &Rhs) -> bool { ... }\n" +"// }\n" +"//\n" +"// pub trait Eq: PartialEq { }\n" msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "/// An arithmetic operator.\n" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "\"alice\"" msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "/// A token in the expression language.\n" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "\"bob\"" msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "/// An expression in the expression language.\n" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "A type can't implement `Eq` without implementing `PartialEq`." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "/// A reference to a variable.\n" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "" +"Reminder: Partial means \"there are invalid members of this set for this " +"function.\"" msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "/// A literal number.\n" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "" +"This doesn't mean that equality will panic, or that it returns a result, " +"just that there may be values that may not behave as you expect equality to " +"behave." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "/// A binary operation.\n" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "" +"For example, with floating point values `NaN` is an outlier: `NaN == NaN` is " +"false, despite bitwise equality." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "'z'" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "" +"`PartialEq` exists to separate types like f32/f64 from types with Total " +"Equality." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "'_'" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +msgid "" +"You can implement `PartialEq` between different types, but this is mostly " +"useful for reference/smart pointer types." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "'+'" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "Partial ordering & Total ordering." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "'-'" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "" +"// pub trait PartialOrd: PartialEq\n" +"// {\n" +"// // Required method\n" +"// fn partial_cmp(&self, other: &Rhs) -> Option;\n" +"//\n" +"// /* Provided methods omitted */\n" +"// }\n" +"// pub trait Ord: Eq + PartialOrd {\n" +"// // Required method\n" +"// fn cmp(&self, other: &Self) -> Ordering;\n" +"//\n" +"// /* Provided methods omitted */\n" +"// }\n" msgstr "" -#: src/error-handling/exercise.md -msgid "\"Unexpected character {c}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "`Ord` gives access to `min`, `max`, and `clamp` methods." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "\"Unexpected end of input\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "When derived, compares things in the order they are defined." msgstr "" -#: src/error-handling/exercise.md -msgid "\"Invalid 32-bit integer'\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "" +"For enums this means each variant is considered \"greater than\" the last as " +"they are written." msgstr "" -#: src/error-handling/exercise.md -msgid "\"Unexpected token {tok:?}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "" +"For structs this means fields are compared as they are written, so `id` " +"fields are compared before `name` fields in `Totally`." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "// Look ahead to parse a binary operation if present.\n" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "Prerequisites: `PartialEq` for `PartialOrd`, `Eq` for `Ord`." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "\"10+foo+20-30\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "" +"To implement `Ord`, a type must also implement `PartialEq`, `Eq`, and " +"`PartialOrd`." msgstr "" -#: src/error-handling/exercise.md src/error-handling/solution.md -msgid "\"{expr:?}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "" +"Like with `PartialEq` and `Eq`, a type cannot implement `Ord` without " +"implementing `PartialOrd`." msgstr "" -#: src/error-handling/solution.md -msgid "\"Unexpected character '{0}' in input\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "" +"Like those equality traits, `PartialOrd` exists to separate types with non-" +"total ordering (particularly floating-point numbers) from types with total " +"ordering." msgstr "" -#: src/error-handling/solution.md -msgid "\"Tokenizer error: {0}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md +msgid "" +"Used for sorting/searching algorithms and maintaining the ordering of " +"`BTreeMap`/`BTreeSet` style data types." msgstr "" -#: src/error-handling/solution.md -msgid "\"Unexpected token {0:?}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md +msgid "Performing a hash on a type." msgstr "" -#: src/error-handling/solution.md -msgid "\"Invalid number\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md +msgid "" +"// pub trait Hash {\n" +"// // Required method\n" +"// fn hash(&self, state: &mut H)\n" +"// where H: Hasher;\n" +"//\n" +"// // Provided method\n" +"// fn hash_slice(data: &[Self], state: &mut H)\n" +"// where H: Hasher,\n" +"// Self: Sized { ... }\n" +"// }\n" msgstr "" -#: src/unsafe-rust.md -msgid "[Unsafe](./unsafe-rust/unsafe.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md +msgid "Most commonly used with data structures like `HashMap`." msgstr "" -#: src/unsafe-rust.md -msgid "" -"[Dereferencing Raw Pointers](./unsafe-rust/dereferencing.md) (10 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +msgid "Deep-copy a type or duplicate a smart, shareable pointer." msgstr "" -#: src/unsafe-rust.md -msgid "[Mutable Static Variables](./unsafe-rust/mutable-static.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +msgid "When to implement: If duplicating doesn't break invariants." msgstr "" -#: src/unsafe-rust.md -msgid "[Unions](./unsafe-rust/unions.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +msgid "" +"// pub trait Clone: Sized {\n" +"// // Required method\n" +"// fn clone(&self) -> Self;\n" +"// \n" +"// // Provided methods omitted\n" +"// }\n" msgstr "" -#: src/unsafe-rust.md -msgid "[Unsafe Functions](./unsafe-rust/unsafe-functions.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +msgid "// Copies the reference-counted pointer, not the value.\n" msgstr "" -#: src/unsafe-rust.md -msgid "[Unsafe Traits](./unsafe-rust/unsafe-traits.md) (5 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +msgid "" +"\"Deep copy\" a value, or in the case of reference counting pointers like " +"`Rc`/`Arc` create a new instance of that pointer." msgstr "" -#: src/unsafe-rust.md -msgid "[Exercise: FFI Wrapper](./unsafe-rust/exercise.md) (30 minutes)" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +msgid "" +"When to not implement/derive: For types that, to maintain an invariant, the " +"value should not be duplicated. We'll touch on this later in Idiomatic Rust." msgstr "" -#: src/unsafe-rust.md -msgid "This segment should take about 1 hour and 5 minutes" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +msgid "Like `Clone`, but indicates the type is can be bitwise copied." msgstr "" -#: src/unsafe-rust/unsafe.md -msgid "The Rust language has two parts:" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +msgid "When to implement: If possible, but with caveats." msgstr "" -#: src/unsafe-rust/unsafe.md -msgid "**Safe Rust:** memory safe, no undefined behavior possible." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +msgid "" +"// Copy is just a marker trait with Clone as a supertrait.\n" +"// pub trait Copy: Clone { }\n" msgstr "" -#: src/unsafe-rust/unsafe.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md msgid "" -"**Unsafe Rust:** can trigger undefined behavior if preconditions are " -"violated." +"When not to implement/derive: If you do not want to implicitly create copies " +"when dereferencing values of a type, do not implement this trait." msgstr "" -#: src/unsafe-rust/unsafe.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md msgid "" -"We saw mostly safe Rust in this course, but it's important to know what " -"Unsafe Rust is." +"Copy enables implicit duplication, so be careful about what types you're " +"implementing this on." msgstr "" -#: src/unsafe-rust/unsafe.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md msgid "" -"Unsafe code is usually small and isolated, and its correctness should be " -"carefully documented. It is usually wrapped in a safe abstraction layer." +"Ask the class: Can a type with heap data (`Vec`, `BTreeMap`, `Rc`, etc.) be " +"copy? Should it be?" msgstr "" -#: src/unsafe-rust/unsafe.md -msgid "Unsafe Rust gives you access to five new capabilities:" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +msgid "It both cannot and should not, this is a misuse of this trait." msgstr "" -#: src/unsafe-rust/unsafe.md -msgid "Dereference raw pointers." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +msgid "" +"Bitwise copying on these types would mean types with heap data would no " +"longer have exclusive ownership of a pointer, breaking the invariants " +"usually upheld by Rust and its ecosystem." msgstr "" -#: src/unsafe-rust/unsafe.md -msgid "Access or modify mutable static variables." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +msgid "" +"Multiple `Vec`s would point to the same data in memory. Adding and removing " +"data would only update individual `Vec`s length and capacity values. The " +"same for `BTreeMap`." msgstr "" -#: src/unsafe-rust/unsafe.md -msgid "Access `union` fields." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +msgid "" +"Bitwise copying of `Rc`s would not update the reference counting value " +"within the pointers, meaning there could be two instances of a `Rc` value " +"that believe themselves to be the only `Rc` for that pointer. Once one of " +"them is destroyed, the reference count will become 0 on one of them and the " +"inner value dropped despite there being another `Rc` still alive." msgstr "" -#: src/unsafe-rust/unsafe.md -msgid "Call `unsafe` functions, including `extern` functions." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md +msgid "Serialize/Deserialize style traits" msgstr "" -#: src/unsafe-rust/unsafe.md -msgid "Implement `unsafe` traits." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md +msgid "Crates like `serde` can implement serialization automatically." msgstr "" -#: src/unsafe-rust/unsafe.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md msgid "" -"We will briefly cover unsafe capabilities next. For full details, please see " -"[Chapter 19.1 in the Rust Book](https://doc.rust-lang.org/book/ch19-01-" -"unsafe-rust.html) and the [Rustonomicon](https://doc.rust-lang.org/nomicon/)." +"When not to implement: If a type contains sensitive data that should not be " +"erroneously saved to disk or sent over a network, consider not implementing " +"Serialize/Deserialize for that type." msgstr "" -#: src/unsafe-rust/unsafe.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md msgid "" -"Unsafe Rust does not mean the code is incorrect. It means that developers " -"have turned off some compiler safety features and have to write correct code " -"by themselves. It means the compiler no longer enforces Rust's memory-safety " -"rules." +"Shares security concerns with `Debug`, but given serialization is often used " +"in networking there can be higher stakes." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "Creating pointers is safe, but dereferencing them requires `unsafe`:" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "From & Into" msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "\"careful!\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "Conversion from one type to another." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "// Safe because r1 and r2 were obtained from references and so are" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md +msgid "Derivable: ❌, without crates like `derive_more`." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "" -"// guaranteed to be non-null and properly aligned, the objects underlying" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "When to implement: As-needed and convenient." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "// the references from which they were obtained are live throughout the" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "// From String\n" msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "// whole unsafe block, and they are not accessed either through the" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "\"Hello, obvious!\"" msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "// references or concurrently through any other pointers." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "// From &str\n" msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "\"r1 is: {}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "" +"// A From implementation implies an Into implementation, &str.into() ->\n" +" // ObviousImplementation\n" msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "\"uhoh\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "\"Hello, implementation!\"" msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "\"r2 is: {}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "" +"The two traits exist to express different areas you'll find conversion in " +"codebases." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "// NOT SAFE. DO NOT DO THIS." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "" +"`From` provides a constructor-style function, whereas into provides a method " +"on an existing value." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "/*" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "" +"Prefer writing `From` implementations for a type you're authoring instead " +"of `Into`." msgstr "" -#: src/unsafe-rust/dereferencing.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md msgid "" -"It is good practice (and required by the Android Rust style guide) to write " -"a comment for each `unsafe` block explaining how the code inside it " -"satisfies the safety requirements of the unsafe operations it is doing." +"The `Into` trait is implemented for any type that implements `From` " +"automatically." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "" -"In the case of pointer dereferences, this means that the pointers must be " -"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), i.e.:" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "" +"`Into` is preferred as a trait bound for arguments to functions for clarity " +"of intent for what the function can take." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "The pointer must be non-null." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md +msgid "`T: Into` has clearer intent than `String: From`." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "" -"The pointer must be _dereferenceable_ (within the bounds of a single " -"allocated object)." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md +msgid "TryFrom/TryInto" msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "The object must not have been deallocated." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md +msgid "Fallible conversion from one type to another." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "There must not be concurrent accesses to the same location." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md +msgid "Derivable: ❌" msgstr "" -#: src/unsafe-rust/dereferencing.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md +msgid "When to implement: As-needed." +msgstr "" + +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md msgid "" -"If the pointer was obtained by casting a reference, the underlying object " -"must be live and no reference may be used to access the memory." +"Like `From`/`Into`, prefer implementing `TryFrom` for types rather than " +"`TryInto`." msgstr "" -#: src/unsafe-rust/dereferencing.md -msgid "In most cases the pointer must also be properly aligned." +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md +msgid "Implementations can specify what the error type of the `Result`." msgstr "" -#: src/unsafe-rust/dereferencing.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md +msgid "\"Write to string\" trait, prioritizing readability for an end user." +msgstr "" + +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md msgid "" -"The \"NOT SAFE\" section gives an example of a common kind of UB bug: `*r1` " -"has the `'static` lifetime, so `r3` has type `&'static String`, and thus " -"outlives `s`. Creating a reference from a pointer requires _great care_." +"When to implement: As-needed, for errors and other types that an end-user " +"will see." msgstr "" -#: src/unsafe-rust/mutable-static.md -msgid "It is safe to read an immutable static variable:" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md +msgid "\"HTTP Error code {code}\"" msgstr "" -#: src/unsafe-rust/mutable-static.md -#, fuzzy -msgid "\"Hello, world!\"" -msgstr "Hello World!" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md +msgid "\"Whale attack detected – call Ishmael\"" +msgstr "" -#: src/unsafe-rust/mutable-static.md -msgid "\"HELLO_WORLD: {HELLO_WORLD}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md +msgid "Prerequisite for the `Error` trait." msgstr "" -#: src/unsafe-rust/mutable-static.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md msgid "" -"However, since data races can occur, it is unsafe to read and write mutable " -"static variables:" +"If implementing for an error type, focus on providing a descriptive error " +"for users and programmers other than you." msgstr "" -#: src/unsafe-rust/mutable-static.md -msgid "\"COUNTER: {COUNTER}\"" +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md +msgid "" +"Same security considerations as Debug, consider the ways that sensitive data " +"could be exposed in UI or logs." msgstr "" -#: src/unsafe-rust/mutable-static.md +#: src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md msgid "" -"The program here is safe because it is single-threaded. However, the Rust " -"compiler is conservative and will assume the worst. Try removing the " -"`unsafe` and see how the compiler explains that it is undefined behavior to " -"mutate a static from multiple threads." +"Types that implement `Display` automatically have `ToString` implemented for " +"them." msgstr "" -#: src/unsafe-rust/mutable-static.md +#: src/idiomatic/leveraging-the-type-system.md msgid "" -"Using a mutable static is generally a bad idea, but there are some cases " -"where it might make sense in low-level `no_std` code, such as implementing a " -"heap allocator or working with some C APIs." +"Rust's type system is _expressive_: you can use types and traits to build " +"abstractions that make your code harder to misuse." msgstr "" -#: src/unsafe-rust/unions.md -msgid "Unions are like enums, but you need to track the active field yourself:" +#: src/idiomatic/leveraging-the-type-system.md +msgid "" +"In some cases, you can go as far as enforcing correctness at _compile-time_, " +"with no runtime overhead." msgstr "" -#: src/unsafe-rust/unions.md -msgid "\"int: {}\"" +#: src/idiomatic/leveraging-the-type-system.md +msgid "" +"Types and traits can model concepts and constraints from your business " +"domain. With careful design, you can improve the clarity and maintainability " +"of the entire codebase." msgstr "" -#: src/unsafe-rust/unions.md -msgid "\"bool: {}\"" +#: src/idiomatic/leveraging-the-type-system.md +msgid "Additional items speaker may mention:" msgstr "" -#: src/unsafe-rust/unions.md -#, fuzzy -msgid "// Undefined behavior!" -msgstr "āϰāĻžāύāϟāĻžāχāĻŽā§‡ āϕ⧋āύ āĻ…āύāĻŋāĻ°ā§āϧāĻžāϰāĻŋāϤ āφāϚāϰāĻŖ āύ⧇āχ:" - -#: src/unsafe-rust/unions.md +#: src/idiomatic/leveraging-the-type-system.md msgid "" -"Unions are very rarely needed in Rust as you can usually use an enum. They " -"are occasionally needed for interacting with C library APIs." +"Rust's type system borrows a lot of ideas from functional programming " +"languages." msgstr "" -#: src/unsafe-rust/unions.md +#: src/idiomatic/leveraging-the-type-system.md msgid "" -"If you just want to reinterpret bytes as a different type, you probably want " -"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn." -"transmute.html) or a safe wrapper such as the [`zerocopy`](https://crates.io/" -"crates/zerocopy) crate." +"For example, Rust's enums are known as \"algebraic data types\" in languages " +"like Haskell and OCaml. You can take inspiration from learning material " +"geared towards functional languages when looking for guidance on how to " +"design with types. [\"Domain Modeling Made Functional\"](https://pragprog." +"com/titles/swdddf/domain-modeling-made-functional/) is a great resource on " +"the topic, with examples written in F#." msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "Calling Unsafe Functions" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āĻĢāĻžāĻ‚āĻļāύ āĻĄāĻžāĻ•āĻž" - -#: src/unsafe-rust/unsafe-functions.md +#: src/idiomatic/leveraging-the-type-system.md msgid "" -"A function or method can be marked `unsafe` if it has extra preconditions " -"you must uphold to avoid undefined behaviour:" +"Despite Rust's functional roots, not all functional design patterns can be " +"easily translated to Rust." msgstr "" -#: src/unsafe-rust/unsafe-functions.md src/unsafe-rust/exercise.md -#: src/unsafe-rust/solution.md src/android/interoperability/with-c.md -#: src/android/interoperability/with-c/rust.md -#: src/android/interoperability/cpp/cpp-bridge.md -#: src/exercises/chromium/build-rules.md src/bare-metal/aps/inline-assembly.md -#: src/bare-metal/aps/better-uart/using.md src/bare-metal/aps/logging/using.md -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "\"C\"" +#: src/idiomatic/leveraging-the-type-system.md +msgid "" +"For example, you must have a solid grasp on a broad selection of advanced " +"topics to design APIs that leverage higher-order functions and higher-kinded " +"types in Rust." msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "\"đŸ—ģ∈🌏\"" +#: src/idiomatic/leveraging-the-type-system.md +msgid "" +"Evaluate, on a case-by-case basis, whether a more imperative approach may be " +"easier to implement. Consider using in-place mutation, relying on Rust's " +"borrow-checker and type system to control what can be mutated, and where." msgstr "" -#: src/unsafe-rust/unsafe-functions.md +#: src/idiomatic/leveraging-the-type-system.md msgid "" -"// Safe because the indices are in the correct order, within the bounds of" +"The same caution should be applied to object-oriented design patterns. Rust " +"doesn't support inheritance, and object decomposition should take into " +"account the constraints introduced by the borrow checker." msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "// the string slice, and lie on UTF-8 sequence boundaries." +#: src/idiomatic/leveraging-the-type-system.md +msgid "" +"Mention that type-level programming can be often used to create \"zero-cost " +"abstractions\", although the label can be misleading: the impact on compile " +"times and code complexity may be significant." msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "\"emoji: {}\"" +#: src/idiomatic/leveraging-the-type-system.md +msgid "This segment should take about 7 hours and 30 minutes. It contains:" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "\"char count: {}\"" +#: src/idiomatic/leveraging-the-type-system.md +msgid "1 hour and 50 minutes" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -#, fuzzy -msgid "// Undefined behavior if abs misbehaves." -msgstr "āϰāĻžāύāϟāĻžāχāĻŽā§‡ āϕ⧋āύ āĻ…āύāĻŋāĻ°ā§āϧāĻžāϰāĻŋāϤ āφāϚāϰāĻŖ āύ⧇āχ:" +#: src/idiomatic/leveraging-the-type-system.md +msgid "1 hour and 30 minutes" +msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "\"Absolute value of -3 according to C: {}\"" +#: src/idiomatic/leveraging-the-type-system.md +msgid "1 hour and 35 minutes" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "// Not upholding the UTF-8 encoding requirement breaks memory safety!" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +msgid "A _newtype_ is a wrapper around an existing type, often a primitive:" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "// println!(\"emoji: {}\", unsafe { emojis.get_unchecked(0..3) });" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +msgid "/// A unique user identifier, implemented as a newtype around `u64`.\n" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "// println!(\"char count: {}\", count_chars(unsafe {" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +msgid "" +"Unlike type aliases, newtypes aren't interchangeable with the wrapped type:" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "// emojis.get_unchecked(0..3) }));" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "// đŸ› ī¸âŒ\n" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "Writing Unsafe Functions" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āĻĢāĻžāĻ‚āĻļāύ āϞ⧇āĻ–āĻž" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +msgid "" +"The Rust compiler won't let you use methods or operators defined on the " +"underlying type either:" +msgstr "" -#: src/unsafe-rust/unsafe-functions.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md msgid "" -"You can mark your own functions as `unsafe` if they require particular " -"conditions to avoid undefined behaviour." +"Students should have encountered the newtype pattern in the \"Fundamentals\" " +"course, when they learned about [tuple structs](../../user-defined-types/" +"tuple-structs.md)." msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "/// Swaps the values pointed to by the given pointers." +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +msgid "Run the example to show students the error message from the compiler." msgstr "" -#: src/unsafe-rust/unsafe-functions.md src/unsafe-rust/unsafe-traits.md -msgid "/// # Safety" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +msgid "" +"Modify the example to use a typealias instead of a newtype, such as `type " +"MessageId = u64`. The modified example should compile, thus highlighting the " +"differences between the two approaches." msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "/// The pointers must be valid and properly aligned." +#: src/idiomatic/leveraging-the-type-system/newtype-pattern.md +msgid "" +"Stress that newtypes, out of the box, have no behaviour attached to them. " +"You need to be intentional about which methods and operators you are willing " +"to forward from the underlying type. In our `UserId` example, it is " +"reasonable to allow comparisons between `UserId`s, but it wouldn't make " +"sense to allow arithmetic operations like addition or subtraction." msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "// Safe because ..." +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +msgid "" +"When a function takes multiple arguments of the same type, call sites are " +"unclear:" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "\"a = {}, b = {}\"" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +#: src/idiomatic/leveraging-the-type-system/raii.md +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md +msgid "// [...]\n" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "" -"`get_unchecked`, like most `_unchecked` functions, is unsafe, because it can " -"create UB if the range is incorrect. `abs` is incorrect for a different " -"reason: it is an external function (FFI). Calling external functions is " -"usually only a problem when those functions do things with pointers which " -"might violate Rust's memory model, but in general any C function might have " -"undefined behaviour under any arbitrary circumstances." +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +msgid "\"username\"" msgstr "" -#: src/unsafe-rust/unsafe-functions.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md msgid "" -"The `\"C\"` in this example is the ABI; [other ABIs are available too]" -"(https://doc.rust-lang.org/reference/items/external-blocks.html)." +"// In another part of the codebase, we swap arguments by mistake.\n" +"// Bug (best case), security vulnerability (worst case)\n" msgstr "" -#: src/unsafe-rust/unsafe-functions.md -msgid "" -"We wouldn't actually use pointers for a `swap` function - it can be done " -"safely with references." +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +msgid "The newtype pattern can prevent this class of errors at compile time:" msgstr "" -#: src/unsafe-rust/unsafe-functions.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md msgid "" -"Note that unsafe code is allowed within an unsafe function without an " -"`unsafe` block. We can prohibit this with `#[deny(unsafe_op_in_unsafe_fn)]`. " -"Try adding it and see what happens. This will likely change in a future Rust " -"edition." +"Run both examples to show students the successful compilation for the " +"original example, and the compiler error returned by the modified example." msgstr "" -#: src/unsafe-rust/unsafe-traits.md -msgid "Implementing Unsafe Traits" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ Traits āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +msgid "" +"Stress the _semantic_ angle. The newtype pattern should be leveraged to use " +"distinct types for distinct concepts, thus ruling out this class of errors " +"entirely." +msgstr "" -#: src/unsafe-rust/unsafe-traits.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md msgid "" -"Like with functions, you can mark a trait as `unsafe` if the implementation " -"must guarantee particular conditions to avoid undefined behaviour." +"Nonetheless, note that there are legitimate scenarios where a function may " +"take multiple arguments of the same type. In those scenarios, if correctness " +"is of paramount importance, consider using a struct with named fields as " +"input:" msgstr "" -#: src/unsafe-rust/unsafe-traits.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md msgid "" -"For example, the `zerocopy` crate has an unsafe trait that looks [something " -"like this](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" +"// No need to check the definition of the `login` function to spot the " +"issue.\n" msgstr "" -#: src/unsafe-rust/unsafe-traits.md -msgid "/// ..." +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +msgid "" +"Users are forced, at the callsite, to assign values to each field, thus " +"increasing the likelihood of spotting bugs." msgstr "" -#: src/unsafe-rust/unsafe-traits.md -msgid "/// The type must have a defined representation and no padding." +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md +msgid "The newtype pattern can be leveraged to enforce _invariants_." msgstr "" -#: src/unsafe-rust/unsafe-traits.md -msgid "// Safe because u32 has a defined representation and no padding." +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md +msgid "// Other validation checks...\n" msgstr "" -#: src/unsafe-rust/unsafe-traits.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md msgid "" -"There should be a `# Safety` section on the Rustdoc for the trait explaining " -"the requirements for the trait to be safely implemented." +"The newtype pattern, combined with Rust's module and visibility system, can " +"be used to _guarantee_ that instances of a given type satisfy a set of " +"invariants." msgstr "" -#: src/unsafe-rust/unsafe-traits.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md msgid "" -"The actual safety section for `AsBytes` is rather longer and more " -"complicated." +"In the example above, the raw `String` stored inside the `Username` struct " +"can't be accessed directly from other modules or crates, since it's not " +"marked as `pub` or `pub(in ...)`. Consumers of the `Username` type are " +"forced to use the `new` method to create instances. In turn, `new` performs " +"validation, thus ensuring that all instances of `Username` satisfy those " +"checks." msgstr "" -#: src/unsafe-rust/unsafe-traits.md -msgid "The built-in `Send` and `Sync` traits are unsafe." +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md +msgid "" +"The `as_str` method allows consumers to access the raw string representation " +"(e.g., to store it in a database). However, consumers can't modify the " +"underlying value since `&str`, the returned type, restricts them to read-" +"only access." msgstr "" -#: src/unsafe-rust/exercise.md -msgid "Safe FFI Wrapper" -msgstr "āύāĻŋāϰāĻžāĻĒāĻĻ FFI āĻŽā§‹āĻĄāĻŧāĻ•" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md +msgid "Type-level invariants have second-order benefits." +msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md msgid "" -"Rust has great support for calling functions through a _foreign function " -"interface_ (FFI). We will use this to build a safe wrapper for the `libc` " -"functions you would use from C to read the names of files in a directory." +"The input is validated once, at the boundary, and the rest of the program " +"can rely on the invariants being upheld. We can avoid redundant validation " +"and \"defensive programming\" checks throughout the program, reducing noise " +"and improving performance." msgstr "" -#: src/unsafe-rust/exercise.md -msgid "You will want to consult the manual pages:" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md +msgid "Is It Truly Encapsulated?" msgstr "" -#: src/unsafe-rust/exercise.md -msgid "[`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md +msgid "" +"You must evaluate _the entire API surface_ exposed by a newtype to determine " +"if invariants are indeed bullet-proof. It is crucial to consider all " +"possible interactions, including trait implementations, that may allow users " +"to bypass validation checks." msgstr "" -#: src/unsafe-rust/exercise.md -msgid "[`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md +msgid "// Validation checks...\n" msgstr "" -#: src/unsafe-rust/exercise.md -msgid "[`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md +msgid "// â€ŧī¸\n" msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md msgid "" -"You will also want to browse the [`std::ffi`](https://doc.rust-lang.org/std/" -"ffi/) module. There you find a number of string types which you need for the " -"exercise:" +"`DerefMut` allows users to get a mutable reference to the wrapped value." msgstr "" -#: src/unsafe-rust/exercise.md -msgid "Encoding" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md +msgid "" +"The mutable reference can be used to modify the underlying data in ways that " +"may violate the invariants enforced by `Username::new`!" msgstr "" -#: src/unsafe-rust/exercise.md -msgid "Use" +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md +msgid "" +"When auditing the API surface of a newtype, you can narrow down the review " +"scope to methods and traits that provide mutable access to the underlying " +"data." msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md +msgid "Remind students of privacy boundaries." +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md msgid "" -"[`str`](https://doc.rust-lang.org/std/primitive.str.html) and [`String`]" -"(https://doc.rust-lang.org/std/string/struct.String.html)" +"In particular, functions and methods defined in the same module of the " +"newtype can access its underlying data directly. If possible, move the " +"newtype definition to its own separate module to reduce the scope of the " +"audit." msgstr "" -#: src/unsafe-rust/exercise.md -msgid "UTF-8" +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "RAII: `Drop` trait" msgstr "" -#: src/unsafe-rust/exercise.md -msgid "Text processing in Rust" +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "" +"RAII (**R**esource **A**cquisition **I**s **I**nitialization) ties the " +"lifetime of a resource to the lifetime of a value." msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/raii.md msgid "" -"[`CStr`](https://doc.rust-lang.org/std/ffi/struct.CStr.html) and [`CString`]" -"(https://doc.rust-lang.org/std/ffi/struct.CString.html)" +"[Rust uses RAII to manage memory](https://doc.rust-lang.org/rust-by-example/" +"scope/raii.html), and the `Drop` trait allows you to extend this to other " +"resources, such as file descriptors or locks." msgstr "" -#: src/unsafe-rust/exercise.md -msgid "NUL-terminated" +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "b\"example\"" msgstr "" -#: src/unsafe-rust/exercise.md -msgid "Communicating with C functions" +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "\"example.txt\"" msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "\"content: {:?}\"" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/raii.md msgid "" -"[`OsStr`](https://doc.rust-lang.org/std/ffi/struct.OsStr.html) and " -"[`OsString`](https://doc.rust-lang.org/std/ffi/struct.OsString.html)" +"Easy to miss: `file.close()` is never called. Ask the class if they noticed." msgstr "" -#: src/unsafe-rust/exercise.md -msgid "OS-specific" +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "" +"To release the file descriptor correctly, `file.close()` must be called " +"after the last use — and also in early-return paths in case of errors." msgstr "" -#: src/unsafe-rust/exercise.md -msgid "Communicating with the OS" +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "" +"Instead of relying on the user to call `close()`, we can implement the " +"`Drop` trait to release the resource automatically. This ties cleanup to the " +"lifetime of the `File` value." msgstr "" -#: src/unsafe-rust/exercise.md -msgid "You will convert between all these types:" +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "// libc::close(...);\n" msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "\"file descriptor was closed\"" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/raii.md msgid "" -"`&str` to `CString`: you need to allocate space for a trailing `\\0` " -"character," +"Note that `Drop::drop()` cannot return a `Result`. Any failures must be " +"handled internally or ignored. In the standard library, errors during FD " +"closure inside `Drop` are silently discarded. See the implementation: " +"" msgstr "" -#: src/unsafe-rust/exercise.md -msgid "`CString` to `*const i8`: you need a pointer to call C functions," +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "When is `Drop::drop` called?" msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/raii.md msgid "" -"`*const i8` to `&CStr`: you need something which can find the trailing `\\0` " -"character," +"Normally, when the `file` variable in `main()` goes out of scope (either on " +"return or due to a panic), `drop()` is called automatically." msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/raii.md msgid "" -"`&CStr` to `&[u8]`: a slice of bytes is the universal interface for \"some " -"unknown data\"," +"If the file is moved into another function (as is this case with `File::" +"close()`), the value is dropped when that function returns — not in `main`." msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/raii.md msgid "" -"`&[u8]` to `&OsStr`: `&OsStr` is a step towards `OsString`, use [`OsStrExt`]" -"(https://doc.rust-lang.org/std/os/unix/ffi/trait.OsStrExt.html) to create it," +"In contrast, C++ runs destructors in the original scope even for moved-from " +"values." msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/raii.md msgid "" -"`&OsStr` to `OsString`: you need to clone the data in `&OsStr` to be able to " -"return it and call `readdir` again." +"Demo: insert `panic!(\"oops\")` at the start of `read_to_end()` and run it. " +"`drop()` still runs during unwinding." msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "The `Drop` trait has another important limitation: it is not `async`." +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/raii.md msgid "" -"The [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html) also has a very " -"useful chapter about FFI." +"This means you cannot `await` inside a destructor, which is often needed " +"when cleaning up asynchronous resources like sockets, database connections, " +"or tasks that must signal completion to another system." msgstr "" -#: src/unsafe-rust/exercise.md +#: src/idiomatic/leveraging-the-type-system/raii.md msgid "" -"Copy the code below to and fill in the missing " -"functions and methods:" +"Learn more: " msgstr "" -#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md -msgid "\"macos\"" +#: src/idiomatic/leveraging-the-type-system/raii.md +msgid "" +"There is an experimental `AsyncDrop` trait available on nightly: " msgstr "" -#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md -msgid "// Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "Drop can be skipped" msgstr "" -#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md -msgid "" -"// Layout according to the Linux man page for readdir(3), where ino_t and\n" -" // off_t are resolved according to the definitions in\n" -" // /usr/include/x86_64-linux-gnu/{sys/types.h, bits/typesizes.h}.\n" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "There are cases where destructors will not run." msgstr "" -#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md -msgid "// Layout according to the macOS man page for dir(5).\n" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "\"OwnedFd::drop() called with raw fd: {:?}\"" msgstr "" -#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md -msgid "\"x86_64\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "\"TmpFile::drop() called with owned fd: {:?}\"" msgstr "" -#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md msgid "" -"// See https://github.com/rust-lang/libc/issues/414 and the section on\n" -" // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2).\n" -" //\n" -" // \"Platforms that existed before these updates were available\" " -"refers\n" -" // to macOS (as opposed to iOS / wearOS / etc.) on Intel and " -"PowerPC.\n" +"// libc::unlink(\"/tmp/file\")\n" +" // panic!(\"TmpFile::drop() panics\");\n" msgstr "" -#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md -msgid "\"readdir$INODE64\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "\"TmpFile::close(): not implemented yet\"" msgstr "" -#: src/unsafe-rust/exercise.md -msgid "" -"// Call opendir and return a Ok value if that worked,\n" -" // otherwise return Err with a message." +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "// std::mem::forget(file);\n" msgstr "" -#: src/unsafe-rust/exercise.md -msgid "// Keep calling readdir until we get a NULL pointer back." +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "// file.close();\n" msgstr "" -#: src/unsafe-rust/exercise.md -msgid "// Call closedir as needed." +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"Drop is not guaranteed to always run. There is a number of cases when drop " +"is skipped: the program can crash or exit, the value with the drop " +"implementation can be leaked etc." msgstr "" -#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md -#: src/android/interoperability/with-c/rust.md -msgid "\".\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"In the version that calls [`std::process::exit`](https://doc.rust-lang.org/" +"std/process/fn.exit.html), `TmpFile::drop()` is never run because `exit()` " +"terminates the process immediately without any opportunity for a `drop()` " +"method to be called." msgstr "" -#: src/unsafe-rust/exercise.md src/unsafe-rust/solution.md -msgid "\"files: {:#?}\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"You can prevent accidental use of `exit` by denying the [`clippy::exit`]" +"(https://rust-lang.github.io/rust-clippy/stable/index.html#exit) lint." msgstr "" -#: src/unsafe-rust/solution.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md msgid "" -"// Call opendir and return a Ok value if that worked,\n" -" // otherwise return Err with a message.\n" +"If you remove the `std::process::exit(0)` line, each `drop()` method in this " +"simple case will run in turn." msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"Invalid path: {err}\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"Try uncommenting the [`std::mem::forget`](https://doc.rust-lang.org/std/mem/" +"fn.forget.html) call. What do you think will happen?" msgstr "" -#: src/unsafe-rust/solution.md -msgid "// SAFETY: path.as_ptr() cannot be NULL.\n" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"`mem::forget()` takes ownership and \"forgets\" about the value `file` " +"without running its **destructor** `Drop::drop()`. The destructor of " +"`owned_fd` is still run." msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"Could not open {:?}\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"Remove the `mem::forget()` call, then uncomment the `file.close()` call " +"below it. What do you expect now?" msgstr "" -#: src/unsafe-rust/solution.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md msgid "" -"// Keep calling readdir until we get a NULL pointer back.\n" -" // SAFETY: self.dir is never NULL.\n" +"With the default `panic = \"unwind\"` setting, the stack still unwinds and " +"destructors run, even when the panic starts in `main`." msgstr "" -#: src/unsafe-rust/solution.md -msgid "// We have reached the end of the directory.\n" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"With [`panic = \"abort\"`](https://doc.rust-lang.org/cargo/reference/" +"profiles.html#panic) no destructors are run." msgstr "" -#: src/unsafe-rust/solution.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md msgid "" -"// SAFETY: dirent is not NULL and dirent.d_name is NUL\n" -" // terminated.\n" +"As a last step, uncomment the `panic!` inside `TmpFile::drop()` and run it. " +"Ask the class: which destructors run before the abort?" msgstr "" -#: src/unsafe-rust/solution.md -msgid "// Call closedir as needed.\n" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"After a double panic, Rust no longer guarantees that remaining destructors " +"will run:" msgstr "" -#: src/unsafe-rust/solution.md -msgid "// SAFETY: self.dir is not NULL.\n" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"Some cleanup that was already in progress may still complete (for example, " +"field destructors of the value currently being dropped)," msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"Could not close {:?}\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"but anything scheduled later in the unwind path might be skipped entirely." msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"no-such-directory\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"This is why we say you cannot rely solely on `drop()` for critical external " +"cleanup, nor assume that a double panic aborts without running any further " +"destructors." msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"Non UTF-8 character in path\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"Some languages forbid or restrict exceptions in destructors. Rust allows " +"panicking in `Drop::drop`, but it is almost never a good idea, since it can " +"disrupt unwinding and lead to unpredictable cleanup. It is best avoided " +"unless there is a very specific need, such as in the case of a **drop bomb**." msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"..\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"Drop is suitable for cleaning up resources within the scope of a process, " +"but it is not the right tool for providing hard guarantees that something " +"happens outside of the process (e.g., on local disk, or in another service " +"in a distributed system)." msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"foo.txt\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"For example, deleting a temporary file in `drop()` is fine in a toy example, " +"but in a real program you would still need an external cleanup mechanism " +"such as a temp file reaper." msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"The Foo Diaries\\n\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_skipped.md +msgid "" +"In contrast, we can rely on `drop()` to unlock a mutex, since it is a " +"process-local resource. If `drop()` is skipped and the mutex is left locked, " +"it has no lasting effects outside the process." msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"bar.png\"" +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md +msgid "Mutex and MutexGuard" msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"\\n\"" +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md +msgid "" +"In earlier examples, RAII was used to manage concrete resources like file " +"descriptors. With a `Mutex`, the \"resource\" is mutable access to a value. " +"You access the value by calling `lock`, which then returns a `MutexGuard` " +"which will unlock the `Mutex` automatically when dropped." msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"crab.rs\"" +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md +msgid "\"{guard:?}\"" msgstr "" -#: src/unsafe-rust/solution.md -msgid "\"//! Crab\\n\"" +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md +msgid "" +"A `Mutex` controls exclusive access to a value. Unlike earlier RAII " +"examples, the resource here is logical: temporary exclusive access to the " +"data inside." msgstr "" -#: src/android.md -msgid "Welcome to Rust in Android" +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md +msgid "" +"This right is represented by a `MutexGuard`. Only one guard for this mutex " +"can exist at a time. While it lives, it provides `&mut T` access." msgstr "" -#: src/android.md +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md msgid "" -"Rust is supported for system software on Android. This means that you can " -"write new services, libraries, drivers or even firmware in Rust (or improve " -"existing code as needed)." +"Although `lock()` takes `&self`, it returns a `MutexGuard` with mutable " +"access. This works through _interior mutability_, where a type manages its " +"own borrowing rules internally to allow mutation through `&self`." msgstr "" -#: src/android.md +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md msgid "" -"We will attempt to call Rust from one of your own projects today. So try to " -"find a little corner of your code base where we can move some lines of code " -"to Rust. The fewer dependencies and \"exotic\" types the better. Something " -"that parses some raw bytes would be ideal." +"`MutexGuard` implements `Deref` and `DerefMut`, making access ergonomic. You " +"lock the mutex and use the guard like a `&mut T`." msgstr "" -#: src/android.md +#: src/idiomatic/leveraging-the-type-system/raii/mutex.md msgid "" -"The speaker may mention any of the following given the increased use of Rust " -"in Android:" +"The mutex is released by `MutexGuard::drop()`. You never call an explicit " +"unlock function." msgstr "" -#: src/android.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md msgid "" -"Service example: [DNS over HTTP](https://security.googleblog.com/2022/07/dns-" -"over-http3-in-android.html)" +"A **drop guard** in Rust is a temporary object that performs some kind of " +"cleanup when it goes out of scope. In the case of `Mutex`, the `lock` method " +"returns a `MutexGuard` that automatically unlocks the mutex on `drop`:" msgstr "" -#: src/android.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md +msgid "The example above shows a simplified `Mutex` and its associated guard." +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md msgid "" -"Libraries: [Rutabaga Virtual Graphics Interface](https://crosvm.dev/book/" -"appendix/rutabaga_gfx.html)" +"Even though it is not a production-ready implementation, it illustrates the " +"core idea:" msgstr "" -#: src/android.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md +msgid "the guard represents exclusive access," +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md msgid "" -"Kernel Drivers: [Binder](https://lore.kernel.org/rust-for-linux/20231101-" -"rust-binder-v1-0-08ba9197f637@google.com/)" +"and its `Drop` implementation releases the lock when it goes out of scope." msgstr "" -#: src/android.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md msgid "" -"Firmware: [pKVM firmware](https://security.googleblog.com/2023/10/bare-metal-" -"rust-in-android.html)" +"This example shows a C++ style mutex that does not contain the data it " +"protects. While this is non-idiomatic in Rust, the goal here is only to " +"illustrate the core idea of a drop guard, not to demonstrate a proper Rust " +"mutex design." msgstr "" -#: src/android/setup.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md +msgid "For brevity, several features are omitted:" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md msgid "" -"We will be using a Cuttlefish Android Virtual Device to test our code. Make " -"sure you have access to one or create a new one with:" +"A real `Mutex` stores the protected value inside the mutex. \n" +"This toy example omits the value entirely to focus only on the drop guard " +"mechanism." msgstr "" -#: src/android/setup.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md msgid "" -"Please see the [Android Developer Codelab](https://source.android.com/docs/" -"setup/start) for details." +"Ergonomic access via `Deref` and `DerefMut` on `MutexGuard` (letting the " +"guard behave like a `&T` or `&mut T`)." msgstr "" -#: src/android/setup.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md msgid "" -"Cuttlefish is a reference Android device designed to work on generic Linux " -"desktops. MacOS support is also planned." +"A fully blocking `.lock()` method and a non-blocking `try_lock` variant." msgstr "" -#: src/android/setup.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md msgid "" -"The Cuttlefish system image maintains high fidelity to real devices, and is " -"the ideal emulator to run many Rust use cases." +"You can explore the [`Mutex` implementation in Rust’s std library](https://" +"doc.rust-lang.org/std/sync/struct.Mutex.html) as an example of a production-" +"ready mutex. The [`Mutex` from the `parking_lot` crate](https://docs.rs/" +"parking_lot/latest/parking_lot/type.Mutex.html) is another worthwhile " +"reference." msgstr "" -#: src/android/build-rules.md -msgid "The Android build system (Soong) supports Rust via a number of modules:" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "Drop Bombs: Enforcing API Correctness" msgstr "" -#: src/android/build-rules.md -msgid "Module Type" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"Use `Drop` to enforce invariants and detect incorrect API usage. A \"drop " +"bomb\" panics if a value is dropped without being explicitly finalized." msgstr "" -#: src/android/build-rules.md -msgid "Description" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"This pattern is often used when the finalizing operation (like `commit()` or " +"`rollback()`) needs to return a `Result`, which cannot be done from `Drop`." msgstr "" -#: src/android/build-rules.md -msgid "`rust_binary`" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md +msgid "\"COMMIT\"" msgstr "" -#: src/android/build-rules.md -msgid "Produces a Rust binary." +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md +msgid "\"Transaction dropped without commit!\"" msgstr "" -#: src/android/build-rules.md -msgid "`rust_library`" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md +msgid "" +"// Use `tx` to build the transaction, then commit it.\n" +" // Comment out the call to `commit` to see the panic.\n" msgstr "" -#: src/android/build-rules.md -msgid "Produces a Rust library, and provides both `rlib` and `dylib` variants." +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"In some systems, a value must be finalized by a specific API before it is " +"dropped." msgstr "" -#: src/android/build-rules.md -msgid "`rust_ffi`" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "For example, a `Transaction` might need to be committed or rolled back." msgstr "" -#: src/android/build-rules.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md msgid "" -"Produces a Rust C library usable by `cc` modules, and provides both static " -"and shared variants." +"A drop bomb ensures that a value like `Transaction` cannot be silently " +"dropped in an unfinished state. The destructor panics if the transaction has " +"not been explicitly finalized (for example, with `commit()`)." msgstr "" -#: src/android/build-rules.md -msgid "`rust_proc_macro`" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"The finalizing operation (such as `commit()`) usually takes `self` by value. " +"This ensures that once the transaction is finalized, the original object can " +"no longer be used." msgstr "" -#: src/android/build-rules.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md msgid "" -"Produces a `proc-macro` Rust library. These are analogous to compiler " -"plugins." +"A common reason to use this pattern is when cleanup cannot be done in " +"`Drop`, either because it is fallible or asynchronous." msgstr "" -#: src/android/build-rules.md -msgid "`rust_test`" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"This pattern is appropriate even in public APIs. It can help users catch " +"bugs early when they forget to explicitly finalize a transactional object." msgstr "" -#: src/android/build-rules.md -msgid "Produces a Rust test binary that uses the standard Rust test harness." +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"If cleanup can safely happen in `Drop`, some APIs choose to panic only in " +"debug builds. Whether this is appropriate depends on the guarantees your API " +"must enforce." msgstr "" -#: src/android/build-rules.md -msgid "`rust_fuzz`" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"Panicking in release builds is reasonable when silent misuse would cause " +"major correctness or security problems." msgstr "" -#: src/android/build-rules.md -msgid "Produces a Rust fuzz binary leveraging `libfuzzer`." +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"Question: Why do we need an `active` flag inside `Transaction`? Why can't " +"`drop()` panic unconditionally?" msgstr "" -#: src/android/build-rules.md -msgid "`rust_protobuf`" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"Expected answer: `commit()` takes `self` by value and runs `drop()`, which " +"would panic." msgstr "" -#: src/android/build-rules.md -msgid "" -"Generates source and produces a Rust library that provides an interface for " -"a particular protobuf." +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "More to explore" msgstr "" -#: src/android/build-rules.md -msgid "`rust_bindgen`" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md +msgid "" +"Several related patterns help enforce correct teardown or prevent accidental " +"drops." msgstr "" -#: src/android/build-rules.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md msgid "" -"Generates source and produces a Rust library containing Rust bindings to C " -"libraries." +"The [`drop_bomb` crate](https://docs.rs/drop_bomb/latest/drop_bomb/): A " +"small utility that panics if dropped unless explicitly defused with `." +"defuse()`. Comes with a `DebugDropBomb` variant that only activates in debug " +"builds." msgstr "" -#: src/android/build-rules.md -msgid "We will look at `rust_binary` and `rust_library` next." +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md +msgid "Drop Bombs: using `std::mem::forget`" msgstr "" -#: src/android/build-rules.md -msgid "Additional items speaker may mention:" +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md +msgid "// Defuse the drop bomb by preventing Drop from ever running.\n" msgstr "" -#: src/android/build-rules.md -msgid "" -"Cargo is not optimized for multi-language repos, and also downloads packages " -"from the internet." +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md +msgid "// This is the \"drop bomb\"\n" msgstr "" -#: src/android/build-rules.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md msgid "" -"For compliance and performance, Android must have crates in-tree. It must " -"also interop with C/C++/Java code. Soong fills that gap." +"This example removes the flag from the previous slide and makes the drop " +"method panic unconditionally. To avoid that panic on a successful commit, " +"the commit method now takes ownership of the transaction and calls [`std::" +"mem::forget`](https://doc.rust-lang.org/std/mem/fn.forget.html), which " +"prevents the `Drop::drop()` method from running." msgstr "" -#: src/android/build-rules.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md msgid "" -"Soong has many similarities to Bazel, which is the open-source variant of " -"Blaze (used in google3)." +"If the forgotten value owned heap allocated memory that would normally be " +"freed in its `drop()` implementation, one consequence is a memory leak. That " +"is not the case for the `Transaction` in the example above, since it does " +"not own any heap memory." msgstr "" -#: src/android/build-rules.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb_forget.md msgid "" -"There is a plan to transition [Android](https://source.android.com/docs/" -"setup/build/bazel/introduction), [ChromeOS](https://chromium.googlesource." -"com/chromiumos/bazel/), and [Fuchsia](https://source.android.com/docs/setup/" -"build/bazel/introduction) to Bazel." +"We can avoid needing a runtime flag by using `mem::forget()` in a tactical " +"way. When the transaction commits successfully, we can defuse the drop bomb " +"by calling `std::mem::forget` on the value, which prevents its `Drop` " +"implementation from running." msgstr "" -#: src/android/build-rules.md -msgid "Learning Bazel-like build rules is useful for all Rust OS developers." +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "" +"Below are the signatures for the [`drop()`](https://doc.rust-lang.org/std/" +"mem/fn.drop.html) and [`forget()`](https://doc.rust-lang.org/std/mem/fn." +"forget.html) functions:" msgstr "" -#: src/android/build-rules.md -msgid "Fun fact: Data from Star Trek is a Soong-type Android." +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "// std::mem::forget\n" msgstr "" -#: src/android/build-rules/binary.md -msgid "Rust Binaries" +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "// std::mem::drop\n" msgstr "" -#: src/android/build-rules/binary.md -msgid "" -"Let us start with a simple application. At the root of an AOSP checkout, " -"create the following files:" +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "Both `mem::forget()` and `mem::drop()` take ownership of the value `t`." msgstr "" -#: src/android/build-rules/binary.md src/android/build-rules/library.md -msgid "_hello_rust/Android.bp_:" +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "Despite having the same function signature, they have opposite effects:" msgstr "" -#: src/android/build-rules/binary.md -msgid "\"hello_rust\"" +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "" +"`forget()` uses [`ManuallyDrop`](https://doc.rust-lang.org/std/mem/struct." +"ManuallyDrop.html) to prevent the destructor `Drop::drop()` from being " +"invoked." msgstr "" -#: src/android/build-rules/binary.md src/android/build-rules/library.md -#: src/android/logging.md -msgid "\"src/main.rs\"" +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "" +"This is useful for scenarios such as implementing a drop bomb or otherwise " +"opting out of destructor behavior." msgstr "" -#: src/android/build-rules/binary.md src/android/build-rules/library.md -msgid "_hello_rust/src/main.rs_:" +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "" +"Be careful though, since any resources the value exclusively owns such as " +"heap allocated memory or file handles will remain in an unreachable state." msgstr "" -#: src/android/build-rules/binary.md src/android/build-rules/library.md -msgid "//! Rust demo.\n" +#: src/idiomatic/leveraging-the-type-system/raii/forget_and_drop.md +msgid "" +"`drop()` is a convenience function for disposing of a value. Because `t` is " +"moved into the function, it is automatically dropped which triggers its " +"`Drop::drop()` implementation before the parent function returns." msgstr "" -#: src/android/build-rules/binary.md src/android/build-rules/library.md -msgid "/// Prints a greeting to standard output.\n" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "Scope Guards" msgstr "" -#: src/android/build-rules/binary.md src/exercises/chromium/build-rules.md -msgid "\"Hello from Rust!\"" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "" +"A scope guard uses the `Drop` trait to run cleanup code automatically when a " +"scope exits, even during unwinding." msgstr "" -#: src/android/build-rules/binary.md -msgid "You can now build, push, and run the binary:" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "\"download.tmp\"" msgstr "" -#: src/android/build-rules/binary.md -msgid "" -"```shell\n" -"m hello_rust\n" -"adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust\" /data/local/tmp\n" -"adb shell /data/local/tmp/hello_rust\n" -"```" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "\"cannot create temporary file\"" msgstr "" -#: src/android/build-rules/library.md -msgid "Rust Libraries" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "// Set up cleanup immediately after file creation\n" msgstr "" -#: src/android/build-rules/library.md -msgid "You use `rust_library` to create a new Rust library for Android." +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "\"download failed, deleting: {:?}\"" msgstr "" -#: src/android/build-rules/library.md -msgid "Here we declare a dependency on two libraries:" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "\"partial data...\"" msgstr "" -#: src/android/build-rules/library.md -msgid "`libgreeting`, which we define below," +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "// Download succeeded, keep the file\n" msgstr "" -#: src/android/build-rules/library.md -msgid "" -"`libtextwrap`, which is a crate already vendored in [`external/rust/crates/`]" -"(https://cs.android.com/android/platform/superproject/+/master:external/rust/" -"crates/)." +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "\"Download '{path}' complete!\"" msgstr "" -#: src/android/build-rules/library.md -msgid "\"hello_rust_with_dep\"" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "// Otherwise, the guard runs and deletes the file\n" msgstr "" -#: src/android/build-rules/library.md -msgid "\"libgreetings\"" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "" +"This example models a download workflow. We create a temporary file first, " +"then use a scope guard to ensure that the file is deleted if the download " +"fails." msgstr "" -#: src/android/build-rules/library.md -msgid "\"libtextwrap\"" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "" +"The `scopeguard` crate allows you to conveniently define a single-use " +"`Drop`\\-based cleanup without defining a custom type with a custom `Drop` " +"implementation." msgstr "" -#: src/android/build-rules/library.md -msgid "// Need this to avoid dynamic link error.\n" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "" +"The guard is created directly after creating the file, so even if `writeln!" +"()` fails, the file will still be cleaned up. This ordering is essential for " +"correctness." msgstr "" -#: src/android/build-rules/library.md -msgid "\"greetings\"" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "" +"The `guard()` creates a `ScopeGuard` instance. It a user-defined value (in " +"this case, `path`) and the cleanup closure that later receives this value." msgstr "" -#: src/android/build-rules/library.md -#: src/android/aidl/example-service/service.md -#: src/android/interoperability/java.md -msgid "\"src/lib.rs\"" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "" +"The guard's closure runs on scope exit unless it is _defused_ with " +"`ScopeGuard::into_inner` (removing the value so the guard does nothing on " +"drop). In the success path, we call `into_inner` so the guard will not " +"delete the file." msgstr "" -#: src/android/build-rules/library.md -msgid "_hello_rust/src/lib.rs_:" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "A scope guard is similar to the `defer` feature in Go." msgstr "" -#: src/android/build-rules/library.md -msgid "//! Greeting library.\n" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "" +"This pattern is ideal for \"cleanup on failure\" scenarios, where a cleanup " +"should run by default unless a success path is explicitly taken." msgstr "" -#: src/android/build-rules/library.md -msgid "/// Greet `name`.\n" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "" +"This pattern is also useful when you don't control the cleanup strategy of " +"the resource object. In this example, `File::drop()` closes the file but " +"does not delete it, and we can't change the standard library to delete the " +"file instead (nor should we, it is not a good idea anyway)." msgstr "" -#: src/android/build-rules/library.md -msgid "\"Hello {name}, it is very nice to meet you!\"" +#: src/idiomatic/leveraging-the-type-system/raii/scope_guard.md +msgid "" +"The `scopeguard` crate also supports cleanup strategies via the [`Strategy`]" +"(https://docs.rs/scopeguard/latest/scopeguard/trait.Strategy.html) trait. " +"You can choose to run the guard on unwind only, or on success only, not just " +"always." msgstr "" -#: src/android/build-rules/library.md -msgid "You build, push, and run the binary like before:" +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "Drop: Option" msgstr "" -#: src/android/build-rules/library.md -msgid "" -"```shell\n" -"m hello_rust_with_dep\n" -"adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep\" /data/local/" -"tmp\n" -"adb shell /data/local/tmp/hello_rust_with_dep\n" -"```" +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "\"write '{data}' to file '{}'\"" msgstr "" -#: src/android/aidl.md -msgid "" -"The [Android Interface Definition Language (AIDL)](https://developer.android." -"com/guide/components/aidl) is supported in Rust:" +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "\"automatically closing handle for file: {}\"" msgstr "" -#: src/android/aidl.md -msgid "Rust code can call existing AIDL servers," +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "\"closed handle for file: {}\"" msgstr "" -#: src/android/aidl.md -msgid "You can create new AIDL servers in Rust." +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "\"manually closed file: {}\"" msgstr "" -#: src/android/aidl/birthday-service.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md msgid "" -"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." +"In this example we want to let the user call `close()` manually so that " +"errors from closing the file can be reported explicitly." msgstr "" -#: src/android/aidl/example-service/interface.md -msgid "AIDL Interfaces" +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "" +"At the same time we still want RAII semantics: if the user forgets to call " +"`close()`, the handle must be cleaned up automatically in `Drop`." msgstr "" -#: src/android/aidl/example-service/interface.md -msgid "You declare the API of your service using an AIDL interface:" +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "" +"Wrapping the handle in an `Option` gives us both behaviors. `close()` " +"extracts the handle with `take()`, and `Drop` only runs cleanup if a handle " +"is still present." msgstr "" -#: src/android/aidl/example-service/interface.md -#: src/android/aidl/example-service/service-bindings.md +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md msgid "" -"_birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl_:" +"Demo: remove the `.close()` call and run the code — `Drop` now prints the " +"automatic cleanup." msgstr "" -#: src/android/aidl/example-service/interface.md -#: src/android/aidl/example-service/service-bindings.md -#: src/android/aidl/example-service/changing-definition.md -msgid "/** Birthday service interface. */" +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "" +"The main downside is ergonomics. `Option` forces us to handle both the " +"`Some` and `None` case even in places where, logically, `None` cannot occur. " +"Rust’s type system cannot express that relationship between `File` and its " +"`Handle`, so we handle both cases manually." msgstr "" -#: src/android/aidl/example-service/interface.md -#: src/android/aidl/example-service/service-bindings.md -#: src/android/aidl/example-service/changing-definition.md -msgid "/** Generate a Happy Birthday message. */" +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "" +"Instead of `Option` we could use [`ManuallyDrop`](https://doc.rust-lang.org/" +"std/mem/struct.ManuallyDrop.html), which suppresses automatic destruction by " +"preventing Rust from calling `Drop` for the value; you must handle teardown " +"yourself." msgstr "" - -#: src/android/aidl/example-service/interface.md -msgid "_birthday_service/aidl/Android.bp_:" + +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "" +"The [_scopeguard_ example](./scope_guard.md) on the previous slide shows how " +"`ManuallyDrop` can replace `Option` to avoid handling `None` in places where " +"the value should always exist." msgstr "" -#: src/android/aidl/example-service/interface.md -msgid "\"com.example.birthdayservice\"" +#: src/idiomatic/leveraging-the-type-system/raii/drop_option.md +msgid "" +"In such designs we typically track the drop state with a separate flag next " +"to the `ManuallyDrop`, which lets us track whether the handle has " +"already been manually consumed." msgstr "" -#: src/android/aidl/example-service/interface.md -msgid "\"com/example/birthdayservice/*.aidl\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "" +"It may desirable to **extend** foreign types with new inherent methods. For " +"example, allow your code to check if a string is a palindrome using method-" +"calling syntax: `s.is_palindrome()`." msgstr "" -#: src/android/aidl/example-service/interface.md -msgid "// Rust is not enabled by default\n" +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "It might feel natural to reach out for an `impl` block:" msgstr "" -#: src/android/aidl/example-service/interface.md +#: src/idiomatic/leveraging-the-type-system/extension-traits.md msgid "" -"Note that the directory structure under the `aidl/` directory needs to match " -"the package name used in the AIDL file, i.e. the package is `com.example." -"birthdayservice` and the file is at `aidl/com/example/IBirthdayService.aidl`." +"The Rust compiler won't allow it, though. But you can use the **extension " +"trait pattern** to work around this limitation." msgstr "" -#: src/android/aidl/example-service/service-bindings.md -msgid "Generated Service API" +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "A Rust item (be it a trait or a type) is referred to as:" msgstr "" -#: src/android/aidl/example-service/service-bindings.md -msgid "" -"Binder generates a trait corresponding to the interface definition. trait to " -"talk to the service." +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "**foreign**, if it isn't defined in the current crate" msgstr "" -#: src/android/aidl/example-service/service-bindings.md -#, fuzzy -msgid "_Generated trait_:" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āϰāĻžāĻ¸ā§āϟ" +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "**local**, if it is defined in the current crate" +msgstr "" -#: src/android/aidl/example-service/service-bindings.md +#: src/idiomatic/leveraging-the-type-system/extension-traits.md msgid "" -"Your service will need to implement this trait, and your client will use " -"this trait to talk to the service." +"The distinction has significant implications for [coherence and orphan rules]" +"(https://doc.rust-lang.org/stable/reference/items/implementations.html#r-" +"items.impl.trait.orphan-rule), as we'll get a chance to explore in this " +"section of the course." msgstr "" -#: src/android/aidl/example-service/service-bindings.md -msgid "" -"The generated bindings can be found at `out/soong/.intermediates//`." +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "Compile the example to show the compiler error that's emitted." msgstr "" -#: src/android/aidl/example-service/service-bindings.md +#: src/idiomatic/leveraging-the-type-system/extension-traits.md msgid "" -"Point out how the generated function signature, specifically the argument " -"and return types, correspond the interface definition." +"Highlight how the compiler error message nudges you towards the extension " +"trait pattern." msgstr "" -#: src/android/aidl/example-service/service-bindings.md +#: src/idiomatic/leveraging-the-type-system/extension-traits.md msgid "" -"`String` for an argument results in a different Rust type than `String` as a " -"return type." +"Explain how many type-system restrictions in Rust aim to prevent _ambiguity_." msgstr "" -#: src/android/aidl/example-service/service.md -msgid "Service Implementation" +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "" +"What would happen if you were allowed to define new inherent methods on " +"foreign types? Different crates in your dependency tree might end up " +"defining different methods on the same foreign type with the same name." msgstr "" -#: src/android/aidl/example-service/service.md -msgid "We can now implement the AIDL service:" +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "" +"As soon as there is room for ambiguity, there must be a way to disambiguate. " +"If disambiguation happens implicitly, it can lead to surprising or otherwise " +"unexpected behavior. If disambiguation happens explicitly, it can increase " +"the cognitive load on developers who are reading your code." msgstr "" -#: src/android/aidl/example-service/service.md -#: src/android/aidl/example-service/changing-implementation.md -msgid "_birthday_service/src/lib.rs_:" +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "" +"Furthermore, every time a crate defines a new inherent method on a foreign " +"type, it may cause compilation errors in _your_ code, as you may be forced " +"to introduce explicit disambiguation." msgstr "" -#: src/android/aidl/example-service/service.md -msgid "/// The `IBirthdayService` implementation.\n" +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "" +"Rust has decided to avoid the issue altogether by forbidding the definition " +"of new inherent methods on foreign types." msgstr "" -#: src/android/aidl/example-service/service.md -#: src/android/aidl/example-service/changing-implementation.md -#: src/android/aidl/types/file-descriptor.md -msgid "\"Happy Birthday {name}, congratulations with the {years} years!\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits.md +msgid "" +"Other languages (e.g, Kotlin, C#, Swift) allow adding methods to existing " +"types, often called \"extension methods.\" This leads to different trade-" +"offs in terms of potential ambiguities and the need for global reasoning." msgstr "" -#: src/android/aidl/example-service/service.md -#: src/android/aidl/example-service/server.md -#: src/android/aidl/example-service/client.md -msgid "_birthday_service/Android.bp_:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "" +"An **extension trait** is a local trait definition whose primary purpose is " +"to attach new methods to foreign types." msgstr "" -#: src/android/aidl/example-service/service.md -#: src/android/aidl/example-service/server.md -msgid "\"libbirthdayservice\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "// Bring the extension trait into scope...\n" msgstr "" -#: src/android/aidl/example-service/service.md -#: src/android/aidl/example-service/server.md -#: src/android/aidl/example-service/client.md -msgid "\"birthdayservice\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "// ...then invoke its methods as if they were inherent methods\n" msgstr "" -#: src/android/aidl/example-service/service.md -#: src/android/aidl/example-service/server.md -#: src/android/aidl/example-service/client.md -msgid "\"com.example.birthdayservice-rust\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "\"dad\"" msgstr "" -#: src/android/aidl/example-service/service.md -#: src/android/aidl/example-service/server.md -#: src/android/aidl/example-service/client.md -msgid "\"libbinder_rs\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "\"grandma\"" msgstr "" -#: src/android/aidl/example-service/service.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md msgid "" -"Point out the path to the generated `IBirthdayService` trait, and explain " -"why each of the segments is necessary." +"The `Ext` suffix is conventionally attached to the name of extension traits." msgstr "" -#: src/android/aidl/example-service/service.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md msgid "" -"TODO: What does the `binder::Interface` trait do? Are there methods to " -"override? Where source?" +"It communicates that the trait is primarily used for extension purposes, and " +"it is therefore not intended to be implemented outside the crate that " +"defines it." msgstr "" -#: src/android/aidl/example-service/server.md -msgid "AIDL Server" -msgstr "" - -#: src/android/aidl/example-service/server.md -msgid "Finally, we can create a server which exposes the service:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "" +"Refer to the [\"Extension Trait\" RFC](https://rust-lang.github.io/rfcs/0445-" +"extension-trait-conventions.html) as the authoritative source for naming " +"conventions." msgstr "" -#: src/android/aidl/example-service/server.md -msgid "_birthday_service/src/server.rs_:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "" +"The extension trait implementation for a foreign type must be in the same " +"crate as the trait itself, otherwise you'll be blocked by Rust's [_orphan " +"rule_](https://github.com/rust-lang/rfcs/blob/master/text/2451-re-" +"rebalancing-coherence.md#what-is-coherence-and-why-do-we-care)." msgstr "" -#: src/android/aidl/example-service/server.md -msgid "//! Birthday service.\n" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "The extension trait must be in scope when its methods are invoked." msgstr "" -#: src/android/aidl/example-service/server.md -msgid "/// Entry point for birthday service.\n" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "" +"Comment out the `use` statement in the example to show the compiler error " +"that's emitted if you try to invoke an extension method without having the " +"corresponding extension trait in scope." msgstr "" -#: src/android/aidl/example-service/server.md -msgid "\"Failed to register service\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "" +"The example above uses an [_underscore import_](https://doc.rust-lang.org/" +"stable/reference/items/use-declarations.html#r-items.use.as-underscore) " +"(`use ext::StringExt as _`) to minimize the likelihood of a naming conflict " +"with other imported traits." msgstr "" -#: src/android/aidl/example-service/server.md -msgid "\"birthday_server\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "" +"With an underscore import, the trait is considered to be in scope and you're " +"allowed to invoke its methods on types that implement the trait. Its " +"_symbol_, instead, is not directly accessible. This prevents you, for " +"example, from using that trait in a `where` clause." msgstr "" -#: src/android/aidl/example-service/server.md -msgid "\"src/server.rs\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-foreign-types.md +msgid "" +"Since extension traits aren't meant to be used in `where` clauses, they are " +"conventionally imported via an underscore import." msgstr "" -#: src/android/aidl/example-service/server.md -#: src/android/aidl/example-service/client.md -msgid "// To avoid dynamic link error.\n" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"What happens when you have a name conflict between an inherent method and an " +"extension method?" msgstr "" -#: src/android/aidl/example-service/server.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md msgid "" -"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 students are used to if they've used Binder from C++ or " -"another language. Explain to students why each step is necessary." +"// Which `count_ones` method is invoked?\n" +" // The one from `CountOnesExt`? Or the inherent one from `i32`?\n" msgstr "" -#: src/android/aidl/example-service/server.md -msgid "Create an instance of your service type (`BirthdayService`)." +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"A foreign type may, in a newer version, add a new inherent method with the " +"same name as our extension method." msgstr "" -#: src/android/aidl/example-service/server.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md msgid "" -"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`." +"Ask: What will happen in the example above? Will there be a compiler error? " +"Will one of the two methods be given higher priority? Which one?" msgstr "" -#: src/android/aidl/example-service/server.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md msgid "" -"Call `add_service`, giving it a service identifier and your service object " -"(the `BnBirthdayService` object in the example)." +"Add a `panic!(\"Extension trait\");` in the body of `CountOnesExt::" +"count_ones` to clarify which method is being invoked." msgstr "" -#: src/android/aidl/example-service/server.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md msgid "" -"Call `join_thread_pool` to add the current thread to Binder's thread pool " -"and start listening for connections." +"To prevent users of the Rust language from having to manually specify which " +"method to use in all cases, there is a priority ordering system for how " +"methods get \"picked\" first:" msgstr "" -#: src/android/aidl/example-service/deploy.md -msgid "We can now build, push, and start the service:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "Immutable (`&self`) first" msgstr "" -#: src/android/aidl/example-service/deploy.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md msgid "" -"```shell\n" -"m birthday_server\n" -"adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_server\" /data/local/" -"tmp\n" -"adb root\n" -"adb shell /data/local/tmp/birthday_server\n" -"```" +"Inherent (method defined in the type's `impl` block) before Trait (method " +"added by a trait impl)." msgstr "" -#: src/android/aidl/example-service/deploy.md -msgid "In another terminal, check that the service runs:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "Mutable (`&mut self`) Second" msgstr "" -#: src/android/aidl/example-service/deploy.md -msgid "You can also call the service with `service call`:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "Inherent before Trait." msgstr "" -#: src/android/aidl/example-service/client.md -msgid "AIDL Client" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"If every method with the same name has different mutability and was either " +"defined in as an inherent method or trait method, with no overlap, this " +"makes the job easy for the compiler." msgstr "" -#: src/android/aidl/example-service/client.md -msgid "Finally, we can create a Rust client for our new service." +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"This does introduce some ambiguity for the user, who may be confused as to " +"why a method they're relying on is not producing expected behavior. Avoid " +"name conflicts instead of relying on this mechanism if you can." msgstr "" -#: src/android/aidl/example-service/client.md -#: src/android/aidl/example-service/changing-implementation.md -msgid "_birthday_service/src/client.rs_:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"Demonstrate: Change the signature and implementation of `CountOnesExt::" +"count_ones` to `fn count_ones(&mut self) -> u32` and modify the invocation " +"accordingly:" msgstr "" -#: src/android/aidl/example-service/client.md -msgid "/// Call the birthday service.\n" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"`CountOnesExt::count_ones` is invoked, rather than the inherent method, " +"since `&mut self` has a higher priority than `&self`, the one used by the " +"inherent method." msgstr "" -#: src/android/aidl/example-service/client.md src/android/aidl/types/objects.md -#: src/android/aidl/types/parcelables.md -#: src/android/aidl/types/file-descriptor.md -msgid "\"Failed to connect to BirthdayService\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"If an immutable inherent method and a mutable trait method exist for the " +"same type, we can specify which one to use at the call site by using " +"`(&).count_ones()` to get the immutable (higher priority) method or " +"`(&mut ).count_ones()`" msgstr "" -#: src/android/aidl/example-service/client.md -msgid "// Call the service.\n" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"Point the students to the Rust reference for more information on [method " +"resolution](https://doc.rust-lang.org/stable/reference/expressions/method-" +"call-expr.html)." msgstr "" -#: src/android/aidl/example-service/client.md -msgid "\"{msg}\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"Avoid naming conflicts between extension trait methods and inherent methods. " +"Rust's method resolution algorithm is complex and may surprise users of your " +"code." msgstr "" -#: src/android/aidl/example-service/client.md -msgid "\"birthday_client\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/method-resolution-conflicts.md +msgid "" +"The interaction between the priority search used by Rust's method resolution " +"algorithm and automatic `Deref`ing can be used to emulate [specialization]" +"(https://github.com/rust-lang/rust/issues/31844) on the stable toolchain, " +"primarily in the context of macro-generated code. Check out [\"Autoref " +"Specialization\"](https://github.com/dtolnay/case-studies/blob/master/" +"autoref-specialization/README.md) for the specific details." msgstr "" -#: src/android/aidl/example-service/client.md -msgid "\"src/client.rs\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md +msgid "" +"What happens when you have a name conflict between two different trait " +"methods implemented for the same type?" msgstr "" -#: src/android/aidl/example-service/client.md -msgid "Notice that the client does not depend on `libbirthdayservice`." +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md +msgid "" +"// Which method is invoked?\n" +"// The one from `Ext1`? Or the one from `Ext2`?\n" msgstr "" -#: src/android/aidl/example-service/client.md -msgid "Build, push, and run the client on your device:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md +msgid "" +"The trait you are extending may, in a newer version, add a new trait method " +"with the same name as your extension method. Or another extension trait for " +"the same type may define a method with a name that conflicts with your own " +"extension method." msgstr "" -#: src/android/aidl/example-service/client.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md msgid "" -"```shell\n" -"m birthday_client\n" -"adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_client\" /data/local/" -"tmp\n" -"adb shell /data/local/tmp/birthday_client Charlie 60\n" -"```" +"Ask: what will happen in the example above? Will there be a compiler error? " +"Will one of the two methods be given higher priority? Which one?" msgstr "" -#: src/android/aidl/example-service/client.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md msgid "" -"`Strong` is the trait object representing the service " -"that the client has connected to." +"The compiler rejects the code because it cannot determine which method to " +"invoke. Neither `Ext1` nor `Ext2` has a higher priority than the other." msgstr "" -#: src/android/aidl/example-service/client.md -msgid "" -"`Strong` is a custom smart pointer type for Binder. It handles both an in-" -"process ref count for the service trait object, and the global Binder ref " -"count that tracks how many processes have a reference to the object." +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md +msgid "To resolve this conflict, you must specify which trait you want to use." msgstr "" -#: src/android/aidl/example-service/client.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md msgid "" -"Note that the trait object that the client uses to talk to the service uses " -"the exact same trait that the server implements. For a given Binder " -"interface, there is a single Rust trait generated that both client and " -"server use." +"Demonstrate: call `Ext1::is_palindrome(\"dad\")` or `Ext2::" +"is_palindrome(\"dad\")` instead of `\"dad\".is_palindrome()`." msgstr "" -#: src/android/aidl/example-service/client.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md msgid "" -"Use the same service identifier used when registering the service. This " -"should ideally be defined in a common crate that both the client and server " -"can depend on." +"For methods with more complex signatures, you may need to use a more " +"explicit [fully-qualified syntax](https://doc.rust-lang.org/reference/" +"expressions/call-expr.html#disambiguating-function-calls)." msgstr "" -#: src/android/aidl/example-service/changing-definition.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.md msgid "" -"Let us extend the API with more functionality: we want to let clients " -"specify a list of lines for the birthday card:" +"Demonstrate: replace `\"dad\".is_palindrome()` with `::" +"is_palindrome(\"dad\")` or `::is_palindrome(\"dad\")`." msgstr "" -#: src/android/aidl/example-service/changing-definition.md -msgid "This results in an updated trait definition for `IBirthdayService`:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"As with types, it may be desirable to **extend foreign traits**. In " +"particular, to attach new methods to _all_ implementors of a given trait." msgstr "" -#: src/android/aidl/example-service/changing-definition.md -msgid "" -"Note how the `String[]` in the AIDL definition is translated as a " -"`&[String]` in Rust, i.e. that idiomatic Rust types are used in the " -"generated bindings wherever possible:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "\"'{}'\"" msgstr "" -#: src/android/aidl/example-service/changing-definition.md -msgid "`in` array arguments are translated to slices." +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "\"'dad'\"" msgstr "" -#: src/android/aidl/example-service/changing-definition.md -msgid "`out` and `inout` args are translated to `&mut Vec`." +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "\"'4'\"" msgstr "" -#: src/android/aidl/example-service/changing-definition.md -msgid "Return values are translated to returning a `Vec`." +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "\"'true'\"" msgstr "" -#: src/android/aidl/example-service/changing-implementation.md -msgid "Updating Client and Service" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"Highlight how we added new behavior to _multiple_ types at once. `.quoted()` " +"can be called on string slices, numbers, and booleans since they all " +"implement the `Display` trait." msgstr "" -#: src/android/aidl/example-service/changing-implementation.md -msgid "Update the client and server code to account for the new API." +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"This flavor of the extension trait pattern uses [_blanket implementations_]" +"(https://doc.rust-lang.org/stable/reference/glossary.html#blanket-" +"implementation)." msgstr "" -#: src/android/aidl/example-service/changing-implementation.md -msgid "'\\n'" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"A blanket implementation implements a trait for all types `T` that satisfy " +"the trait bounds specified in the `impl` block. In this case, the only " +"requirement is that `T` implements the `Display` trait." msgstr "" -#: src/android/aidl/example-service/changing-implementation.md -msgid "\"Habby birfday to yuuuuu\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"Draw the students' attention to the implementation of `DisplayExt::quoted`: " +"we can't make any assumptions about `T` other than that it implements " +"`Display`. All our logic must either use methods from `Display` or functions/" +"macros that don't require other traits." msgstr "" -#: src/android/aidl/example-service/changing-implementation.md -msgid "\"And also: many more\"" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"For example, we can call `format!` with `T`, but can't call `." +"to_uppercase()` because it is not necessarily a `String`." msgstr "" -#: src/android/aidl/example-service/changing-implementation.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md msgid "" -"TODO: Move code snippets into project files where they'll actually be built?" +"We could introduce additional trait bounds on `T`, but it would restrict the " +"set of types that can leverage the extension trait." msgstr "" -#: src/android/aidl/types.md -msgid "Working With AIDL Types" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"Conventionally, the extension trait is named after the trait it extends, " +"followed by the `Ext` suffix. In the example above, `DisplayExt`." msgstr "" -#: src/android/aidl/types.md -msgid "AIDL types translate into the appropriate idiomatic Rust type:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"There are entire crates that extend standard library traits with new " +"functionality." msgstr "" -#: src/android/aidl/types.md -msgid "Primitive types map (mostly) to idiomatic Rust types." +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"`itertools` crate provides the `Itertools` trait that extends `Iterator`. It " +"adds many iterator adapters, such as `interleave` and `unique`. It provides " +"new algorithmic building blocks for iterator pipelines built with method " +"chaining." msgstr "" -#: src/android/aidl/types.md -msgid "Collection types like slices, `Vec`s and string types are supported." +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"`futures` crate provides the `FutureExt` trait, which extends the `Future` " +"trait with new combinators and helper methods." msgstr "" -#: src/android/aidl/types.md +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md msgid "" -"References to AIDL objects and file handles can be sent between clients and " -"services." +"Extension traits can be used by libraries to distinguish between stable and " +"experimental methods." msgstr "" -#: src/android/aidl/types.md -msgid "File handles and parcelables are fully supported." +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "Stable methods are part of the trait definition." msgstr "" -#: src/android/aidl/types/primitives.md -msgid "Primitive types map (mostly) idiomatically:" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"Experimental methods are provided via an extension trait defined in a " +"different library, with a less restrictive stability policy. Some utility " +"methods are then \"promoted\" to the core trait definition once they have " +"been proven useful and their design has been refined." msgstr "" -#: src/android/aidl/types/primitives.md -#, fuzzy -msgid "AIDL Type" -msgstr "AIDL" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"Extension traits can be used to split a [dyn-incompatible trait](https://doc." +"rust-lang.org/reference/items/traits.html#r-items.traits.dyn-compatible) in " +"two:" +msgstr "" -#: src/android/aidl/types/primitives.md src/android/aidl/types/arrays.md -#: src/android/interoperability/cpp/type-mapping.md -#, fuzzy -msgid "Rust Type" -msgstr "āωāĻĻāĻžāĻšāϰāϪ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āϰāĻžāĻ¸ā§āϟ" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"A **dyn-compatible core**, restricted to the methods that satisfy dyn-" +"compatibility requirements." +msgstr "" -#: src/android/aidl/types/primitives.md -msgid "Note" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"An **extension trait**, containing the remaining methods that are not dyn-" +"compatible (e.g., methods with a generic parameter)." msgstr "" -#: src/android/aidl/types/primitives.md -#, fuzzy -msgid "`boolean`" -msgstr "`bool`" +#: src/idiomatic/leveraging-the-type-system/extension-traits/extending-other-traits.md +msgid "" +"Concrete types that implement the core trait will be able to invoke all " +"methods, thanks to the blanket impl for the extension trait. Trait objects " +"(`dyn CoreTrait`) will be able to invoke all methods on the core trait as " +"well as those on the extension trait that don't require `Self: Sized`." +msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`byte`" +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "" +"In what scenarios should you prefer an extension trait over a free function?" msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`i8`" +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "// vs\n" msgstr "" -#: src/android/aidl/types/primitives.md -msgid "Note that bytes are signed." +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "The main advantage of extension traits is **ease of discovery**." msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`u16`" +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "" +"Extension methods can be easier to discover than free functions. Language " +"servers (e.g., `rust-analyzer`) will suggest them if you type `.` after an " +"instance of the foreign type." msgstr "" -#: src/android/aidl/types/primitives.md -msgid "Note the usage of `u16`, NOT `u32`." +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "" +"However, a bespoke extension trait might be overkill for a single method. " +"Both approaches require an additional import, and the familiar method syntax " +"may not justify the boilerplate of a full trait definition." msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`int`" +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "" +"**Discoverability:** Extension methods are easier to discover than free " +"functions. Language servers (e.g., `rust-analyzer`) will suggest them if you " +"type `.` after an instance of the foreign type." msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`i32`" +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "" +"**Method Chaining:** A major ergonomic win for extension traits is method " +"chaining. This is the foundation of the `Iterator` trait, allowing for " +"fluent calls like `data.iter().filter(...).map(...)`. Achieving this with " +"free functions would be far more cumbersome " +"(`map(filter(iter(data), ...), ...)`)." msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`long`" +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "" +"**API Cohesion:** Extension traits help create a cohesive API. If you have " +"several related functions for a foreign type (e.g., `is_palindrome`, " +"`word_count`, `to_kebab_case`), grouping them in a single `StrExt` trait is " +"often cleaner than having multiple free functions for a user to import." msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`i64`" +#: src/idiomatic/leveraging-the-type-system/extension-traits/should-i-define-an-extension-trait.md +msgid "" +"**Trade-offs:** Despite these advantages, a bespoke extension trait might be " +"overkill for a single, simple function. Both approaches require an " +"additional import, and the familiar method syntax may not justify the " +"boilerplate of a full trait definition." msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`float`" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +msgid "Typestate Pattern: Problem" msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`f32`" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +msgid "" +"How can we ensure that only valid operations are allowed on a value based on " +"its current state?" msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`double`" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md +msgid "\"{name} {{\"" msgstr "" -#: src/android/aidl/types/primitives.md -msgid "`f64`" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "\" {key}={value};\"" msgstr "" -#: src/android/aidl/types/arrays.md -msgid "" -"The array types (`T[]`, `byte[]`, and `List`) get translated to the " -"appropriate Rust array type depending on how they are used in the function " -"signature:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "\"}\\n\"" msgstr "" -#: src/android/aidl/types/arrays.md -#, fuzzy -msgid "Position" -msgstr "āϏāĻŽāĻžāϧāĻžāύāϏāĻŽā§‚āĻš" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "\"User\"" +msgstr "" -#: src/android/aidl/types/arrays.md -msgid "`in` argument" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "\"id\"" msgstr "" -#: src/android/aidl/types/arrays.md -#, fuzzy -msgid "`&[T]`" -msgstr "Slices" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "\"42\"" +msgstr "" -#: src/android/aidl/types/arrays.md -msgid "`out`/`inout` argument" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "\"name\"" msgstr "" -#: src/android/aidl/types/arrays.md -msgid "`&mut Vec`" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +msgid "// serializer.serialize_struct_end(); // ← Oops! Forgotten\n" msgstr "" -#: src/android/aidl/types/arrays.md -msgid "Return" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +msgid "This `Serializer` is meant to write a structured value." msgstr "" -#: src/android/aidl/types/arrays.md -#: src/android/interoperability/cpp/type-mapping.md -msgid "`Vec`" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +msgid "" +"However, in this example we forgot to call `serialize_struct_end()` before " +"`finish()`. As a result, the serialized output is incomplete or " +"syntactically incorrect." msgstr "" -#: src/android/aidl/types/arrays.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md msgid "" -"In Android 13 or higher, fixed-size arrays are supported, i.e. `T[N]` " -"becomes `[T; N]`. Fixed-size arrays can have multiple dimensions (e.g. " -"int\\[3\\]\\[4\\]). In the Java backend, fixed-size arrays are represented " -"as array types." +"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." msgstr "" -#: src/android/aidl/types/arrays.md -msgid "Arrays in parcelable fields always get translated to `Vec`." +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +msgid "But this has downsides:" msgstr "" -#: src/android/aidl/types/objects.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md msgid "" -"AIDL objects can be sent either as a concrete AIDL type or as the type-" -"erased `IBinder` interface:" +"It is easy to get wrong as an implementer. Rust’s type system cannot help " +"enforce the correctness of our state transitions." msgstr "" -#: src/android/aidl/types/objects.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md msgid "" -"**birthday_service/aidl/com/example/birthdayservice/IBirthdayInfoProvider." -"aidl**:" +"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." msgstr "" -#: src/android/aidl/types/objects.md src/android/aidl/types/parcelables.md -#: src/android/aidl/types/file-descriptor.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md msgid "" -"**birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl**:" +"A better solution is to model the valid state transitions directly in the " +"type system." msgstr "" -#: src/android/aidl/types/objects.md -msgid "/** The same thing, but using a binder object. */" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern.md +msgid "" +"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." msgstr "" -#: src/android/aidl/types/objects.md -msgid "/** The same thing, but using `IBinder`. */" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "Typestate Pattern: Example" msgstr "" -#: src/android/aidl/types/objects.md src/android/aidl/types/parcelables.md -#: src/android/aidl/types/file-descriptor.md -msgid "**birthday_service/src/client.rs**:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "" +"The typestate pattern encodes part of a value’s runtime state into its type. " +"This allows us to prevent invalid or inapplicable operations at compile time." msgstr "" -#: src/android/aidl/types/objects.md -msgid "/// Rust struct implementing the `IBirthdayInfoProvider` interface.\n" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "`Serializer` usage flowchart:" msgstr "" -#: src/android/aidl/types/objects.md -msgid "// Create a binder object for the `IBirthdayInfoProvider` interface.\n" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "" +"This example is inspired by Serde’s [`Serializer` trait](https://docs.rs/" +"serde/latest/serde/ser/trait.Serializer.html). Serde uses typestates " +"internally to ensure serialization follows a valid structure. For more, see: " +"" msgstr "" -#: src/android/aidl/types/objects.md -msgid "// Send the binder object to the service.\n" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "" +"The key idea behind typestate is that state transitions happen by consuming " +"a value and producing a new one. At each step, only operations valid for " +"that state are available." msgstr "" -#: src/android/aidl/types/objects.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "In this example:" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md msgid "" -"// Perform the same operation but passing the provider as an `SpIBinder`.\n" +"We begin with a `Serializer`, which only allows us to start serializing a " +"struct." msgstr "" -#: src/android/aidl/types/objects.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md msgid "" -"Note the usage of `BnBirthdayInfoProvider`. This serves the same purpose as " -"`BnBirthdayService` that we saw previously." +"Once we call `.serialize_struct(...)`, ownership moves into a " +"`SerializeStruct` value. From that point on, we can only call methods " +"related to serializing struct fields." msgstr "" -#: src/android/aidl/types/parcelables.md -msgid "Binder for Rust supports sending parcelables directly:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "" +"The original `Serializer` is no longer accessible — preventing us from " +"mixing modes (such as starting another _struct_ mid-struct) or calling " +"`finish()` too early." msgstr "" -#: src/android/aidl/types/parcelables.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md msgid "" -"**birthday_service/aidl/com/example/birthdayservice/BirthdayInfo.aidl**:" +"Only after calling `.finish_struct()` do we receive the `Serializer` back. " +"At that point, the output can be finalized or reused." msgstr "" -#: src/android/aidl/types/parcelables.md -msgid "/** The same thing, but with a parcelable. */" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md +msgid "" +"If we forget to call `finish_struct()` and drop the `SerializeStruct` early, " +"the `Serializer` is also dropped. This ensures incomplete output cannot leak " +"into the system." msgstr "" -#: src/android/aidl/types/file-descriptor.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-example.md msgid "" -"Files can be sent between Binder clients/servers using the " -"`ParcelFileDescriptor` type:" +"By contrast, if we had implemented everything on `Serializer` directly — as " +"seen on the previous slide, nothing would stop someone from skipping " +"important steps or mixing serialization flows." msgstr "" -#: src/android/aidl/types/file-descriptor.md -msgid "/** The same thing, but loads info from a file. */" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "" +"How do we manage increasingly complex configuration flows with many possible " +"states and transitions, while still preventing incompatible operations?" msgstr "" -#: src/android/aidl/types/file-descriptor.md -msgid "// Open a file and put the birthday info in it.\n" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "/* [...] */" msgstr "" -#: src/android/aidl/types/file-descriptor.md -msgid "\"/data/local/tmp/birthday.info\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "" +"// TODO, implement:\n" +" //\n" +" // fn serialize_struct(self, name: &str) -> SerializeStruct\n" +" // fn finish(self) -> String\n" msgstr "" -#: src/android/aidl/types/file-descriptor.md -msgid "\"{name}\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "" +"// TODO, implement:\n" +" //\n" +" // fn serialize_property(mut self, name: &str) -> " +"SerializeStructProperty\n" msgstr "" -#: src/android/aidl/types/file-descriptor.md -msgid "\"{years}\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "" +"// TODO,\n" +" // How should we finish this struct? This depends on where it appears:\n" +" // - At the root level: return `Serializer`\n" +" // - As a property inside another struct: return `SerializeStruct`\n" +" // - As a value inside a list: return `SerializeList`\n" +" //\n" +" // fn finish(self) -> ???\n" msgstr "" -#: src/android/aidl/types/file-descriptor.md -msgid "// Create a `ParcelFileDescriptor` from the file and send it.\n" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "" +"// TODO, implement:\n" +" //\n" +" // fn serialize_string(self, value: &str) -> SerializeStruct\n" +" // fn serialize_struct(self, name: &str) -> SerializeStruct\n" +" // fn serialize_list(self) -> SerializeList\n" +" // fn finish(self) -> SerializeStruct\n" msgstr "" -#: src/android/aidl/types/file-descriptor.md -msgid "**birthday_service/src/lib.rs**:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "" +"// TODO, implement:\n" +" //\n" +" // fn serialize_string(mut self, value: &str) -> Self\n" +" // fn serialize_struct(mut self, value: &str) -> SerializeStruct\n" +" // fn serialize_list(mut self) -> SerializeList\n" msgstr "" -#: src/android/aidl/types/file-descriptor.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md msgid "" -"// Convert the file descriptor to a `File`. `ParcelFileDescriptor` wraps\n" -" // an `OwnedFd`, which can be cloned and then used to create a " -"`File`\n" -" // object.\n" +"// TODO:\n" +" // Like `SerializeStruct::finish`, the return type depends on nesting.\n" +" //\n" +" // fn finish(mut self) -> ???\n" msgstr "" -#: src/android/aidl/types/file-descriptor.md -msgid "\"Invalid file handle\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +msgid "Diagram of valid transitions:" msgstr "" -#: src/android/aidl/types/file-descriptor.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md msgid "" -"`ParcelFileDescriptor` wraps an `OwnedFd`, and so can be created from a " -"`File` (or any other type that wraps an `OwnedFd`), and can be used to " -"create a new `File` handle on the other side." +"Building on our previous serializer, we now want to support **nested " +"structures** and **lists**." msgstr "" -#: src/android/aidl/types/file-descriptor.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md msgid "" -"Other types of file descriptors can be wrapped and sent, e.g. TCP, UDP, and " -"UNIX sockets." +"However, this introduces both **duplication** and **structural complexity**." msgstr "" -#: src/android/logging.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md msgid "" -"You should use the `log` crate to automatically log to `logcat` (on-device) " -"or `stdout` (on-host):" +"Even more critically, we now hit a **type system limitation**: we cannot " +"cleanly express what `finish()` should return without duplicating variants " +"for every nesting context (e.g. root, struct, list)." msgstr "" -#: src/android/logging.md -msgid "_hello_rust_logs/Android.bp_:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "From the diagram of valid transitions, we can observe:" msgstr "" -#: src/android/logging.md -msgid "\"hello_rust_logs\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "The transitions are recursive" msgstr "" -#: src/android/logging.md -msgid "\"liblog_rust\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "The return types depend on _where_ a substructure or list appears" msgstr "" -#: src/android/logging.md -msgid "\"liblogger\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "Each context requires a return path to its parent" msgstr "" -#: src/android/logging.md -msgid "_hello_rust_logs/src/main.rs_:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "" +"With only concrete types, this becomes unmanageable. Our current approach " +"leads to an explosion of types and manual wiring." msgstr "" -#: src/android/logging.md -msgid "//! Rust logging demo.\n" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.md +msgid "" +"In the next chapter, we’ll see how **generics** let us model recursive flows " +"with less boilerplate, while still enforcing valid operations at compile " +"time." msgstr "" -#: src/android/logging.md -msgid "/// Logs a greeting.\n" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +msgid "" +"By combining typestate modeling with generics, we can express a wider range " +"of valid states and transitions without duplicating logic. This approach is " +"especially useful when the number of states grows or when multiple states " +"share behavior but differ in structure." msgstr "" -#: src/android/logging.md -msgid "\"rust\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +msgid "" +"We now have all the tools needed to implement the methods for the " +"`Serializer` and its state type definitions. This ensures that our API only " +"permits valid transitions, as illustrated in the following diagram:" msgstr "" -#: src/android/logging.md -msgid "\"Starting program.\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +msgid "" +"By leveraging generics to track the parent context, we can construct " +"arbitrarily nested serializers that enforce valid transitions between " +"struct, list, and property states." msgstr "" -#: src/android/logging.md -msgid "\"Things are going fine.\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +msgid "" +"This enables us to build a recursive structure while maintaining strict " +"control over which methods are accessible in each state." msgstr "" -#: src/android/logging.md -msgid "\"Something went wrong!\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +msgid "" +"Methods common to all states can be defined for any `S` in `Serializer`." msgstr "" -#: src/android/logging.md src/android/interoperability/with-c/bindgen.md -#: src/android/interoperability/with-c/rust.md -msgid "Build, push, and run the binary on your device:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics.md +msgid "" +"Marker types (e.g., `List`) introduce no memory or runtime overhead, as " +"they contain no data other than a possible Zero-Sized Type. Their only role " +"is to enforce correct API usage through the type system." msgstr "" -#: src/android/logging.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md msgid "" -"```shell\n" -"m hello_rust_logs\n" -"adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs\" /data/local/" -"tmp\n" -"adb shell /data/local/tmp/hello_rust_logs\n" +"Referring back to our original diagram of valid transitions, we can " +"visualize the beginning of our implementation as follows:" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md +msgid "" +"```bob\n" +" serialize\n" +" struct\n" +"+--------------------+ --------------> +----------------------------+\n" +"| \"Serializer\" | | \"Serializer>\" |\n" +"+--------------------+ <-------------- +----------------------------+\n" +" finish struct\n" +" |\n" +" |\n" +" |\n" +"finish |\n" +" V\n" +"\n" +" +--------+\n" +" | String |\n" +" +--------+\n" "```" msgstr "" -#: src/android/logging.md -msgid "The logs show up in `adb logcat`:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md +msgid "" +"At the \"root\" of our `Serializer`, the only construct allowed is a " +"`Struct`." msgstr "" -#: src/android/interoperability.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/root.md msgid "" -"Rust has excellent support for interoperability with other languages. This " -"means that you can:" +"The `Serializer` can only be finalized into a `String` from this root level." msgstr "" -#: src/android/interoperability.md -msgid "Call Rust functions from other languages." +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md +msgid "\"{}{name}: \"" msgstr "" -#: src/android/interoperability.md -msgid "Call functions written in other languages from Rust." +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md +msgid "\"{}}}\"" msgstr "" -#: src/android/interoperability.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md +msgid "The diagram can now be expanded as follows:" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md msgid "" -"When you call functions in a foreign language we say that you're using a " -"_foreign function interface_, also known as FFI." +"```bob\n" +" +------+\n" +" finish | |\n" +" serialize struct V |\n" +" struct\n" +"+--------------------+ --------------> +-------------------------+\n" +"| \"Serializer\" | | \"Serializer>\" |\n" +"+--------------------+ <-------------- +-------------------------+\n" +" finish struct\n" +" | serialize |\n" +" | property V\n" +" |\n" +"finish | +-----------------------------------+\n" +" V | \"Serializer>>\" " +"|\n" +" +-----------------------------------+\n" +" +--------+\n" +" | String |\n" +" +--------+\n" +"```" msgstr "" -#: src/android/interoperability/with-c.md -msgid "Interoperability with C" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md +msgid "A `Struct` can only contain a `Property`;" msgstr "" -#: src/android/interoperability/with-c.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/struct.md msgid "" -"Rust has full support for linking object files with a C calling convention. " -"Similarly, you can export Rust functions and call them from C." +"Finishing a `Struct` returns control back to its parent, which in our " +"previous slide was assumed the `Root`, but in reality however it can be also " +"something else such as `Struct` in case of nested \"structs\"." msgstr "" -#: src/android/interoperability/with-c.md -msgid "You can do it by hand if you want:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md +msgid "\"[\"" msgstr "" -#: src/android/interoperability/with-c.md -msgid "\"{x}, {abs_x}\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md +msgid "\"{value},\"" msgstr "" -#: src/android/interoperability/with-c.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md msgid "" -"We already saw this in the [Safe FFI Wrapper exercise](../../exercises/day-3/" -"safe-ffi-wrapper.md)." +"With the addition of the Property state methods, our diagram is now nearly " +"complete:" msgstr "" -#: src/android/interoperability/with-c.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md msgid "" -"This assumes full knowledge of the target platform. Not recommended for " -"production." +"```bob\n" +" +------+\n" +" finish | |\n" +" serialize struct V |\n" +" struct\n" +"+--------------------+ --------------> +-------------------------+\n" +"| \"Serializer\" | | \"Serializer>\" |\n" +"+--------------------+ <-------------- +-------------------------+ " +"<-----------+\n" +" finish " +"struct |\n" +" | serialize " +"| |\n" +" | property V " +"serialize |\n" +" | string " +"or |\n" +"finish | +---------------------------+ " +"struct |\n" +" V | \"Serializer>\" | " +"------------+\n" +" +---------------------------+\n" +" +--------+\n" +" | String | serialize |\n" +" +--------+ list V\n" +"\n" +" +-----------------------+\n" +" | \"Serializer>\" |\n" +" +-----------------------+\n" +"```" msgstr "" -#: src/android/interoperability/with-c.md -msgid "We will look at better options next." +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md +msgid "" +"A property can be defined as a `String`, `Struct`, or `List`, enabling " +"the representation of nested structures." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "Using Bindgen" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/property.md +msgid "" +"This concludes the step-by-step implementation. The full implementation, " +"including support for `List`, is shown in the next slide." msgstr "" -#: src/android/interoperability/with-c/bindgen.md +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "Serializer: complete implementation" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "Looking back at our original desired flow:" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "We can now see this reflected directly in the types of our serializer:" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md msgid "" -"The [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html) " -"tool can auto-generate bindings from a C header file." +"```bob\n" +" +------+\n" +" finish | |\n" +" serialize struct V |\n" +" struct\n" +"+--------------------+ --------------> +-------------------------+ " +"<---------------+\n" +"| \"Serializer\" | | \"Serializer>\" " +"| |\n" +"+--------------------+ <-------------- +-------------------------+ " +"<-----------+ |\n" +" finish " +"struct | |\n" +" | | serialize " +"| | |\n" +" | +----------+ property V " +"serialize | |\n" +" | | string " +"or | |\n" +"finish | | +---------------------------+ " +"struct | |\n" +" V | | \"Serializer>\" | " +"------------+ |\n" +" finish | +---------------------------" +"+ |\n" +" +--------+ struct " +"| |\n" +" | String | | serialize " +"| |\n" +" +--------+ | list " +"V |\n" +" | " +"finish |\n" +" | +-----------------------+ " +"list |\n" +" +-----> | \"Serializer>\" | " +"----------------+\n" +" +-----------------------+\n" +" serialize\n" +" | list or string ^\n" +" | or finish list |\n" +" +-----------------+\n" +"```" msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "First create a small C library:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "" +"The code for the full implementation of the `Serializer` and all its states " +"can be found in [this Rust playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2024&gist=c9cbb831cd05fe9db4ce42713c83ca16)." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "_interoperability/bindgen/libbirthday.h_:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "This pattern isn't a silver bullet. It still allows issues like:" msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "_interoperability/bindgen/libbirthday.c_:" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "" +"Empty or invalid property names (which can be fixed using [the newtype " +"pattern](../../newtype-pattern.md))" msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "" +"Duplicate property names (which could be tracked in `Struct` and handled " +"via `Result`)" msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"libbirthday.h\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "" +"If validation failures occur, we can also change method signatures to return " +"a `Result`, allowing recovery:" msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"+--------------\\n\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "" +"While this API is powerful, it’s not always ergonomic. Production " +"serializers typically favor simpler APIs and reserve the typestate pattern " +"for enforcing critical invariants." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"| Happy Birthday %s!\\n\"" +#: src/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-generics/complete.md +msgid "" +"One excellent real-world example is [`rustls::ClientConfig`](https://docs.rs/" +"rustls/latest/rustls/client/struct.ClientConfig.html#method.builder), which " +"uses typestate with generics to guide the user through safe and correct " +"configuration steps." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"| Congratulations with the %i years!\\n\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "Using the Borrow checker to enforce Invariants" msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "Add this to your `Android.bp` file:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"The borrow checker, while added to enforce memory ownership, can model other " +"problems and prevent API misuse." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "_interoperability/bindgen/Android.bp_:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"/// Doors can be open or closed, and you need the right key to lock or " +"unlock\n" +"/// one. Modelled with a Shared key and Owned door.\n" msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"libbirthday\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "\"Opened the door with key shape '{}'\"" msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"libbirthday.c\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "\"Door wasn't opened! Your key only opens locks with shape '{}'\"" msgstr "" -#: src/android/interoperability/with-c/bindgen.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md msgid "" -"Create a wrapper header file for the library (not strictly needed in this " -"example):" +"We've seen the borrow checker prevent memory safety bugs (use-after-free, " +"data races)." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"We've also used types to shape and restrict APIs already using [the " +"Typestate pattern](../leveraging-the-type-system/typestate-pattern.md)." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "You can now auto-generate the bindings:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "Language features are often introduced for a specific purpose." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"libbirthday_bindgen\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"Over time, users may develop ways of using a feature in ways that were not " +"predicted when they were introduced." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"birthday_bindgen\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"Java 5 introduced Generics in 2004 with the [main stated purpose of enabling " +"type-safe collections](https://jcp.org/en/jsr/detail?id=14)." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"libbirthday_wrapper.h\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"Adoption was slow at first, but some new projects began designing their APIs " +"around generics from the beginning." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"bindings\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"Since then, users and developers of the language expanded the use of " +"generics to other areas of type-safe API design:" msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "Finally, we can use the bindings in our Rust program:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"Class information can be held onto via Java's `Class` or Guava's " +"`TypeToken`." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"print_birthday_card\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "The Builder pattern can be implemented using Recursive Generics." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"main.rs\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"We aim to do something similar here: Even though the borrow checker was " +"introduced to prevent use-after-free and data races, we treat it as just " +"another API design tool." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "_interoperability/bindgen/main.rs_:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"It can be used to model program properties that have nothing to do with " +"preventing memory safety bugs." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "//! Bindgen demo.\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"To use the borrow checker as a problem solving tool, we will need to " +"\"forget\" that the original purpose of it is to prevent mutable aliasing in " +"the context of preventing use-after-frees and data races." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "// SAFETY: `print_card` is safe to call with a valid `card` pointer.\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"We should imagine working within situations where the rules are the same but " +"the meaning is slightly different." msgstr "" -#: src/android/interoperability/with-c/bindgen.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md msgid "" -"```shell\n" -"m print_birthday_card\n" -"adb push \"$ANDROID_PRODUCT_OUT/system/bin/print_birthday_card\" /data/local/" -"tmp\n" -"adb shell /data/local/tmp/print_birthday_card\n" -"```" +"This example uses ownership and borrowing are used to model the state of a " +"physical door." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "Finally, we can run auto-generated tests to ensure the bindings work:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"`open_door` **consumes** a `LockedDoor` and returns a new `OpenDoor`. The " +"old `LockedDoor` value is no longer available." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"libbirthday_bindgen_test\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"If the wrong key is used, the door is left locked. It is returned as an " +"`Err` case of the `Result`." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\":libbirthday_bindgen\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"It is a compile-time error to try and use a door that has already been " +"opened." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"general-tests\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"Similarly, `lock_door` consumes an `OpenDoor`, preventing closing the door " +"twice at compile time." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "\"none\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"The rules of the borrow checker exist to prevent memory safety bugs, but the " +"underlying logical system does not \"know\" what memory is." msgstr "" -#: src/android/interoperability/with-c/bindgen.md -msgid "// Generated file, skip linting\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"All the borrow checker does is enforce a specific set of rules of how users " +"can order operations." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "Calling Rust" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants.md +msgid "" +"This is just one case of piggy-backing onto the rules of the borrow checker " +"to design APIs to be harder or impossible to misuse." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "Exporting Rust functions and types to C is easy:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "// An internal data type to have something to hold onto.\n" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "_interoperability/rust/libanalyze/analyze.rs_" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "// The \"outer\" data.\n" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "//! Rust FFI demo.\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "// let exclusive = exclusive_use(&mut value); // ❌🔨\n" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "/// Analyze the numbers.\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "// let shared = shared_use(&value); // ❌🔨\n" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "\"x ({x}) is smallest!\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"This example re-frames the borrow checker rules away from references and " +"towards semantic meaning in non-memory-safety settings." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "\"y ({y}) is probably larger than x ({x})\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "Nothing is being mutated, nothing is being sent across threads." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "_interoperability/rust/libanalyze/analyze.h_" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"In Rust's borrow checker we have access to three different ways of " +"\"taking\" a value:" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "_interoperability/rust/libanalyze/Android.bp_" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"Owned value `T`. Value is dropped when the scope ends, unless it is not " +"returned to another scope." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "\"libanalyze_ffi\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"Shared Reference `&T`. Allows aliasing but prevents mutable access while " +"shared references are in use." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "\"analyze_ffi\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"Mutable Reference `&mut T`. Only one of these is allowed to exist for a " +"value at any one point, but can be used to create shared references." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "\"analyze.rs\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"Ask: The two commented-out lines in the `demo` functions would cause " +"compilation errors, Why?" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "We can now call this from a C binary:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"`demo_exclusive`: Because the `shared` value is still aliased after the " +"`exclusive` reference is taken." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "_interoperability/rust/analyze/main.c_" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"`demo_denied`: Because `value` is consumed the line before the " +"`shared_again_again` reference is taken from `&value`." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "\"analyze.h\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"Remember that every `&T` and `&mut T` has a lifetime, just one the user " +"doesn't have to annotate or think about most of the time." msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "_interoperability/rust/analyze/Android.bp_" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md +msgid "" +"We rarely specify lifetimes because the Rust compiler allows us to _elide_ " +"them in most cases. See: [Lifetime Elision](../../../lifetimes/lifetime-" +"elision.md)" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "\"analyze_numbers\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "" +"Sometimes we want values that _can only be used once_. One critical example " +"of this is in cryptography: A \"Nonce.\"" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "\"main.c\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "/* specifics omitted */" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "" -"```shell\n" -"m analyze_numbers\n" -"adb push \"$ANDROID_PRODUCT_OUT/system/bin/analyze_numbers\" /data/local/" -"tmp\n" -"adb shell /data/local/tmp/analyze_numbers\n" -"```" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "/// A single-use number suitable for cryptographic purposes.\n" msgstr "" -#: src/android/interoperability/with-c/rust.md -msgid "" -"`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol " -"will just be the name of the function. You can also use `#[export_name = " -"\"some_name\"]` to specify whatever name you want." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "/// A cryptographically sound random generator function.\n" msgstr "" -#: src/android/interoperability/cpp.md -msgid "" -"The [CXX crate](https://cxx.rs/) makes it possible to do safe " -"interoperability between Rust and C++." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "// chosen by a fair dice roll, https://xkcd.com/221/\n" msgstr "" -#: src/android/interoperability/cpp.md -msgid "The overall approach looks like this:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "/// Consume a nonce, but not the key or the data.\n" msgstr "" -#: src/android/interoperability/cpp/bridge.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md msgid "" -"CXX relies on a description of the function signatures that will be exposed " -"from each language to the other. You provide this description using extern " -"blocks in a Rust module annotated with the `#[cxx::bridge]` attribute macro." +"// The key and data can be re-used, copied, etc. but the nonce cannot.\n" msgstr "" -#: src/android/interoperability/cpp/bridge.md -msgid "\"org::blobstore\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "// encrypt(nonce, &key, &data_2); // đŸ› ī¸âŒ\n" msgstr "" -#: src/android/interoperability/cpp/bridge.md -msgid "// Shared structs with fields visible to both languages.\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "Problem: How can we guarantee a value is used only once?" msgstr "" -#: src/android/interoperability/cpp/bridge.md -#: src/android/interoperability/cpp/generated-cpp.md -msgid "// Rust types and signatures exposed to C++.\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "" +"Motivation: A nonce is a piece of random, unique data used in cryptographic " +"protocols to prevent replay attacks." msgstr "" -#: src/android/interoperability/cpp/bridge.md -#: src/android/interoperability/cpp/rust-bridge.md -#: src/android/interoperability/cpp/generated-cpp.md -#: src/android/interoperability/cpp/rust-result.md -#: src/chromium/interoperability-with-cpp/example-bindings.md -#: src/chromium/interoperability-with-cpp/error-handling-qr.md -#: src/chromium/interoperability-with-cpp/error-handling-png.md -#, fuzzy -msgid "\"Rust\"" -msgstr "Rustdoc" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "" +"Background: In practice people have ended up accidentally re-using nonces. " +"Most commonly, this causes the cryptographic protocol to completely break " +"down and stop fulfilling its function." +msgstr "" -#: src/android/interoperability/cpp/bridge.md -#: src/android/interoperability/cpp/cpp-bridge.md -msgid "// C++ types and signatures exposed to Rust.\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "" +"Depending on the specifics of nonce reuse and cryptography at hand, private " +"keys can also become computable by attackers." msgstr "" -#: src/android/interoperability/cpp/bridge.md -#: src/android/interoperability/cpp/cpp-bridge.md -#: src/android/interoperability/cpp/cpp-exception.md -#: src/chromium/interoperability-with-cpp/example-bindings.md -msgid "\"C++\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "" +"Rust has an obvious tool for achieving the invariant \"Once you use this, " +"you can't use it again\": passing a value as an _owned argument_." msgstr "" -#: src/android/interoperability/cpp/bridge.md -#: src/android/interoperability/cpp/cpp-bridge.md -msgid "\"include/blobstore.h\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "" +"Highlight: the `encrypt` function takes `nonce` by value (an owned " +"argument), but `key` and `data` by reference." msgstr "" -#: src/android/interoperability/cpp/bridge.md -msgid "The bridge is generally declared in an `ffi` module within your crate." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "The technique for single-use values is as follows:" msgstr "" -#: src/android/interoperability/cpp/bridge.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md msgid "" -"From the declarations made in the bridge module, CXX will generate matching " -"Rust and C++ type/function definitions in order to expose those items to " -"both languages." +"Keep constructors private, so a user can't construct values with the same " +"inner value twice." msgstr "" -#: src/android/interoperability/cpp/bridge.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md msgid "" -"To view the generated Rust code, use [cargo-expand](https://github.com/" -"dtolnay/cargo-expand) to view the expanded proc macro. For most of the " -"examples you would use `cargo expand ::ffi` to expand just the `ffi` module " -"(though this doesn't apply for Android projects)." +"Don't implement `Clone`/`Copy` traits or equivalent methods, so a user can't " +"duplicate data we want to keep unique." msgstr "" -#: src/android/interoperability/cpp/bridge.md -msgid "To view the generated C++ code, look in `target/cxxbridge`." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "" +"Make the interior type opaque (like with the newtype pattern), so the user " +"cannot modify an existing value on their own." msgstr "" -#: src/android/interoperability/cpp/rust-bridge.md -msgid "Rust Bridge Declarations" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "Ask: What are we missing from the newtype pattern in the slide's code?" msgstr "" -#: src/android/interoperability/cpp/rust-bridge.md -msgid "// Opaque type\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "Expect: Module boundary." msgstr "" -#: src/android/interoperability/cpp/rust-bridge.md -msgid "// Method on `MyType`\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "" +"Demonstrate: Without a module boundary a user can construct a nonce on their " +"own." msgstr "" -#: src/android/interoperability/cpp/rust-bridge.md -#, fuzzy -msgid "// Free function\n" -msgstr "āĻĢāĻžāĻ‚āĻļāύ" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +msgid "Fix: Put `Key`, `Nonce`, and `new_nonce` behind a module." +msgstr "" -#: src/android/interoperability/cpp/rust-bridge.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md msgid "" -"Items declared in the `extern \"Rust\"` reference items that are in scope in " -"the parent module." +"Cryptography Nuance: A nonce might still be used twice if it was created " +"through pseudo-random process with no actual randomness. That can't be " +"prevented through this method. This API design prevents one nonce " +"duplication, but not all logic bugs." msgstr "" -#: src/android/interoperability/cpp/rust-bridge.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md msgid "" -"The CXX code generator uses your `extern \"Rust\"` section(s) to produce a C+" -"+ header file containing the corresponding C++ declarations. The generated " -"header has the same path as the Rust source file containing the bridge, " -"except with a .rs.h file extension." +"We can use the mutual exclusion of `&T` and `&mut T` references to prevent " +"data from being used before it is ready." msgstr "" -#: src/android/interoperability/cpp/generated-cpp.md -msgid "Results in (roughly) the following C++:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "/* fields omitted */" msgstr "" -#: src/android/interoperability/cpp/cpp-bridge.md -msgid "C++ Bridge Declarations" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "// fake results\n" msgstr "" -#: src/android/interoperability/cpp/cpp-bridge.md -msgid "Results in (roughly) the following Rust:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "// Send the query over, but don't wait for results.\n" msgstr "" -#: src/android/interoperability/cpp/cpp-bridge.md -msgid "\"org$blobstore$cxxbridge1$new_blobstore_client\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "// Finish executing the transaction and retrieve the results.\n" msgstr "" -#: src/android/interoperability/cpp/cpp-bridge.md -msgid "\"org$blobstore$cxxbridge1$BlobstoreClient$put\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "// The transaction `tx` mutably borrows `db`.\n" msgstr "" -#: src/android/interoperability/cpp/cpp-bridge.md -msgid "" -"The programmer does not need to promise that the signatures they have typed " -"in are accurate. CXX performs static assertions that the signatures exactly " -"correspond with what is declared in C++." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "\"SELECT * FROM users\"" msgstr "" -#: src/android/interoperability/cpp/cpp-bridge.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md msgid "" -"`unsafe extern` blocks allow you to declare C++ functions that are safe to " -"call from Rust." +"// This won't compile because `db` is already mutably borrowed by `tx`.\n" +" // let results = db.results(); // ❌🔨\n" msgstr "" -#: src/android/interoperability/cpp/shared-types.md -msgid "// A=1, J=11, Q=12, K=13\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "// The borrow of `db` ends when `tx` is consumed by `commit()`.\n" msgstr "" -#: src/android/interoperability/cpp/shared-types.md -msgid "Only C-like (unit) enums are supported." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "// Now it is possible to borrow `db` again.\n" msgstr "" -#: src/android/interoperability/cpp/shared-types.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md msgid "" -"A limited number of traits are supported for `#[derive()]` on shared types. " -"Corresponding functionality is also generated for the C++ code, e.g. if you " -"derive `Hash` also generates an implementation of `std::hash` for the " -"corresponding C++ type." +"Motivation: In this database API queries are kicked off for asynchronous " +"execution and the results are only available once the whole transaction is " +"finished." msgstr "" -#: src/android/interoperability/cpp/shared-enums.md -#, fuzzy -msgid "Generated Rust:" -msgstr "āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āϰāĻžāĻ¸ā§āϟ" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "" +"A user might think that queries are executed immediately, and try to read " +"results before they are made available. This API misuse could make the app " +"read incomplete or incorrect data." +msgstr "" -#: src/android/interoperability/cpp/shared-enums.md -msgid "Generated C++:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "" +"While an obvious misunderstanding, situations such as this can happen in " +"practice." msgstr "" -#: src/android/interoperability/cpp/shared-enums.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md msgid "" -"On the Rust side, the code generated for shared enums is actually a struct " -"wrapping a numeric value. This is because it is not UB in C++ for an enum " -"class to hold a value different from all of the listed variants, and our " -"Rust representation needs to have the same behavior." +"Ask: Has anyone misunderstood an API by not reading the docs for proper use?" msgstr "" -#: src/android/interoperability/cpp/rust-result.md -msgid "\"fallible1 requires depth > 0\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "" +"Expect: Examples of early-career or in-university mistakes and " +"misunderstandings." msgstr "" -#: src/android/interoperability/cpp/rust-result.md -msgid "\"Success!\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "" +"As an API grows in size and user base, a smaller percentage of users has " +"deep knowledge of the system the API represents." msgstr "" -#: src/android/interoperability/cpp/rust-result.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md msgid "" -"Rust functions that return `Result` are translated to exceptions on the C++ " -"side." +"This example shows how we can use Aliasing XOR Mutability to prevent this " +"kind of misuse." msgstr "" -#: src/android/interoperability/cpp/rust-result.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md msgid "" -"The exception thrown will always be of type `rust::Error`, which primarily " -"exposes a way to get the error message string. The error message will come " -"from the error type's `Display` impl." +"The code might read results before they are ready if the programmer assumes " +"that the queries execute immediately rather than kicked off for asynchronous " +"execution." msgstr "" -#: src/android/interoperability/cpp/rust-result.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md msgid "" -"A panic unwinding from Rust to C++ will always cause the process to " -"immediately terminate." +"The constructor for the `Transaction` type takes a mutable reference to the " +"database connection, and stores it in the returned `Transaction` value." msgstr "" -#: src/android/interoperability/cpp/cpp-exception.md -msgid "\"example/include/example.h\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "" +"The explicit lifetime here doesn't have to be intimidating, it just means " +"\"`Transaction` is outlived by the `DatabaseConnection` that was passed to " +"it\" in this case." +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "" +"The reference is mutable to completely lock out the `DatabaseConnection` " +"from other usage, such as starting further transactions or reading the " +"results." +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "" +"While a `Transaction` exists, we can't touch the `DatabaseConnection` " +"variable that was created from it." msgstr "" -#: src/android/interoperability/cpp/cpp-exception.md -msgid "\"Error: {}\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md +msgid "" +"Demonstrate: uncomment the `db.results()` line. Doing so will result in a " +"compile error, as `db` is already mutably borrowed." msgstr "" -#: src/android/interoperability/cpp/cpp-exception.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md msgid "" -"C++ functions declared to return a `Result` will catch any thrown exception " -"on the C++ side and return it as an `Err` value to the calling Rust function." +"Note: The query results not being public and placed behind a getter function " +"lets us enforce the invariant \"users can only look at query results if " +"there is no active transactions.\"" msgstr "" -#: src/android/interoperability/cpp/cpp-exception.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/aliasing-xor-mutability.md msgid "" -"If an exception is thrown from an extern \"C++\" function that is not " -"declared by the CXX bridge to return `Result`, the program calls C++'s `std::" -"terminate`. The behavior is equivalent to the same exception being thrown " -"through a `noexcept` C++ function." +"If the query results were placed in a public struct field, this invariant " +"could be violated." msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -#, fuzzy -msgid "C++ Type" -msgstr "Types" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +msgid "PhantomData 1/4: De-duplicating Same Data & Semantics" +msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -#, fuzzy -msgid "`rust::String`" -msgstr "String" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +msgid "" +"The newtype pattern can sometimes come up against the DRY principle, how do " +"we solve this?" +msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`&str`" -msgstr "`&str`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +msgid "// And so on ...\n" +msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`rust::Str`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +msgid "" +"Problem: We want to use the newtype pattern to differentiate permissions, " +"but we're having to implement the same traits over and over again for the " +"same data." msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -#, fuzzy -msgid "`CxxString`" -msgstr "String" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +msgid "" +"Ask: Assume the details of each implementation here are the same between " +"types, what are ways we can avoid repeating ourselves?" +msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`std::string`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "Expect:" msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`&[T]`/`&mut [T]`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +msgid "Make this an enum, not distinct data types." msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`rust::Slice`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +msgid "" +"Bundle the user ID with permission tokens like `struct Admin(u64, " +"UserPermission, ModeratorPermission, AdminPermission);`" msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`rust::Box`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +msgid "Adding a type parameter which encodes permissions." msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`UniquePtr`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-01-types.md +msgid "Mentioning `PhantomData` ahead of schedule (it's in the title)." msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`std::unique_ptr`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "PhantomData 2/4: Type-level tagging" msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`rust::Vec`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "" +"Let's solve the problem from the previous slide by adding a type parameter." msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`CxxVector`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "// use std::marker::PhantomData;\n" msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "`std::vector`" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "// Admins are users\n" msgstr "" -#: src/android/interoperability/cpp/type-mapping.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md msgid "" -"These types can be used in the fields of shared structs and the arguments " -"and returns of extern functions." +"// impl Debug for UserTag {/* ... */}\n" +"// impl PartialEq for UserTag {/* ... */}\n" +"// impl Eq for UserTag {/* ... */}\n" +"// And so on ...\n" msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "" -"Note that Rust's `String` does not map directly to `std::string`. There are " -"a few reasons for this:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "/* All functionality for users and above */" msgstr "" -#: src/android/interoperability/cpp/type-mapping.md -msgid "" -"`std::string` does not uphold the UTF-8 invariant that `String` requires." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "/* All functionality for only admins */" msgstr "" -#: src/android/interoperability/cpp/type-mapping.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md msgid "" -"The two types have different layouts in memory and so can't be passed " -"directly between languages." +"Here we're using a type parameter and gating permissions behind \"tag\" " +"types that implement different permission traits." msgstr "" -#: src/android/interoperability/cpp/type-mapping.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md msgid "" -"`std::string` requires move constructors that don't match Rust's move " -"semantics, so a `std::string` can't be passed by value to Rust." +"Tag types, or marker types, are zero-sized types that have some semantic " +"meaning to users and API designers." msgstr "" -#: src/android/interoperability/cpp/android-build-cpp.md -#: src/android/interoperability/cpp/android-cpp-genrules.md -#: src/android/interoperability/cpp/android-build-rust.md -#, fuzzy -msgid "Building in Android" -msgstr "āĻ…ā§āϝāĻžāĻ¨ā§āĻĄā§āϰāϝāĻŧ⧇āĻĄā§‡ āϰāĻžāĻ¸ā§āϟ" - -#: src/android/interoperability/cpp/android-build-cpp.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md msgid "" -"Create a `cc_library_static` to build the C++ library, including the CXX " -"generated header and source file." +"Ask: What issues does having it be an actual instance of that type pose?" msgstr "" -#: src/android/interoperability/cpp/android-build-cpp.md -#: src/android/interoperability/cpp/android-build-rust.md -msgid "\"libcxx_test_cpp\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "" +"Answer: If it's not a zero-sized type (like `()` or `struct MyTag;`), then " +"we're allocating more memory than we need to when all we care for is type " +"information that is only relevant at compile-time." msgstr "" -#: src/android/interoperability/cpp/android-build-cpp.md -msgid "\"cxx_test.cpp\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "Demonstrate: remove the `tag` value entirely, then compile!" msgstr "" -#: src/android/interoperability/cpp/android-build-cpp.md -msgid "\"cxx-bridge-header\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "This won't compile, as there's an unused (phantom) type parameter." msgstr "" -#: src/android/interoperability/cpp/android-build-cpp.md -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "\"libcxx_test_bridge_header\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "This is where `PhantomData` comes in!" msgstr "" -#: src/android/interoperability/cpp/android-build-cpp.md -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "\"libcxx_test_bridge_code\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "" +"Demonstrate: Uncomment the `PhantomData` import, and make `ChatId` the " +"following:" msgstr "" -#: src/android/interoperability/cpp/android-build-cpp.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md msgid "" -"Point out that `libcxx_test_bridge_header` and `libcxx_test_bridge_code` are " -"the dependencies for the CXX-generated C++ bindings. We'll show how these " -"are setup on the next slide." +"`PhantomData` is a zero-sized type with a type parameter. We can " +"construct values of it like other ZSTs with `let phantom: " +"PhantomData = PhantomData;` or with the `PhantomData::default()` " +"implementation." msgstr "" -#: src/android/interoperability/cpp/android-build-cpp.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md msgid "" -"Note that you also need to depend on the `cxx-bridge-header` library in " -"order to pull in common CXX definitions." +"Demonstrate: implement `From` for `ChatId`, emphasizing the " +"construction of `PhantomData`" msgstr "" -#: src/android/interoperability/cpp/android-build-cpp.md -msgid "" -"Full docs for using CXX in Android can be found in [the Android docs]" -"(https://source.android.com/docs/setup/build/rust/building-rust-modules/" -"android-rust-patterns#rust-cpp-interop-using-cxx). You may want to share " -"that link with the class so that students know where they can find these " -"instructions again in the future." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md +msgid "// Or `PhantomData::default()`\n" msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-02-types-implemented.md msgid "" -"Create two genrules: One to generate the CXX header, and one to generate the " -"CXX source file. These are then used as inputs to the `cc_library_static`." +"`PhantomData` can be used as part of the Typestate pattern to have data with " +"the same structure but different methods, e.g., have `TaggedData` " +"implement methods or trait implementations that `TaggedData` doesn't." msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "// Generate a C++ header containing the C++ bindings" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "PhantomData 3/4: Lifetimes for External Resources" msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "// to the Rust exported functions in lib.rs." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"The invariants of external resources often match what we can do with " +"lifetime rules." msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "\"cxxbridge\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"/// Direct FFI to a database library in C.\n" +"/// We got this API as is, we have no influence over it.\n" msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "\"$(location cxxbridge) $(in) --header > $(out)\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "// maximum 255 databases open at the same time\n" msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md -#: src/android/interoperability/cpp/android-build-rust.md -msgid "\"lib.rs\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "// ... etc.\n" msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "\"lib.rs.h\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"Remember the transaction API from the [Aliasing XOR Mutability](./aliasing-" +"xor-mutability.md) example." msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "// Generate the C++ code that Rust calls into." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"We held onto a mutable reference to the database connection within the " +"transaction type to lock out the database while a transaction is active." msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "\"$(location cxxbridge) $(in) > $(out)\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"In this example, we want to implement a `Transaction` API on top of an " +"external, non-Rust API." msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md -msgid "\"lib.rs.cc\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"We start by defining a `Transaction` type that holds onto `&mut " +"DatabaseConnection`." msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md msgid "" -"The `cxxbridge` tool is a standalone tool that generates the C++ side of the " -"bridge module. It is included in Android and available as a Soong tool." +"Ask: What are the limits of this implementation? Assume the `u8` is accurate " +"implementation-wise and enough information for us to use the external API." msgstr "" -#: src/android/interoperability/cpp/android-cpp-genrules.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md msgid "" -"By convention, if your Rust source file is `lib.rs` your header file will be " -"named `lib.rs.h` and your source file will be named `lib.rs.cc`. This naming " -"convention isn't enforced, though." +"Indirection takes up 7 bytes more than we need to on a 64-bit platform, as " +"well as costing a pointer dereference at runtime." msgstr "" -#: src/android/interoperability/cpp/android-build-rust.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md msgid "" -"Create a `rust_binary` that depends on `libcxx` and your `cc_library_static`." +"Problem: We want the transaction to borrow the database connection that " +"created it, but we don't want the `Transaction` object to store a real " +"reference." msgstr "" -#: src/android/interoperability/cpp/android-build-rust.md -msgid "\"cxx_test\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"Ask: What happens when we remove the mutable reference in `Transaction` " +"while keeping the lifetime parameter?" msgstr "" -#: src/android/interoperability/cpp/android-build-rust.md -msgid "\"libcxx\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "Expect: Unused lifetime parameter!" msgstr "" -#: src/android/interoperability/java.md -msgid "Interoperability with Java" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"Like with the type tagging from the previous slides, we can bring in " +"`PhantomData` to capture this unused lifetime parameter for us." msgstr "" -#: src/android/interoperability/java.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md msgid "" -"Java can load shared objects via [Java Native Interface (JNI)](https://en." -"wikipedia.org/wiki/Java_Native_Interface). The [`jni` crate](https://docs.rs/" -"jni/) allows you to create a compatible library." +"The difference is that we will need to use the lifetime alongside another " +"type, but that other type does not matter too much." msgstr "" -#: src/android/interoperability/java.md -msgid "First, we create a Rust function to export to Java:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "Demonstrate: change `Transaction` to the following:" msgstr "" -#: src/android/interoperability/java.md -msgid "_interoperability/java/src/lib.rs_:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "Update the `DatabaseConnection::new_transaction()` method:" msgstr "" -#: src/android/interoperability/java.md -msgid "//! Rust <-> Java FFI demo.\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"This gives an owned database connection that is tied to the " +"`DatabaseConnection` that created it, but with less runtime memory footprint " +"that the store-a-reference version did." msgstr "" -#: src/android/interoperability/java.md -msgid "/// HelloWorld::hello method implementation.\n" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"Because `PhantomData` is a zero-sized type (like `()` or `struct " +"MyZeroSizedType;`), the size of `Transaction` is now the same as `u8`." msgstr "" -#: src/android/interoperability/java.md -msgid "\"system\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"The implementation that held onto a reference instead was as large as a " +"`usize`." msgstr "" -#: src/android/interoperability/java.md -msgid "\"Hello, {input}!\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"This way of encoding relationships between types and values is very powerful " +"when combined with unsafe, as the ways one can manipulate lifetimes becomes " +"almost arbitrary. This is also dangerous, but when combined with tools like " +"external, mechanically-verified proofs we can safely encode cyclic/self-" +"referential types while encoding lifetime & safety expectations in the " +"relevant data types." msgstr "" -#: src/android/interoperability/java.md -msgid "_interoperability/java/Android.bp_:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-03-lifetimes.md +msgid "" +"The [GhostCell (2021)](https://plv.mpi-sws.org/rustbelt/ghostcell/) paper " +"and its [relevant implementation](https://gitlab.mpi-sws.org/FP/ghostcell) " +"show this kind of work off. While the borrow checker is restrictive, there " +"are still ways to use escape hatches and then _show that the ways you used " +"those escape hatches are consistent and safe._" msgstr "" -#: src/android/interoperability/java.md -msgid "\"libhello_jni\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "PhantomData 4/4: OwnedFd & BorrowedFd" msgstr "" -#: src/android/interoperability/java.md -msgid "\"hello_jni\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "`BorrowedFd` is a prime example of `PhantomData` in action." msgstr "" -#: src/android/interoperability/java.md -msgid "\"libjni\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "" +"// Create a file with a raw syscall with write-only and create permissions.\n" msgstr "" -#: src/android/interoperability/java.md -msgid "We then call this function from Java:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "\"c_str.txt\"" msgstr "" -#: src/android/interoperability/java.md -msgid "_interoperability/java/HelloWorld.java_:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "" +"// Pass the ownership of an integer file descriptor to an `OwnedFd`.\n" +" // `OwnedFd::drop()` closes the file descriptor.\n" msgstr "" -#: src/android/interoperability/java.md -msgid "\"helloworld_jni\"" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "\"Could not open file with syscall!\"" msgstr "" -#: src/android/interoperability/java.md -#, fuzzy -msgid "\"HelloWorld.java\"" -msgstr "Hello World!" - -#: src/android/interoperability/java.md -#, fuzzy -msgid "\"HelloWorld\"" -msgstr "Hello World!" - -#: src/android/interoperability/java.md -msgid "Finally, you can build, sync, and run the binary:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "" +"// Create a `BorrowedFd` from an `OwnedFd`.\n" +" // `BorrowedFd::drop()` does not close the file because it doesn't own " +"it!\n" msgstr "" -#: src/exercises/android/morning.md -msgid "" -"This is a group exercise: We will look at one of the projects you work with " -"and try to integrate some Rust into it. Some suggestions:" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "// std::mem::drop(owned_fd); // ❌🔨\n" msgstr "" -#: src/exercises/android/morning.md -msgid "Call your AIDL service with a client written in Rust." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "// owned_fd will be dropped here, and the file will be closed.\n" msgstr "" -#: src/exercises/android/morning.md -msgid "Move a function from your project to Rust and call it." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "A file descriptor represents a specific process's access to a file." msgstr "" -#: src/exercises/android/morning.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md msgid "" -"No solution is provided here since this is open-ended: it relies on someone " -"in the class having a piece of code which you can turn in to Rust on the fly." +"Reminder: Device and OS-specific features are exposed as if they were files " +"on unix-style systems." msgstr "" -#: src/chromium.md -msgid "Welcome to Rust in Chromium" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "" +"[`OwnedFd`](https://rust-lang.github.io/rfcs/3128-io-safety.html#ownedfd-and-" +"borrowedfdfd) is an owned wrapper type for a file descriptor. It _owns_ the " +"file descriptor, and closes it when dropped." msgstr "" -#: src/chromium.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md msgid "" -"Rust is supported for third-party libraries in Chromium, with first-party " -"glue code to connect between Rust and existing Chromium C++ code." +"Note: We have our own implementation of it here, draw attention to the " +"explicit `Drop` implementation." msgstr "" -#: src/chromium.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md msgid "" -"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 free to follow this recipe in your part of the codebase instead of the " -"exact part we talk about." +"`BorrowedFd` is its borrowed counterpart, it does not need to close the file " +"when it is dropped." msgstr "" -#: src/chromium/setup.md -msgid "" -"Make sure you can build and run Chromium. Any platform and set of build " -"flags is OK, so long as your code is relatively recent (commit position " -"1223636 onwards, corresponding to November 2023):" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "Note: We have not explicitly implemented `Drop` for `BorrowedFd`." msgstr "" -#: src/chromium/setup.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md msgid "" -"(A component, debug build is recommended for quickest iteration time. This " -"is the default!)" +"`BorrowedFd` uses a lifetime captured with a `PhantomData` to enforce the " +"invariant \"if this file descriptor exists, the OS file descriptor is still " +"open even though it is not responsible for closing that file descriptor.\"" msgstr "" -#: src/chromium/setup.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md msgid "" -"See [How to build Chromium](https://www.chromium.org/developers/how-tos/get-" -"the-code/) if you aren't already at that point. Be warned: setting up to " -"build Chromium takes time." +"The lifetime parameter of `BorrowedFd` demands that there exists another " +"value in your program that lasts as long as that specific `BorrowedFd` or " +"outlives it (in this case an `OwnedFd`)." msgstr "" -#: src/chromium/setup.md -msgid "It's also recommended that you have Visual Studio code installed." +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "" +"Demonstrate: Uncomment the `std::mem::drop(owned_fd)` line and try to " +"compile to show that `borrowed_fd` relies on the lifetime of `owned_fd`." msgstr "" -#: src/chromium/setup.md -msgid "About the exercises" +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md +msgid "" +"This has been encoded by the API designers to mean _that other value is what " +"keeps the access to the file open_." msgstr "" -#: src/chromium/setup.md +#: src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md msgid "" -"This part of the course has a series of exercises which 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." +"Because Rust's borrow checker enforces this relationship where one value " +"must last at least as long as another, users of this API do not need to " +"worry about handling this correct file descriptor aliasing and closing logic " +"themselves." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types.md msgid "" -"The Rust community typically uses `cargo` and libraries from [crates.io]" -"(https://crates.io/). Chromium is built using `gn` and `ninja` and a curated " -"set of dependencies." +"Types with private constructors can be used to act as proof of invariants." msgstr "" -#: src/chromium/cargo.md -msgid "When writing code in Rust, your choices are:" +#: src/idiomatic/leveraging-the-type-system/token-types.md +msgid "// A public type with private fields behind a module boundary.\n" msgstr "" -#: src/chromium/cargo.md -msgid "" -"Use `gn` and `ninja` with the help of the templates from `//build/rust/*." -"gni` (e.g. `rust_static_library` that we'll meet later). This uses " -"Chromium's audited toolchain and crates." +#: src/idiomatic/leveraging-the-type-system/token-types.md +msgid "\"We have a token, so we can make assumptions.\"" msgstr "" -#: src/chromium/cargo.md -msgid "" -"Use `cargo`, but [restrict yourself to Chromium's audited toolchain and " -"crates](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/" -"docs/rust.md#Using-cargo)" +#: src/idiomatic/leveraging-the-type-system/token-types.md +msgid "// We have a token, so we can do this work.\n" msgstr "" -#: src/chromium/cargo.md -msgid "" -"Use `cargo`, trusting a [toolchain](https://rustup.rs/) and/or [crates " -"downloaded from the internet](https://crates.io/)" +#: src/idiomatic/leveraging-the-type-system/token-types.md +msgid "// We could not get a token, so we can't call `protected_work`.\n" msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types.md msgid "" -"From here on we'll be focusing on `gn` and `ninja`, because this is how Rust " -"code can be built into the Chromium browser. At the same time, Cargo is an " -"important part of the Rust ecosystem and you should keep it in your toolbox." +"Motivation: We want to be able to restrict user's access to functionality " +"until they've performed a specific task." msgstr "" -#: src/chromium/cargo.md -#, fuzzy -msgid "Mini exercise" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ" +#: src/idiomatic/leveraging-the-type-system/token-types.md +msgid "" +"We can do this by defining a type the API consumer cannot construct on their " +"own, through the privacy rules of structs and modules." +msgstr "" -#: src/chromium/cargo.md -msgid "Split into small groups and:" +#: src/idiomatic/leveraging-the-type-system/token-types.md +msgid "" +"[Newtypes](./newtype-pattern.md) use the privacy rules in a similar way, to " +"restrict construction unless a value is guaranteed to hold up an invariant " +"at runtime." +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/token-types.md +msgid "Ask: What is the purpose of the `proof: ()` field here?" msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types.md msgid "" -"Brainstorm scenarios where `cargo` may offer an advantage and assess the " -"risk profile of these scenarios." +"Without `proof: ()`, `Token` would have no private fields and users would be " +"able to construct values of `Token` arbitrarily." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types.md msgid "" -"Discuss which tools, libraries, and groups of people need to be trusted when " -"using `gn` and `ninja`, offline `cargo`, etc." +"Demonstrate: Try to construct the token manually in `main` and show the " +"compilation error. Demonstrate: Remove the `proof` field from `Token` to " +"show how users would be able to construct `Token` if it had no private " +"fields." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types.md msgid "" -"Ask students to avoid peeking at the speaker notes before completing the " -"exercise. Assuming folks taking the course are physically together, ask them " -"to discuss in small groups of 3-4 people." +"By putting the `Token` type behind a module boundary (`token`), users " +"outside that module can't construct the value on their own as they don't " +"have permission to access the `proof` field." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types.md msgid "" -"Notes/hints related to the first part of the exercise (\"scenarios where " -"Cargo may offer an advantage\"):" +"The API developer gets to define methods and functions that produce these " +"tokens. The user does not." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types.md msgid "" -"It's fantastic that when writing a tool, or prototyping a part of Chromium, " -"one has access to the rich ecosystem of crates.io libraries. There is a " -"crate for almost anything and they are usually quite pleasant to use. " -"(`clap` for command-line parsing, `serde` for serializing/deserializing to/" -"from various formats, `itertools` for working with iterators, etc.)." +"The token becomes a proof that one has met the API developer's conditions of " +"access for those tokens." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types.md msgid "" -"`cargo` makes it easy to try a library (just add a single line to `Cargo." -"toml` and start writing code)" +"Ask: How might an API developer accidentally introduce ways to circumvent " +"this?" msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types.md msgid "" -"It may be worth comparing how CPAN helped make `perl` a popular choice. Or " -"comparing with `python` + `pip`." +"Expect answers like \"serialization implementations\", other parser/\"from " +"string\" implementations, or an implementation of `Default`." msgstr "" -#: src/chromium/cargo.md -msgid "" -"Development experience is made really nice not only by core Rust tools (e.g. " -"using `rustup` to switch to a different `rustc` version when testing a crate " -"that needs to work on nightly, current stable, and older stable) but also by " -"an ecosystem of third-party tools (e.g. Mozilla provides `cargo vet` for " -"streamlining and sharing security audits; `criterion` crate gives a " -"streamlined way to run benchmarks)." +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md +msgid "Token types work well as a proof of checked permission." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md msgid "" -"`cargo` makes it easy to add a tool via `cargo install --locked cargo-vet`." +"// We don't have to check that we have permissions, because\n" +"// the AdminToken argument is equivalent to such a check.\n" msgstr "" -#: src/chromium/cargo.md -msgid "It may be worth comparing with Chrome Extensions or VScode extensions." +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md +msgid "\"CoolUser\"" msgstr "" -#: src/chromium/cargo.md -msgid "" -"Broad, generic examples of projects where `cargo` may be the right choice:" +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md +msgid "\"Incorrect password! Could not prove privileges.\"" msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md msgid "" -"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 " -"language)." +"This example shows modelling gaining administrator privileges for a chat " +"client with a password and giving a user a moderator rank once those " +"privileges are gained. The `AdminToken` type acts as \"proof of correct user " +"privileges.\"" msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md msgid "" -"Participating in the Rust ecosystem requires using standard Rust tools like " -"Cargo. Libraries that want to get external contributions, and want to be " -"used outside of Chromium (e.g. in Bazel or Android/Soong build environments) " -"should probably use Cargo." +"The user asked for a password in-code and if we get the password correct, we " +"get a `AdminToken` to perform administrator actions within a specific " +"environment (here, a chat client)." msgstr "" -#: src/chromium/cargo.md -msgid "Examples of Chromium-related projects that are `cargo`\\-based:" +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md +msgid "" +"Once the permissions are gained, we can call the `add_moderator` function." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md msgid "" -"`serde_json_lenient` (experimented with in other parts of Google which " -"resulted in PRs with performance improvements)" +"We can't call that function without the token type, so by being able to call " +"it at all all we can assume we have permissions." msgstr "" -#: src/chromium/cargo.md -msgid "Fontations libraries like `font-types`" +#: src/idiomatic/leveraging-the-type-system/token-types/permission-tokens.md +msgid "" +"Demonstrate: Try to construct the `AdminToken` in `main` again to reiterate " +"that the foundation of useful tokens is preventing their arbitrary " +"construction." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md msgid "" -"`gnrt` tool (we will meet it later in the course) which depends on `clap` " -"for command-line parsing and on `toml` for configuration files." +"Sometimes, a token type needs additional data. A mutex guard is an example " +"of a token that represents permission + data." msgstr "" -#: src/chromium/cargo.md -msgid "" -"Disclaimer: a unique reason for using `cargo` was unavailability of `gn` " -"when building and bootstrapping Rust standard library when building Rust " -"toolchain." +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md +msgid "// The acquired MutexGuard is proof of exclusive access.\n" msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md msgid "" -"`run_gnrt.py` uses Chromium's copy of `cargo` and `rustc`. `gnrt` depends on " -"third-party libraries downloaded from the internet, but `run_gnrt.py` asks " -"`cargo` that only `--locked` content is allowed via `Cargo.lock`.)" +"Mutexes enforce mutual exclusion of read/write access to a value. We've " +"covered Mutexes earlier in this course already (See: RAII/Mutex), but here " +"we're looking at `MutexGuard` specifically." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md msgid "" -"Students may identify the following items as being implicitly or explicitly " -"trusted:" +"`MutexGuard` is a value generated by a `Mutex` that proves you have read/" +"write access at that point in time." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md msgid "" -"`rustc` (the Rust compiler) which in turn depends on the LLVM libraries, the " -"Clang compiler, the `rustc` sources (fetched from GitHub, reviewed by Rust " -"compiler team), binary Rust compiler downloaded for bootstrapping" +"`MutexGuard` also holds onto a reference to the `Mutex` that generated it, " +"with `Deref` and `DerefMut` implementations that give access to the data of " +"`Mutex` while the underlying `Mutex` keeps that data private from the user." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md msgid "" -"`rustup` (it may be worth pointing out that `rustup` is developed under the " -"umbrella of the https://github.com/rust-lang/ organization - same as `rustc`)" +"If `mutex.lock()` does not return a `MutexGuard`, you don't have permission " +"to change the value within the mutex." msgstr "" -#: src/chromium/cargo.md -msgid "`cargo`, `rustfmt`, etc." +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md +msgid "" +"Not only do you have no permission, but you have no means to access the " +"mutex data unless you gain a `MutexGuard`." msgstr "" -#: src/chromium/cargo.md +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md msgid "" -"Various internal infrastructure (bots that build `rustc`, system for " -"distributing the prebuilt toolchain to Chromium engineers, etc.)" +"This contrasts with C++, where mutexes and lock guards do not control access " +"to the data itself, acting only as a flag that a user must remember to check " +"every time they read or manipulate data." msgstr "" -#: src/chromium/cargo.md -msgid "Cargo tools like `cargo audit`, `cargo vet`, etc." +#: src/idiomatic/leveraging-the-type-system/token-types/mutex-guard.md +msgid "" +"Demonstrate: make the `mutex` variable mutable then try to dereference it to " +"change its value. Show how there's no deref implementation for it, and no " +"other way to get to the data held by it other than getting a mutex guard." msgstr "" -#: src/chromium/cargo.md -msgid "" -"Rust libraries vendored into `//third_party/rust` (audited by " -"security@chromium.org)" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +msgid "Variable-Specific Tokens (Branding 1/4)" msgstr "" -#: src/chromium/cargo.md -msgid "Other Rust libraries (some niche, some quite popular and commonly used)" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +msgid "What if we want to tie a token to a specific variable?" msgstr "" -#: src/chromium/policy.md -msgid "Chromium Rust policy" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +msgid "// Works fine!\n" msgstr "" -#: src/chromium/policy.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"Chromium does not yet allow first-party Rust except in rare cases as " -"approved by Chromium's [Area Tech Leads](https://source.chromium.org/" -"chromium/chromium/src/+/main:ATL_OWNERS)." +"// let data_2 = Bytes { bytes: vec![0, 1] };\n" +" // data_2.get_proven(&token_1); // Panics! Can we prevent this?\n" msgstr "" -#: src/chromium/policy.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"Chromium's policy on third party libraries is outlined [here](https://" -"chromium.googlesource.com/chromium/src/+/main/docs/adding_to_third_party." -"md#rust) - Rust is allowed for third party libraries under various " -"circumstances, including if they're the best option for performance or for " -"security." +"What if we want to tie a token to a _specific variable_ in our code? Can we " +"do this in Rust's type system?" msgstr "" -#: src/chromium/policy.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"Very few Rust libraries directly expose a C/C++ API, so that means that " -"nearly all such libraries will require a small amount of first-party glue " -"code." +"Motivation: We want to have a Token Type that represents a known, valid " +"index into a byte array." msgstr "" -#: src/chromium/policy.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"```bob\n" -"\"C++\" Rust\n" -".- - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - " -"-.\n" -": : : :\n" -": Existing Chromium : : Chromium Rust Existing " -"Rust :\n" -": \"C++\" : : \"wrapper\" " -"crate :\n" -": +---------------+ : : +----------------+ +-------------" -"+ :\n" -": | | : : | | | " -"| :\n" -": | o-----+-+-----------+-+-> o-+----------+--> " -"| :\n" -": | | : Language : | | Crate | " -"| :\n" -": +---------------+ : boundary : +----------------+ API +-------------" -"+ :\n" -": : : :\n" -"`- - - - - - - - - -' `- - - - - - - - - - - - - - - - - - - - - - " -"-'\n" -"```" +"Once we have these proven indexes we would be able to avoid bounds checks " +"entirely, as the tokens would act as the _proof of an existing index_." msgstr "" -#: src/chromium/policy.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"First-party Rust glue code for a particular third-party crate should " -"normally be kept in `third_party/rust///wrapper`." +"Since the index is known to be valid, `get_proven()` can skip the bounds " +"check." msgstr "" -#: src/chromium/policy.md -msgid "Because of this, today's course will be heavily focused on:" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +msgid "" +"In this example there's nothing stopping the proven index of one array being " +"used on a different array. If an index is out of bounds in this case, it is " +"undefined behavior." msgstr "" -#: src/chromium/policy.md -msgid "Bringing in third-party Rust libraries (\"crates\")" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +msgid "Demonstrate: Uncomment the `data_2.get_proven(&token_1);` line." msgstr "" -#: src/chromium/policy.md -msgid "Writing glue code to be able to use those crates from Chromium C++." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +msgid "" +"The code here panics! We want to prevent this \"crossover\" of token types " +"for indexes at compile time." msgstr "" -#: src/chromium/policy.md -msgid "If this policy changes over time, the course will evolve to keep up." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +msgid "Ask: How might we try to do this?" msgstr "" -#: src/chromium/build-rules.md -#, fuzzy -msgid "Build rules" -msgstr "āĻ—āĻ āύ⧇āϰ āύāĻŋāϝāĻŧāĻŽ" - -#: src/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"Rust code is usually built using `cargo`. Chromium builds with `gn` and " -"`ninja` for efficiency --- its static rules allow maximum parallelism. Rust " -"is no exception." +"Expect students to not reach a good implementation from this, but be willing " +"to experiment and follow through on suggestions." msgstr "" -#: src/chromium/build-rules.md -msgid "Adding Rust code to Chromium" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md +msgid "Ask: What are the alternatives, why are they not good enough?" msgstr "" -#: src/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"In some existing Chromium `BUILD.gn` file, declare a `rust_static_library`:" +"Expect runtime checking of index bounds, especially as both `Vec::get` and " +"`Bytes::get_index` already uses runtime checking." msgstr "" -#: src/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"```gn\n" -"import(\"//build/rust/rust_static_library.gni\")\n" -"\n" -"rust_static_library(\"my_rust_lib\") {\n" -" crate_root = \"lib.rs\"\n" -" sources = [ \"lib.rs\" ]\n" -"}\n" -"```" +"Runtime bounds checking does not prevent the erroneous crossover in the " +"first place, it only guarantees a panic." msgstr "" -#: src/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"You can also add `deps` on other Rust targets. Later we'll use this to " -"depend upon third party code." +"The kind of token-association we will be doing here is called Branding. This " +"is an advanced technique that expands applicability of token types to more " +"API designs." msgstr "" -#: src/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-01-motivation.md msgid "" -"You must specify _both_ the crate root, _and_ a full list of sources. The " -"`crate_root` is the file given to the Rust compiler representing the root " -"file of the compilation unit --- typically `lib.rs`. `sources` is a complete " -"list of all source files which `ninja` needs in order to determine when " -"rebuilds are necessary." +"[`GhostCell`](https://plv.mpi-sws.org/rustbelt/ghostcell/paper.pdf) is a " +"prominent user of this, later slides will touch on it." msgstr "" -#: src/chromium/build-rules.md -msgid "" -"(There's no such thing as a Rust `source_set`, because in Rust, an entire " -"crate is a compilation unit. A `static_library` is the smallest unit.)" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "`PhantomData` and Lifetime Subtyping (Branding 2/4)" msgstr "" -#: src/chromium/build-rules.md -msgid "" -"Students might be wondering why we need a gn template, rather than using " -"[gn's built-in support for Rust static libraries](https://gn.googlesource." -"com/gn/+/main/docs/reference.md#func_static_library). The answer is that " -"this template provides support for CXX interop, Rust features, and unit " -"tests, some of which we'll use later." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "Idea:" msgstr "" -#: src/chromium/build-rules/unsafe.md -msgid "Including `unsafe` Rust Code" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "Use a lifetime as a unique brand for each token." msgstr "" -#: src/chromium/build-rules/unsafe.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Unsafe Rust code is forbidden in `rust_static_library` by default --- it " -"won't compile. If you need unsafe Rust code, add `allow_unsafe = true` to " -"the gn target. (Later in the course we'll see circumstances where this is " -"necessary.)" +"Make lifetimes sufficiently distinct so that they don't implicitly convert " +"into each other." msgstr "" -#: src/chromium/build-rules/unsafe.md -msgid "" -"```gn\n" -"import(\"//build/rust/rust_static_library.gni\")\n" -"\n" -"rust_static_library(\"my_rust_lib\") {\n" -" crate_root = \"lib.rs\"\n" -" sources = [\n" -" \"lib.rs\",\n" -" \"hippopotamus.rs\"\n" -" ]\n" -" allow_unsafe = true\n" -"}\n" -"```" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "// The main focus\n" msgstr "" -#: src/chromium/build-rules/depending.md -msgid "Simply add the above target to the `deps` of some Chromium C++ target." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "// We want this to NOT compile\n" msgstr "" -#: src/chromium/build-rules/depending.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "In Rust, lifetimes can have subtyping relations between one another." +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"```gn\n" -"import(\"//build/rust/rust_static_library.gni\")\n" -"\n" -"rust_static_library(\"my_rust_lib\") {\n" -" crate_root = \"lib.rs\"\n" -" sources = [ \"lib.rs\" ]\n" -"}\n" -"\n" -"# or source_set, static_library etc.\n" -"component(\"preexisting_cpp\") {\n" -" deps = [ \":my_rust_lib\" ]\n" -"}\n" -"```" +"This kind of relation allows the compiler to determine if one lifetime " +"outlives another." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Types are elided in Rust code, which makes a good IDE even more useful than " -"for C++. Visual Studio code works well for Rust in Chromium. To use it," +"Determining if a lifetime outlives another also allows us to say _the " +"shortest common lifetime is the one that ends first_." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Ensure your VSCode has the `rust-analyzer` extension, not earlier forms of " -"Rust support" +"This is useful in many cases, as it means two different lifetimes can be " +"treated as if they were the same in the regions they do overlap." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"`gn gen out/Debug --export-rust-project` (or equivalent for your output " -"directory)" +"This is usually what we want. But here we want to use lifetimes as a way to " +"distinguish values so we say that a token only applies to a single variable " +"without having to create a newtype for every single variable we declare." msgstr "" -#: src/chromium/build-rules/vscode.md -msgid "`ln -s out/Debug/rust-project.json rust-project.json`" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "" +"**Goal**: We want two lifetimes that the Rust compiler cannot determine if " +"one outlives the other." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"A demo of some of the code annotation and exploration features of rust-" -"analyzer might be beneficial if the audience are naturally skeptical of IDEs." +"We are using `try_coerce_lifetimes` as a compile-time check to see if the " +"lifetimes have a common shorter lifetime (AKA being subtyped)." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"The following steps may help with the demo (but feel free to instead use a " -"piece of Chromium-related Rust that you are most familiar with):" +"Note: This slide compiles, by the end of this slide it should only compile " +"when `subtyped_lifetimes` is commented out." msgstr "" -#: src/chromium/build-rules/vscode.md -msgid "Open `components/qr_code_generator/qr_code_generator_ffi_glue.rs`" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "There are two important parts of this code:" msgstr "" -#: src/chromium/build-rules/vscode.md -msgid "" -"Place the cursor over the `QrCode::new` call (around line 26) in " -"\\`qr_code_generator_ffi_glue.rs" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "The `impl for<'a>` bound on the closure passed to `lifetime_separator`." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "The way lifetimes are used in the parameter for `PhantomData`." +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "`for<'a>` bound on a Closure" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Demo **show documentation** (typical bindings: vscode = ctrl k i; vim/CoC = " -"K)." +"We are using `for<'a>` as a way of introducing a lifetime generic parameter " +"to a function type and asking that the body of the function to work for all " +"possible lifetimes." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Demo **go to definition** (typical bindings: vscode = F12; vim/CoC = g d). " -"(This will take you to `//third_party/rust/.../qr_code-.../src/lib.rs`.)" +"What this also does is remove some ability of the compiler to make " +"assumptions about that specific lifetime for the function argument, as it " +"must meet Rust's borrow checking rules regardless of the \"real\" lifetime " +"its arguments are going to have. The caller is substituting in actual " +"lifetime, the function itself cannot." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Demo **outline** and navigate to the `QrCode::with_bits` method (around line " -"164; the outline is in the file explorer pane in vscode; typical vim/CoC " -"bindings = space o)" +"This is analogous to a forall (âą¯) quantifier in mathematics, or the way we " +"introduce `` as type variables, but only for lifetimes in trait bounds." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Demo **type annotations** (there are quote a few nice examples in the " -"`QrCode::with_bits` method)" +"When we write a function generic over a type `T`, we can't determine that " +"type from within the function itself. Even if we call a function `fn foo(first: T, second: U)` with two arguments of the same type, the body of " +"this function cannot determine if `T` and `U` are the same type." msgstr "" -#: src/chromium/build-rules/vscode.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"It may be worth pointing out that `gn gen ... --export-rust-project` will " -"need to be rerun after editing `BUILD.gn` files (which we will do a few " -"times throughout the exercises in this session)." +"This also prevents _the API consumer_ from defining a lifetime themselves, " +"which would allow them to circumvent the restrictions we want to impose." msgstr "" -#: src/exercises/chromium/build-rules.md -#, fuzzy -msgid "Build rules exercise" -msgstr "āĻ—āĻ āύ⧇āϰ āύāĻŋāϝāĻŧāĻŽ" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "PhantomData and Lifetime Variance" +msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"In your Chromium build, add a new Rust target to `//ui/base/BUILD.gn` " -"containing:" +"We already know `PhantomData`, which can introduce a formal no-op usage of " +"an otherwise unused type or a lifetime parameter." msgstr "" -#: src/exercises/chromium/build-rules.md -msgid "" -"**Important**: note that `no_mangle` here is considered a type of unsafety " -"by the Rust compiler, so you'll need to to allow unsafe code in your `gn` " -"target." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "Ask: What can we do with `PhantomData`?" msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Add this new Rust target as a dependency of `//ui/base:base`. Declare this " -"function at the top of `ui/base/resource/resource_bundle.cc` (later, we'll " -"see how this can be automated by bindings generation tools):" +"Expect mentions of the Typestate pattern, tying together the lifetimes of " +"owned values." msgstr "" -#: src/exercises/chromium/build-rules.md -msgid "" -"Call this function from somewhere in `ui/base/resource/resource_bundle.cc` - " -"we suggest the top of `ResourceBundle::MaybeMangleLocalizedString`. Build " -"and run Chromium, and ensure that \"Hello from Rust!\" is printed lots of " -"times." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "Ask: In other languages, what is subtyping?" msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"If you use VSCode, now set up Rust to work well in VSCode. It will be useful " -"in subsequent exercises. If you've succeeded, you will be able to use right-" -"click \"Go to definition\" on `println!`." +"Expect mentions of inheritance, being able to use a value of type `B` when a " +"asked for a value of type `A` because `B` is a \"subtype\" of `A`." msgstr "" -#: src/exercises/chromium/build-rules.md -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Where to find help" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md +msgid "Rust does have Subtyping! But only for lifetimes." msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"The options available to the [`rust_static_library` gn template](https://" -"source.chromium.org/chromium/chromium/src/+/main:build/rust/" -"rust_static_library.gni;l=16)" +"Ask: If one lifetime is a subtype of another lifetime, what might that mean?" msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Information about [`#[no_mangle]`](https://doc.rust-lang.org/beta/reference/" -"abi.html#the-no_mangle-attribute)" +"A lifetime is a \"subtype\" of another lifetime when it _outlives_ that " +"other lifetime." msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Information about [`extern \"C\"`](https://doc.rust-lang.org/std/keyword." -"extern.html)" +"The way that lifetimes used by `PhantomData` behave depends not only on " +"where the lifetime \"comes from\" but on how the reference is defined too." msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Information about gn's [`--export-rust-project`](https://gn.googlesource.com/" -"gn/+/main/docs/reference.md#compilation-database) switch" +"The reason this compiles is that the [**Variance**](https://doc.rust-lang." +"org/stable/reference/subtyping.html#r-subtyping.variance) of the lifetime " +"inside of `InvariantLifetime` is too lenient." msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"[How to install rust-analyzer in VSCode](https://code.visualstudio.com/docs/" -"languages/rust)" +"Note: Do not expect to get students to understand variance entirely here, " +"just treat it as a kind of ladder of restrictiveness on the ability of " +"lifetimes to establish subtyping relations." msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"This example is unusual because it boils down to the lowest-common-" -"denominator interop language, C. Both C++ and Rust can natively declare and " -"call C ABI functions. Later in the course, we'll connect C++ directly to " -"Rust." +"Ask: How can we make it more restrictive? How do we make a reference type " +"more restrictive in Rust?" msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"`allow_unsafe = true` is required here because `#[no_mangle]` might allow " -"Rust to generate two functions with the same name, and Rust can no longer " -"guarantee that the right one is called." +"Expect or demonstrate: Making it `&'id mut ()` instead. This will not be " +"enough!" msgstr "" -#: src/exercises/chromium/build-rules.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"If you need a pure Rust executable, you can also do that using the " -"`rust_executable` gn template." +"We need to use a [**Variance**](https://doc.rust-lang.org/stable/reference/" +"subtyping.html#r-subtyping.variance) on lifetimes where subtyping cannot be " +"inferred except on _identical lifetimes_. That is, the only subtype of `'a` " +"the compiler can know is `'a` itself." msgstr "" -#: src/chromium/testing.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Rust community typically authors unit tests in a module placed in the same " -"source file as the code being tested. This was covered [earlier](../testing." -"md) in the course and looks like this:" +"Note: Again, do not try to get the whole class to understand variance. Treat " +"it as a ladder of restrictiveness for now." msgstr "" -#: src/chromium/testing.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"In Chromium we place unit tests in a separate source file and we continue to " -"follow this practice for Rust --- this makes tests consistently discoverable " -"and helps to avoid rebuilding `.rs` files a second time (in the `test` " -"configuration)." +"Demonstrate: Move from `&'id ()` (covariant in lifetime and type), `&'id mut " +"()` (covariant in lifetime, invariant in type), `*mut &'id mut ()` " +"(invariant in lifetime and type), and finally `*mut &'id ()` (invariant in " +"lifetime but not type)." msgstr "" -#: src/chromium/testing.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"This results in the following options for testing Rust code in Chromium:" +"Those last two should not compile, which means we've finally found " +"candidates for how to bind lifetimes to `PhantomData` so they can't be " +"compared to one another in this context." msgstr "" -#: src/chromium/testing.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Native Rust tests (i.e. `#[test]`). Discouraged outside of `//third_party/" -"rust`." +"Reason: `*mut` means [mutable raw pointer](https://doc.rust-lang.org/" +"reference/types/pointer.html#r-type.pointer.raw). Rust has mutable pointers! " +"But you cannot reason about them in safe Rust. Making this a mutable raw " +"pointer to a reference that has a lifetime complicates the compiler's " +"ability subtype because it cannot reason about mutable raw pointers within " +"the borrow checker." msgstr "" -#: src/chromium/testing.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"`gtest` tests authored in C++ and exercising Rust via FFI calls. Sufficient " -"when Rust code is just a thin FFI layer and the existing unit tests provide " -"sufficient coverage for the feature." +"Wrap up: We've introduced ways to stop the compiler from deciding that " +"lifetimes are \"similar enough\" by choosing a Variance for a lifetime in " +"`PhantomData` that is restrictive enough to prevent this slide from " +"compiling." msgstr "" -#: src/chromium/testing.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"`gtest` tests authored in Rust and using the crate under test through its " -"public API (using `pub mod for_testing { ... }` if needed). This is the " -"subject of the next few slides." +"That is, we can now create variables that can exist in the same scope as " +"each other, but whose types are automatically made different from one " +"another per-variable without much boilerplate." msgstr "" -#: src/chromium/testing.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md msgid "" -"Mention that native Rust tests of third-party crates should eventually be " -"exercised by Chromium bots. (Such testing is needed rarely --- only after " -"adding or updating third-party crates.)" +"The `for<'a>` quantifier is not just for function types. It is a [**Higher-" +"ranked trait bound**](https://doc.rust-lang.org/reference/subtyping.html?" +"search=Hiher#r-subtype.higher-ranked)." msgstr "" -#: src/chromium/testing.md -msgid "" -"Some examples may help illustrate when C++ `gtest` vs Rust `gtest` should be " -"used:" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "Implementing Branded Types (Branding 3/4)" msgstr "" -#: src/chromium/testing.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md msgid "" -"QR has very little functionality in the first-party Rust layer (it's just a " -"thin FFI glue) and therefore uses the existing C++ unit tests for testing " -"both the C++ and the Rust implementation (parameterizing the tests so they " -"enable or disable Rust using a `ScopedFeatureList`)." +"Constructing branded types is different to how we construct non-branded " +"types." msgstr "" -#: src/chromium/testing.md -msgid "" -"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." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "// The data we want to modify in this context.\n" msgstr "" -#: src/chromium/testing/rust-gtest-interop.md -msgid "" -"The [`rust_gtest_interop`](https://chromium.googlesource.com/chromium/src/+/" -"main/testing/rust_gtest_interop/README.md) library provides a way to:" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "// The function that uniquely brands the lifetime of a `Bytes`\n" msgstr "" -#: src/chromium/testing/rust-gtest-interop.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md msgid "" -"Use a Rust function as a `gtest` testcase (using the `#[gtest(...)]` " -"attribute)" +"Motivation: We want to have \"proven indexes\" for a type, and we don't want " +"those indexes to be usable by different variables of the same type. We also " +"don't want those indexes to escape a scope." msgstr "" -#: src/chromium/testing/rust-gtest-interop.md -msgid "" -"Use `expect_eq!` and similar macros (similar to `assert_eq!` but not " -"panicking and not terminating the test when the assertion fails)." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "Our Branded Type will be `Bytes`: a byte array." msgstr "" -#: src/chromium/testing/rust-gtest-interop.md -#, fuzzy -msgid "Example:" -msgstr "āωāĻĻāĻžāĻšāϰāĻŖ" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "Our Branded Token will be `ProvenIndex`: an index known to be in range." +msgstr "" -#: src/chromium/testing/build-gn.md -msgid "" -"The simplest way to build Rust `gtest` tests is to add them to an existing " -"test binary that already contains tests authored in C++. For example:" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "There are several notable parts to this implementation:" msgstr "" -#: src/chromium/testing/build-gn.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md msgid "" -"```gn\n" -"test(\"ui_base_unittests\") {\n" -" ...\n" -" sources += [ \"my_rust_lib_unittest.rs\" ]\n" -" deps += [ \":my_rust_lib\" ]\n" -"}\n" -"```" +"`new` does not return a `Bytes`, instead asking for \"starting data\" and a " +"use-once Closure that is passed a `Bytes` when it is called." msgstr "" -#: src/chromium/testing/build-gn.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "That `new` function has a `for<'a>` on its trait bound." +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md msgid "" -"Authoring Rust tests in a separate `static_library` also works, but requires " -"manually declaring the dependency on the support libraries:" +"We have both a getter for an index and a getter for a values with a proven " +"index." msgstr "" -#: src/chromium/testing/build-gn.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "Ask: Why does `new` not return a `Bytes`?" +msgstr "" + +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md msgid "" -"```gn\n" -"rust_static_library(\"my_rust_lib_unittests\") {\n" -" testonly = true\n" -" is_gtest_unittests = true\n" -" crate_root = \"my_rust_lib_unittest.rs\"\n" -" sources = [ \"my_rust_lib_unittest.rs\" ]\n" -" deps = [\n" -" \":my_rust_lib\",\n" -" \"//testing/rust_gtest_interop\",\n" -" ]\n" -"}\n" -"\n" -"test(\"ui_base_unittests\") {\n" -" ...\n" -" deps += [ \":my_rust_lib_unittests\" ]\n" -"}\n" -"```" +"Answer: Because we need `Bytes` to have a unique lifetime controlled by the " +"API." msgstr "" -#: src/chromium/testing/chromium-import-macro.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md msgid "" -"After adding `:my_rust_lib` to GN `deps`, we still need to learn how to " -"import and use `my_rust_lib` from `my_rust_lib_unittest.rs`. We haven't " -"provided an explicit `crate_name` for `my_rust_lib` so its crate name is " -"computed based on the full target path and name. Fortunately we can avoid " -"working with such an unwieldy name by using the `chromium::import!` macro " -"from the automatically-imported `chromium` crate:" +"Ask: So what if `new()` returned `Bytes`, what is the specific harm that it " +"would cause?" msgstr "" -#: src/chromium/testing/chromium-import-macro.md -msgid "\"//ui/base:my_rust_lib\"" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "Answer: Think about the signature of that hypothetical `new()` method:" msgstr "" -#: src/chromium/testing/chromium-import-macro.md -msgid "Under the covers the macro expands to something similar to:" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "`fn new<'a>() -> Bytes<'a> { ... }`" msgstr "" -#: src/chromium/testing/chromium-import-macro.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md msgid "" -"More information can be found in [the doc comment](https://source.chromium." -"org/chromium/chromium/src/+/main:build/rust/chromium_prelude/" -"chromium_prelude.rs?q=f:chromium_prelude.rs%20pub.use.*%5Cbimport%5Cb;%20-f:" -"third_party&ss=chromium%2Fchromium%2Fsrc) of the `chromium::import` macro." +"This would allow the API user to choose what the lifetime `'a` is, removing " +"our ability to guarantee that the lifetimes between different instances of " +"`Bytes` are unique and unable to be subtyped to one another." msgstr "" -#: src/chromium/testing/chromium-import-macro.md -msgid "" -"`rust_static_library` supports specifying an explicit name via `crate_name` " -"property, but doing this is discouraged. And it is discouraged because the " -"crate name has to be globally unique. crates.io guarantees uniqueness of its " -"crate names so `cargo_crate` GN targets (generated by the `gnrt` tool " -"covered in a later section) use short crate names." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "Ask: Why do we need both a `get_index` and a `get_proven`?" msgstr "" -#: src/exercises/chromium/testing.md -#, fuzzy -msgid "Testing exercise" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧇ āϰāĻžāĻ¸ā§āϟ" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "" +"Expect \"Because we can't know if an index is occupied at compile time\"" +msgstr "" -#: src/exercises/chromium/testing.md -msgid "Time for another exercise!" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "Ask: Then what's the point of the proven indexes?" msgstr "" -#: src/exercises/chromium/testing.md -msgid "In your Chromium build:" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md +msgid "" +"Answer: Avoiding bounds checking while keeping knowledge of what indexes are " +"occupied specific to individual variables, unable to erroneously be used on " +"the wrong one." msgstr "" -#: src/exercises/chromium/testing.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md msgid "" -"Add a testable function next to `hello_from_rust`. Some suggestions: adding " -"two integers received as arguments, computing the nth Fibonacci number, " -"summing integers in a slice, etc." +"Note: The focus is not on only on avoiding overuse of bounds checks, but " +"also on preventing that \"cross over\" of indexes." msgstr "" -#: src/exercises/chromium/testing.md -msgid "Add a separate `..._unittest.rs` file with a test for the new function." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "Branded Types in Action (Branding 4/4)" msgstr "" -#: src/exercises/chromium/testing.md -msgid "Add the new tests to `BUILD.gn`." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "" +"// bytes_2.get_proven(&index_1); // ❌🔨\n" +" \"Computations done!\"" msgstr "" -#: src/exercises/chromium/testing.md -msgid "Build the tests, run them, and verify that the new test works." +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "\"{result}\"" msgstr "" -#: src/chromium/interoperability-with-cpp.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md msgid "" -"The Rust community offers multiple options for C++/Rust interop, with new " -"tools being developed all the time. At the moment, Chromium uses a tool " -"called CXX." +"We now have the implementation ready, we can now write a program where token " +"types that are proofs of existing indexes cannot be shared between variables." msgstr "" -#: src/chromium/interoperability-with-cpp.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md msgid "" -"You describe your whole language boundary in an interface definition " -"language (which looks a lot like Rust) and then CXX tools generate " -"declarations for functions and types in both Rust and C++." +"Demonstration: Uncomment the `bytes_2.get_proven(&index_1);` line and show " +"that it does not compile when we use indexes from different variables." msgstr "" -#: src/chromium/interoperability-with-cpp.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md msgid "" -"See the [CXX tutorial](https://cxx.rs/tutorial.html) for a full example of " -"using this." +"Ask: What operations can we perform that we can guarantee would produce a " +"proven index?" msgstr "" -#: src/chromium/interoperability-with-cpp.md -msgid "" -"Talk through the diagram. Explain that behind the scenes, this is doing just " -"the same as you previously did. Point out that automating the process has " -"the following benefits:" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "Expect a \"push\" implementation, suggested demo:" msgstr "" -#: src/chromium/interoperability-with-cpp.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md msgid "" -"The tool guarantees that the C++ and Rust sides match (e.g. you get compile " -"errors if the `#[cxx::bridge]` doesn't match the actual C++ or Rust " -"definitions, but with out-of-sync manual bindings you'd get Undefined " -"Behavior)" +"Ask: Can we make this not just about a byte array, but as a general wrapper " +"on `Vec`?" msgstr "" -#: src/chromium/interoperability-with-cpp.md -msgid "" -"The tool automates generation of FFI thunks (small, C-ABI-compatible, free " -"functions) for non-C features (e.g. enabling FFI calls into Rust or C++ " -"methods; manual bindings would require authoring such top-level, free " -"functions manually)" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "Trivial: Yes!" msgstr "" -#: src/chromium/interoperability-with-cpp.md -msgid "The tool and the library can handle a set of core types - for example:" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "Maybe demonstrate: Generalising `Bytes<'id>` into `BrandedVec<'id, T>`" msgstr "" -#: src/chromium/interoperability-with-cpp.md -msgid "" -"`&[T]` can be passed across the FFI boundary, even though it doesn't " -"guarantee any particular ABI or memory layout. With manual bindings `std::" -"span` / `&[T]` have to be manually destructured and rebuilt out of a " -"pointer and length - this is error-prone given that each language represents " -"empty slices slightly differently)" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "Ask: What other areas could we use something like this?" msgstr "" -#: src/chromium/interoperability-with-cpp.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md msgid "" -"Smart pointers like `std::unique_ptr`, `std::shared_ptr`, and/or `Box` " -"are natively supported. With manual bindings, one would have to pass C-ABI-" -"compatible raw pointers, which would increase lifetime and memory-safety " -"risks." +"The resulting token API is **highly restrictive**, but the things that it " +"makes possible to prove as safe within the Rust type system are meaningful." msgstr "" -#: src/chromium/interoperability-with-cpp.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md msgid "" -"`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 NUL-" -"terminate a string)." +"[GhostCell](https://plv.mpi-sws.org/rustbelt/ghostcell/paper.pdf), a " +"structure that allows for safe cyclic data structures in Rust (among other " +"previously difficult to represent data structures), uses this kind of token " +"type to make sure cells can't \"escape\" a context where we know where " +"operations similar to those shown in these examples are safe." msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md msgid "" -"CXX requires that the whole C++/Rust boundary is declared in `cxx::bridge` " -"modules inside `.rs` source code." +"This \"Branded Types\" sequence of slides is based off their `BrandedVec` " +"implementation in the paper, which covers many of the implementation details " +"of this use case in more depth as a gentle introduction to how `GhostCell` " +"itself is implemented and used in practice." msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md -msgid "\"example/include/blobstore.h\"" +#: src/idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md +msgid "" +"GhostCell also uses formal checks outside of Rust's type system to prove " +"that the things it allows within this kind of context (lifetime branding) " +"are safe." msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md -msgid "// Definitions of Rust types and functions go here" +#: src/idiomatic/polymorphism.md +msgid "" +"Rust has plenty of mechanisms for writing and using polymorphic code, but " +"they're somewhat different from other popular languages!" msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md -msgid "Point out:" +#: src/idiomatic/polymorphism.md +msgid "" +"This chapter will cover the details of Rust's polymorphism and how it's " +"similar, or different to, other languages." msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md -msgid "" -"Although this looks like a regular Rust `mod`, the `#[cxx::bridge]` " -"procedural macro does complex things to it. The generated code is quite a " -"bit more sophisticated - though this does still result in a `mod` called " -"`ffi` in your code." +#: src/idiomatic/polymorphism/refresher.md +msgid "Basic features of Rust's generics and polymorphism." msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md -msgid "Native support for C++'s `std::unique_ptr` in Rust" +#: src/idiomatic/polymorphism/refresher.md +msgid "" +"In this section we'll be going through the core concepts of Rust's approach " +"to polymorphism, the things you'll run into the most in day-to-day usage." msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md -msgid "Native support for Rust slices in C++" +#: src/idiomatic/polymorphism/refresher/traits.md +msgid "Traits, Protocols, Interfaces" msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md -msgid "Calls from C++ to Rust, and Rust types (in the top part)" +#: src/idiomatic/polymorphism/refresher/traits.md +msgid "\"Email to {}: {}\"" msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md -msgid "Calls from Rust to C++, and C++ types (in the bottom part)" +#: src/idiomatic/polymorphism/refresher/traits.md +msgid "\"Chat message sent to {:?}: {}\"" msgstr "" -#: src/chromium/interoperability-with-cpp/example-bindings.md +#: src/idiomatic/polymorphism/refresher/traits.md msgid "" -"**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." +"Rust's concept of polymorphism and generics is heavily built around traits." msgstr "" -#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md -msgid "" -"By far the most useful page when using CXX is the [type reference](https://" -"cxx.rs/bindings.html)." +#: src/idiomatic/polymorphism/refresher/traits.md +msgid "Traits are requirements on a type in a generic context." msgstr "" -#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md -msgid "CXX fundamentally suits cases where:" +#: src/idiomatic/polymorphism/refresher/traits.md +msgid "Requirements function much like a compile-time checked duck typing." msgstr "" -#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +#: src/idiomatic/polymorphism/refresher/traits.md msgid "" -"Your Rust-C++ interface is sufficiently simple that you can declare all of " -"it." +"Duck typing is a concept from the practice of dynamic, untyped languages " +"like Python, \"if it walks like a duck and quacks like a duck, it's a duck.\"" msgstr "" -#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +#: src/idiomatic/polymorphism/refresher/traits.md msgid "" -"You're using only the types natively supported by CXX already, for example " -"`std::unique_ptr`, `std::string`, `&[u8]` etc." +"That is, types with the methods and fields expected by a function are all " +"valid inputs for that function. If a type implements methods, it is that " +"type in a duck-typing context." msgstr "" -#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +#: src/idiomatic/polymorphism/refresher/traits.md msgid "" -"It has many limitations --- for example lack of support for Rust's `Option` " -"type." +"Traits behave like a static duck typing mechanism, in that we specify " +"behavior rather than type. But we get the compile-time checks on if that " +"behavior does really exist." msgstr "" -#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +#: src/idiomatic/polymorphism/refresher/traits.md msgid "" -"These limitations constrain us to using Rust in Chromium only for well " -"isolated \"leaf nodes\" rather than for arbitrary Rust-C++ interop. When " -"considering a use-case for Rust in Chromium, a good starting point is to " -"draft the CXX bindings for the language boundary to see if it appears simple " -"enough." +"Alternatively: Traits are like collections of propositions, and implementing " +"a trait for a type is a proof that the type can be used wherever the trait " +"is asked for." msgstr "" -#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md +#: src/idiomatic/polymorphism/refresher/traits.md msgid "" -"You should also discuss some of the other sticky points with CXX, for " -"example:" +"Traits have required methods, implementing those methods is the proof that a " +"type has the required behavior." msgstr "" -#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md -msgid "" -"Its error handling is based around C++ exceptions (given on the next slide)" +#: src/idiomatic/polymorphism/refresher/traits.md +msgid "reference:" msgstr "" -#: src/chromium/interoperability-with-cpp/limitations-of-cxx.md -msgid "Function pointers are awkward to use." +#: src/idiomatic/polymorphism/refresher/traits.md +msgid "https://doc.rust-lang.org/reference/items/traits.html" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling.md -msgid "" -"CXX's [support for `Result`](https://cxx.rs/binding/result.html) relies " -"on C++ exceptions, so we can't use that in Chromium. Alternatives:" +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +msgid "Trait Bounds on Generics" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling.md -msgid "The `T` part of `Result` can be:" +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +msgid "\"Item: {}\"" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling.md -msgid "" -"Returned via out parameters (e.g. via `&mut T`). This requires that `T` can " -"be passed across the FFI boundary - for example `T` has to be:" +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "\"Hello, Rust!\"" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling.md -msgid "A primitive type (like `u32` or `usize`)" +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +msgid "// Works with integers\n" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling.md -msgid "" -"A type natively supported by `cxx` (like `UniquePtr`) that has a suitable " -"default value to use in a failure case (_unlike_ `Box`)." +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +msgid "// Works with strings\n" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling.md +#: src/idiomatic/polymorphism/refresher/trait-bounds.md msgid "" -"Retained on the Rust side, and exposed via reference. This may be needed " -"when `T` is a Rust type, which cannot be passed across the FFI boundary, and " -"cannot be stored in `UniquePtr`." +"Traits are most commonly used as bounds on generic type parameters for a " +"function or method." msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling.md -msgid "The `E` part of `Result` can be:" +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +msgid "" +"Without a trait bound on a generic type parameter, we don't have access to " +"any behavior to write functions and methods with." msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling.md +#: src/idiomatic/polymorphism/refresher/trait-bounds.md msgid "" -"Returned as a boolean (e.g. `true` representing success, and `false` " -"representing failure)" +"Trait bounds allow us to specify the minimum viable behavior of a type for " +"it to work in generic code." msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling.md -msgid "" -"Preserving error details is in theory possible, but so far hasn't been " -"needed in practice." +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +#: src/idiomatic/polymorphism/refresher/default-impls.md +#: src/idiomatic/polymorphism/refresher/supertraits.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +#: src/idiomatic/polymorphism/refresher/sized.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +msgid "ref:" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-qr.md -#, fuzzy -msgid "CXX Error Handling: QR Example" -msgstr "āĻ¤ā§āϰ⧁āϟāĻŋ āϏāĻžāĻŽāϞāĻžāύ⧋" +#: src/idiomatic/polymorphism/refresher/trait-bounds.md +msgid "https://doc.rust-lang.org/reference/trait-bounds.html" +msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-qr.md +#: src/idiomatic/polymorphism/refresher/deriving-traits.md msgid "" -"The QR code generator is [an example](https://source.chromium.org/chromium/" -"chromium/src/+/main:components/qr_code_generator/qr_code_generator_ffi_glue." -"rs;l=13-18;drc=7bf1b75b910ca430501b9c6a74c1d18a0223ecca) where a boolean is " -"used to communicate success vs failure, and where the successful result can " -"be passed across the FFI boundary:" +"Many traits, protocols, interfaces, have trivial implementations that would " +"be easy to mechanically write." msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-qr.md -msgid "\"qr_code_generator\"" +#: src/idiomatic/polymorphism/refresher/deriving-traits.md +msgid "" +"Definitions of types (their syntax trees) can be fed to procedural macros " +"(compiler plugins) to automatically generate implementations of traits." msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-qr.md +#: src/idiomatic/polymorphism/refresher/deriving-traits.md msgid "" -"Students may be curious about the semantics of the `out_qr_size` output. " -"This is not the size of the vector, but the size of the QR code (and " -"admittedly it is a bit redundant - this is the square root of the size of " -"the vector)." +"These macros have to be authored by someone, the compiler cannot figure out " +"everything by itself." msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-qr.md +#: src/idiomatic/polymorphism/refresher/deriving-traits.md msgid "" -"It may be worth pointing out the importance of initializing `out_qr_size` " -"before calling into the Rust function. Creation of a Rust reference that " -"points to uninitialized memory results in Undefined Behavior (unlike in C++, " -"when only the act of dereferencing such memory results in UB)." +"Many traits have a naive, obvious implementation. Mostly implementations " +"that depend on all fields or variants already implementing the trait." msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-qr.md +#: src/idiomatic/polymorphism/refresher/deriving-traits.md msgid "" -"If students ask about `Pin`, then explain why CXX needs it for mutable " -"references to C++ data: the answer is that C++ data can’t be moved around " -"like Rust data, because it may contain self-referential pointers." +"`PartialEq`/`Eq` can be derived on types whose fields / variants all " +"implement those traits fairly easily: line up the fields / variants, if any " +"of them don't match then the equality check returns false." msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-png.md -#, fuzzy -msgid "CXX Error Handling: PNG Example" -msgstr "āĻ¤ā§āϰ⧁āϟāĻŋ āϏāĻžāĻŽāϞāĻžāύ⧋" +#: src/idiomatic/polymorphism/refresher/deriving-traits.md +msgid "" +"Derives let us avoid boilerplate mechanically and predictably, the authors " +"of a derive implementation likely authored the trait the derive was " +"implemented with the proper semantics of a trait in mind." +msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-png.md +#: src/idiomatic/polymorphism/refresher/deriving-traits.md msgid "" -"A prototype of a PNG decoder illustrates what can be done when the " -"successful result cannot be passed across the FFI boundary:" +"Ask the class: Have the students had to deal with a codebase where most of " +"the code was trivial boilerplate?" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-png.md -msgid "\"gfx::rust_bindings\"" +#: src/idiomatic/polymorphism/refresher/deriving-traits.md +msgid "This is similar to Haskell's `deriving` system." msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-png.md -msgid "/// This returns an FFI-friendly equivalent of `Result," +#: src/idiomatic/polymorphism/refresher/deriving-traits.md +msgid "references:" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-png.md -msgid "/// ()>`." +#: src/idiomatic/polymorphism/refresher/deriving-traits.md +msgid "" +"https://doc.rust-lang.org/reference/attributes/derive.html#r-attributes." +"derive" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-png.md -msgid "/// C++ bindings for the `crate::png::ResultOfPngReader` type." +#: src/idiomatic/polymorphism/refresher/default-impls.md +msgid "Default Method Implementations" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-png.md -msgid "/// C++ bindings for the `crate::png::PngReader` type." +#: src/idiomatic/polymorphism/refresher/default-impls.md +msgid "// Required Method\n" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-png.md -msgid "" -"`PngReader` and `ResultOfPngReader` are Rust types --- objects of these " -"types cannot cross the FFI boundary without indirection of a `Box`. We " -"can't have an `out_parameter: &mut PngReader`, because CXX doesn't allow C++ " -"to store Rust objects by value." +#: src/idiomatic/polymorphism/refresher/default-impls.md +msgid "// Default implementation\n" msgstr "" -#: src/chromium/interoperability-with-cpp/error-handling-png.md +#: src/idiomatic/polymorphism/refresher/default-impls.md msgid "" -"This example illustrates that even though CXX doesn't support arbitrary " -"generics nor templates, we can still pass them across the FFI boundary by " -"manually specializing / monomorphizing them into a non-generic type. In the " -"example `ResultOfPngReader` is a non-generic type that forwards into " -"appropriate methods of `Result` (e.g. into `is_err`, `unwrap`, and/or " -"`as_mut`)." +"Traits often have methods that are implemented for you already, once you " +"implement the required methods." msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md -msgid "Using cxx in Chromium" +#: src/idiomatic/polymorphism/refresher/default-impls.md +msgid "" +"A trait method has a default implementation if the function body is present. " +"This implementation can be written in terms of other methods available, such " +"as other methods in the trait or methods of a supertrait." msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +#: src/idiomatic/polymorphism/refresher/default-impls.md msgid "" -"In Chromium, we define an independent `#[cxx::bridge] mod` for each leaf-" -"node where we want to use Rust. You'd typically have one for each " -"`rust_static_library`. Just add" +"Often you'll see methods that provide the broad functionality that is " +"necessary to implement (like `Ord`'s `compare`) with default implementations " +"for functions that can be implemented in terms of those methods (like " +"`Ord`'s `max`/`min`/`clamp`)." msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +#: src/idiomatic/polymorphism/refresher/default-impls.md msgid "" -"```gn\n" -"cxx_bindings = [ \"my_rust_file.rs\" ]\n" -" # list of files containing #[cxx::bridge], not all source files\n" -"allow_unsafe = true\n" -"```" +"Default methods can be overridden by derive macros, as derive macros produce " +"arbitrary ASTs in the implementation." msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md +#: src/idiomatic/polymorphism/refresher/default-impls.md msgid "" -"to your existing `rust_static_library` target alongside `crate_root` and " -"`sources`." +"https://doc.rust-lang.org/reference/items/traits.html#r-items.traits." +"associated-item-decls" msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md -msgid "C++ headers will be generated at a sensible location, so you can just" +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "Supertraits / Trait Dependencies" msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md -msgid "\"ui/base/my_rust_file.rs.h\"" +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "Traits can be extended by new traits." msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md -msgid "" -"You will find some utility functions in `//base` to convert to/from Chromium " -"C++ types to CXX Rust types --- for example [`SpanToRustSlice`](https://" -"source.chromium.org/chromium/chromium/src/+/main:base/containers/span_rust.h;" -"l=21)." +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "/* methods common to all animals */" msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md -msgid "Students may ask --- why do we still need `allow_unsafe = true`?" +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "/* methods only for mammals */" msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md -msgid "" -"The broad answer is that no C/C++ code is \"safe\" by the normal Rust " -"standards. Calling back and forth to C/C++ from Rust may do arbitrary things " -"to memory, and compromise the safety of Rust's own data layouts. Presence of " -"_too many_ `unsafe` keywords in C/C++ interop can harm the signal-to-noise " -"ratio of such a keyword, and is [controversial](https://steveklabnik.com/" -"writing/the-cxx-debate), but strictly, bringing any foreign code into a Rust " -"binary can cause unexpected behavior from Rust's perspective." +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "// From stdlib\n" msgstr "" -#: src/chromium/interoperability-with-cpp/using-cxx-in-chromium.md -msgid "" -"The narrow answer lies in the diagram at the top of [this page](../" -"interoperability-with-cpp.md) --- behind the scenes, CXX generates Rust " -"`unsafe` and `extern \"C\"` functions just like we did manually in the " -"previous section." +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "/* methods for Ord */" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -#, fuzzy -msgid "Exercise: Interoperability with C++" -msgstr "āφāĻ¨ā§āϤāσāĻ•āĻžāĻ°ā§āϝāĻ•ā§āώāĻŽāϤāĻž" - -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Part one" +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "" +"When authoring a trait, you can specify traits that a type must also. These " +"are called _supertraits_." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/supertraits.md msgid "" -"In the Rust file you previously created, add a `#[cxx::bridge]` which " -"specifies a single function, to be called from C++, called " -"`hello_from_rust`, taking no parameters and returning no value." +"For the example above, any type that implements `Mammal` must also implement " +"`Animal`." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/supertraits.md msgid "" -"Modify your previous `hello_from_rust` function to remove `extern \"C\"` and " -"`#[no_mangle]`. This is now just a standard Rust function." +"These hierarchies of traits let us design systems around the behavior of " +"complex real-world taxonomies (like fauna, machine hardware, operating " +"system specifics, etc)." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Modify your `gn` target to build these bindings." +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "This is distinct from object inheritance! But it looks similar." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/supertraits.md msgid "" -"In your C++ code, remove the forward-declaration of `hello_from_rust`. " -"Instead, include the generated header file." +"Object inheritance allows for overrides and brings in the behavior of the " +"inherited types by default." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Build and run!" +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "" +"A trait having a supertrait doesn't mean that trait can override method " +"implementations as default implementations." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Part two" +#: src/idiomatic/polymorphism/refresher/supertraits.md +msgid "" +"https://doc.rust-lang.org/reference/items/traits.html?highlight=supertrait#r-" +"items.traits.supertraits" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md +msgid "Blanket Trait Implementations" +msgstr "" + +#: src/idiomatic/polymorphism/refresher/blanket-impls.md msgid "" -"It's a good idea to play with CXX a little. It helps you think about how " -"flexible Rust in Chromium actually is." +"When a trait is local, we can implement it for as many types as we like. How " +"far can we take this?" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -#, fuzzy -msgid "Some things to try:" -msgstr "āĻ•āĻŋāϛ⧁ āύ⧋āϟ:" +#: src/idiomatic/polymorphism/refresher/blanket-impls.md +msgid "" +"// A blanket implementation! If something implements Display, it implements\n" +"// PrettyPrint.\n" +msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Call back into C++ from Rust. You will need:" +#: src/idiomatic/polymorphism/refresher/blanket-impls.md +msgid "\"{self}\"" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md msgid "" -"An additional header file which you can `include!` from your `cxx::bridge`. " -"You'll need to declare your C++ function in that new header file." +"The subject of a trait implementation at the definition site of a trait can " +"be anything, including `T` with no bounds." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md msgid "" -"An `unsafe` block to call such a function, or alternatively specify the " -"`unsafe` keyword in your `#[cxx::bridge]` [as described here](https://cxx.rs/" -"extern-c++.html#functions-and-member-functions)." +"We can't do anything with a `T` we don't know nothing about, so this is " +"uncommon." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md msgid "" -"You may also need to `#include \"third_party/rust/cxx/v1/crate/include/cxx." -"h\"`" +"Conditional blanket implementations are much more useful and you are more " +"likely to see and author them." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Pass a C++ string from C++ into Rust." +#: src/idiomatic/polymorphism/refresher/blanket-impls.md +msgid "" +"These implementations will have a bound on the trait, like `impl ToString for T {...}`" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Pass a reference to a C++ object into Rust." +#: src/idiomatic/polymorphism/refresher/blanket-impls.md +msgid "" +"In the example above we have a blanket implementation for all types that " +"implement Display, the implementation has one piece of information available " +"to it from the trait bounds: it implements `Display::fmt`." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md msgid "" -"Intentionally get the Rust function signatures mismatched from the `#[cxx::" -"bridge]`, and get used to the errors you see." +"This is enough to write an implementation for pretty printing to console." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md msgid "" -"Intentionally get the C++ function signatures mismatched from the `#[cxx::" -"bridge]`, and get used to the errors you see." +"Do be careful with these kinds of implementations, as it may end up " +"preventing users downstream from implementing a more meaningful." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md msgid "" -"Pass a `std::unique_ptr` of some type from C++ into Rust, so that Rust can " -"own some C++ object." +"The above isn't written for `Debug` as that would mean almost all types end " +"up implementing `PrettyPrint`, and `Debug` is not semantically similar to " +"`Display`: It's meant for debug output instead of something more human-" +"readable." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/blanket-impls.md msgid "" -"Create a Rust object and pass it into C++, so that C++ owns it. (Hint: you " -"need a `Box`)." +"https://doc.rust-lang.org/reference/glossary.html#blanket-implementation" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Declare some methods on a C++ type. Call them from Rust." +#: src/idiomatic/polymorphism/refresher/conditional-methods.md +msgid "Conditional Method Implementations" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Declare some methods on a Rust type. Call them from C++." +#: src/idiomatic/polymorphism/refresher/conditional-methods.md +msgid "// No trait bounds on the type definition.\n" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Part three" +#: src/idiomatic/polymorphism/refresher/conditional-methods.md +msgid "// Instead bounds are put on the implementations for the type.\n" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "" -"Now you understand the strengths and limitations of CXX interop, think of a " -"couple of use-cases for Rust in Chromium where the interface would be " -"sufficiently simple. Sketch how you might define that interface." +#: src/idiomatic/polymorphism/refresher/conditional-methods.md +msgid "// alternatively\n" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "The [`cxx` binding reference](https://cxx.rs/bindings.html)" +#: src/idiomatic/polymorphism/refresher/conditional-methods.md +msgid "// Specifies the trait bound in a where expression\n" msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/conditional-methods.md msgid "" -"The [`rust_static_library` gn template](https://source.chromium.org/chromium/" -"chromium/src/+/main:build/rust/rust_static_library.gni;l=16)" +"When authoring a type with generic parameters, we can write implementations " +"for that type that depend on what the parameters are or what traits they " +"implement." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md -msgid "Some of the questions you may encounter:" +#: src/idiomatic/polymorphism/refresher/conditional-methods.md +msgid "These methods are only available when the type meets those conditions." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/conditional-methods.md msgid "" -"I'm seeing a problem initializing a variable of type X with type Y, where X " -"and Y are both function types. This is because your C++ function doesn't " -"quite match the declaration in your `cxx::bridge`." +"For things like ordered sets, where you'd want the inner type to always be " +"`Ord`, this is the preferred way of putting a trait bound on a parameter of " +"a type." msgstr "" -#: src/exercises/chromium/interoperability-with-cpp.md +#: src/idiomatic/polymorphism/refresher/conditional-methods.md msgid "" -"I seem to be able to freely convert C++ references into Rust references. " -"Doesn't that risk UB? For CXX's _opaque_ types, no, because they are zero-" -"sized. For CXX trivial types yes, it's _possible_ to cause UB, although " -"CXX's design makes it quite difficult to craft such an example." +"We don't put the definition on the type itself as this would cause " +"downstream issues for everywhere the type is mentioned with a generic " +"parameter." msgstr "" -#: src/chromium/adding-third-party-crates.md +#: src/idiomatic/polymorphism/refresher/conditional-methods.md msgid "" -"Rust libraries are called \"crates\" and are found at [crates.io](https://" -"crates.io). It's _very easy_ for Rust crates to depend upon one another. So " -"they do!" +"We can maintain invariants just fine with conditional method implementations." msgstr "" -#: src/chromium/adding-third-party-crates.md -#, fuzzy -msgid "C++ library" -msgstr "āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ" - -#: src/chromium/adding-third-party-crates.md -#, fuzzy -msgid "Rust crate" -msgstr "āϰāĻžāĻ¸ā§āϟ āχāϕ⧋āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "" +"What prevents users from writing arbitrary trait implementations for any " +"type?" +msgstr "" -#: src/chromium/adding-third-party-crates.md -#, fuzzy -msgid "Build system" -msgstr "āϰāĻžāĻ¸ā§āϟ āχāϕ⧋āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "// Crate `postgresql-bindings`\n" +msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "Lots" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "/* details */" msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "Consistent: `Cargo.toml`" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "// Crate `database-traits`, depends on `postgresql-bindings`\n" msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "Typical library size" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "/* methods */" msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "Large-ish" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "// ✅, `DbConnection` is local.\n" msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "Small" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "// Crate `mycoolnewdb` depends on `database-traits`\n" msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "Transitive dependencies" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "// ✅, `MyCoolNewDbConn` is local.\n" msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "Few" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "" +"// Neither `PostgresqlConn` or `DbConnection` are local to `mycoolnewdb`.\n" +"// This would lead to two implementations of `DbConnection` for " +"PostgresqlConn!\n" msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "For a Chromium engineer, this has pros and cons:" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "// ❌🔨\n" msgstr "" -#: src/chromium/adding-third-party-crates.md +#: src/idiomatic/polymorphism/refresher/orphan-rule.md msgid "" -"All crates use a common build system so we can automate their inclusion into " -"Chromium..." +"Rust traits should never be able to be implemented twice in its ecosystem. " +"Two implementations of the same trait for the same type is a conflict with " +"no solution." msgstr "" -#: src/chromium/adding-third-party-crates.md +#: src/idiomatic/polymorphism/refresher/orphan-rule.md msgid "" -"... but, crates typically have transitive dependencies, so you will likely " -"have to bring in multiple libraries." +"We can prevent this within a crate by detecting if there are multiple " +"definitions and disallowing it, but what about between crates in the entire " +"Rust ecosystem?" msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "We'll discuss:" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "" +"Types are either _local_ to a crate, they are defined there, or they're not." msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "How to put a crate in the Chromium source code tree" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "" +"In the example's \"crates\", `PostgresqlConn` is local to `postgresql-" +"bindings`, `MyCoolNewDbConn` is local to `mycoolnewdb`." msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "How to make `gn` build rules for it" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "" +"Traits are also either _local_ to a crate, they are defined there, or " +"they're not." msgstr "" -#: src/chromium/adding-third-party-crates.md -msgid "How to audit its source code for sufficient safety." +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "" +"Again in the example, the `DbConnection` trait is local to `database-traits`." msgstr "" -#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md -msgid "Configuring the `Cargo.toml` file to add crates" +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "If something is local, you can write trait implementations for it." msgstr "" -#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md +#: src/idiomatic/polymorphism/refresher/orphan-rule.md msgid "" -"Chromium has a single set of centrally-managed direct crate dependencies. " -"These are managed through a single [`Cargo.toml`](https://source.chromium." -"org/chromium/chromium/src/+/main:third_party/rust/chromium_crates_io/Cargo." -"toml):" +"If the trait is local, you can write implementations of that trait for any " +"type." msgstr "" -#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md +#: src/idiomatic/polymorphism/refresher/orphan-rule.md msgid "" -"```toml\n" -"[dependencies]\n" -"bitflags = \"1\"\n" -"cfg-if = \"1\"\n" -"cxx = \"1\"\n" -"# lots more...\n" -"```" +"If the type is local, you can write any trait implementations for that type." msgstr "" -#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md -msgid "" -"As with any other `Cargo.toml`, you can specify [more details about the " -"dependencies](https://doc.rust-lang.org/cargo/reference/specifying-" -"dependencies.html) --- most commonly, you'll want to specify the `features` " -"that you wish to enable in the crate." +#: src/idiomatic/polymorphism/refresher/orphan-rule.md +msgid "Outside of these boundaries, trait implementations cannot be written." msgstr "" -#: src/chromium/adding-third-party-crates/configuring-cargo-toml.md +#: src/idiomatic/polymorphism/refresher/orphan-rule.md msgid "" -"When adding a crate to Chromium, you'll often need to provide some extra " -"information in an additional file, `gnrt_config.toml`, which we'll meet next." +"This keeps implementations \"coherent\": Only one implementation of a trait " +"for a type can exist across crates." msgstr "" -#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md +#: src/idiomatic/polymorphism/refresher/orphan-rule.md msgid "" -"Alongside `Cargo.toml` is [`gnrt_config.toml`](https://source.chromium.org/" -"chromium/chromium/src/+/main:third_party/rust/chromium_crates_io/gnrt_config." -"toml). This contains Chromium-specific extensions to crate handling." +"https://doc.rust-lang.org/stable/reference/items/implementations.html#r-" +"items.impl.trait.orphan-rule" msgstr "" -#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md -msgid "" -"If you add a new crate, you should specify at least the `group`. This is one " -"of:" +#: src/idiomatic/polymorphism/refresher/sized.md +msgid "Statically Sized and Dynamically Sized Types" msgstr "" -#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md -#: src/chromium/adding-third-party-crates/depending-on-a-crate.md -msgid "For instance," +#: src/idiomatic/polymorphism/refresher/sized.md +msgid "/* : Sized */" msgstr "" -#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md +#: src/idiomatic/polymorphism/refresher/sized.md msgid "" -"Depending on the crate source code layout, you may also need to use this " -"file to specify where its `LICENSE` file(s) can be found." +"Motivation: Being able to specify between types whose size are known and " +"compile time and types whose size are known at runtime is useful for" msgstr "" -#: src/chromium/adding-third-party-crates/configuring-gnrt-config-toml.md +#: src/idiomatic/polymorphism/refresher/sized.md msgid "" -"Later, we'll see some other things you will need to configure in this file " -"to resolve problems." +"The Sized trait is automatically implemented by types with a known size at " +"compile-time." msgstr "" -#: src/chromium/adding-third-party-crates/downloading-crates.md +#: src/idiomatic/polymorphism/refresher/sized.md msgid "" -"A tool called `gnrt` knows how to download crates and how to generate `BUILD." -"gn` rules." +"This trait is also automatically added to any type parameter that doesn't " +"opt-out of being sized." msgstr "" -#: src/chromium/adding-third-party-crates/downloading-crates.md -msgid "To start, download the crate you want like this:" +#: src/idiomatic/polymorphism/refresher/sized.md +msgid "Most types implement `Sized`: they have a compile-time known size." msgstr "" -#: src/chromium/adding-third-party-crates/downloading-crates.md +#: src/idiomatic/polymorphism/refresher/sized.md msgid "" -"Although the `gnrt` tool is part of the Chromium source code, by running " -"this command you will be downloading and running its dependencies from " -"`crates.io`. See [the earlier section](../cargo.md) discussing this security " -"decision." +"Types like `[T]`, `str` and `dyn Trait` are all dynamically sized types. " +"Their size is stored as part of the reference to the value of that type." msgstr "" -#: src/chromium/adding-third-party-crates/downloading-crates.md -msgid "This `vendor` command may download:" +#: src/idiomatic/polymorphism/refresher/sized.md +msgid "Type parameters automatically implement `Sized` unless specified." msgstr "" -#: src/chromium/adding-third-party-crates/downloading-crates.md -#, fuzzy -msgid "Your crate" -msgstr "āĻĻāϰāĻ•āĻžāϰ⧀ āĻ•ā§āϰ⧇āϟ-āϏāĻŽā§‚āĻš" +#: src/idiomatic/polymorphism/refresher/sized.md +msgid "" +"https://doc.rust-lang.org/stable/reference/dynamically-sized-types.html#r-" +"dynamic-sized" +msgstr "" -#: src/chromium/adding-third-party-crates/downloading-crates.md -msgid "Direct and transitive dependencies" +#: src/idiomatic/polymorphism/refresher/monomorphization.md +msgid "// instance one, &Vec -> ()\n" msgstr "" -#: src/chromium/adding-third-party-crates/downloading-crates.md +#: src/idiomatic/polymorphism/refresher/monomorphization.md +msgid "// instance two, &Vec -> ()\n" +msgstr "" + +#: src/idiomatic/polymorphism/refresher/monomorphization.md msgid "" -"New versions of other crates, as required by `cargo` to resolve the complete " -"set of crates required by Chromium." +"Each instance of a function or type with generics gets transformed into a " +"unique, concrete version of that function at compile time. Generics do not " +"exist at runtime, only specific types." msgstr "" -#: src/chromium/adding-third-party-crates/downloading-crates.md +#: src/idiomatic/polymorphism/refresher/monomorphization.md msgid "" -"Chromium maintains patches for some crates, kept in `//third_party/rust/" -"chromium_crates_io/patches`. These will be reapplied automatically, but if " -"patching fails you may need to take manual action." +"This comes with a strong baseline performance and capacity for optimization, " +"but at a cost of binary size and compile time." msgstr "" -#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md +#: src/idiomatic/polymorphism/refresher/monomorphization.md msgid "" -"Once you've downloaded the crate, generate the `BUILD.gn` files like this:" +"There are plenty of ways to trim binary size and compilation times, but " +"we're not covering them here." msgstr "" -#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md -msgid "Now run `git status`. You should find:" +#: src/idiomatic/polymorphism/refresher/monomorphization.md +msgid "" +"Pay for what you use: Binary size increase of monomorphization is only " +"incurred for instances of a type or functions on a type used in the final " +"program or dynamic library." msgstr "" -#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md +#: src/idiomatic/polymorphism/refresher/monomorphization.md msgid "" -"At least one new crate source code in `third_party/rust/chromium_crates_io/" -"vendor`" +"When to care: Monomorphization impacts compile times and binary size. In " +"circumstances like WebAssembly in-browser or embedded systems development, " +"you may want to be mindful about designing with generics in mind." msgstr "" -#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md +#: src/idiomatic/polymorphism/from-oop-to-rust.md +msgid "From OOP to Rust: Composition, Not Inheritance" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust.md msgid "" -"At least one new `BUILD.gn` in `third_party/rust//v`" +"Inheritance is key to OOP's success as a paradigm. Decades of successful " +"software engineering has been done with Inheritance as a core part of " +"business logic." msgstr "" -#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md -msgid "An appropriate `README.chromium`" +#: src/idiomatic/polymorphism/from-oop-to-rust.md +msgid "So why did Rust avoid inheritance?" msgstr "" -#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md +#: src/idiomatic/polymorphism/from-oop-to-rust.md msgid "" -"The \"major semver version\" is a [Rust \"semver\" version number](https://" -"doc.rust-lang.org/cargo/reference/semver.html)." +"How do we move from inheritance-based problem solving to Rust's approach?" msgstr "" -#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md +#: src/idiomatic/polymorphism/from-oop-to-rust.md +msgid "How do you represent heterogeneous collections in Rust?" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust.md msgid "" -"Take a close look, especially at the things generated in `third_party/rust`." +"In this section we'll be looking at how to move from thinking about " +"polymorphic problem solving with types in OOP languages like java, C++ etc. " +"to Rust's trait-based approach to Polymorphism." msgstr "" -#: src/chromium/adding-third-party-crates/generating-gn-build-rules.md +#: src/idiomatic/polymorphism/from-oop-to-rust.md msgid "" -"Talk a little about semver --- and specifically the way that in Chromium " -"it's to allow multiple incompatible versions of a crate, which is " -"discouraged but sometimes necessary in the Cargo ecosystem." +"There will be differences, but there are also plenty of areas in common – " +"especially with modern standards of OOP development. Remember to keep an " +"open mind." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md +msgid "Inheritance in OOP languages" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md +msgid "// Base class\n" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md +msgid "// Inheriting class\n" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md +msgid "// Create a Car object\n" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md +msgid "// Inherited method\n" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md +msgid "// Car's own method\n" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md msgid "" -"If your build fails, it may be because of a `build.rs`: programs which do " -"arbitrary things at build time. This is fundamentally at odds with the " -"design of `gn` and `ninja` which aim for static, deterministic, build rules " -"to maximize parallelism and repeatability of builds." +"This should be a short reminder for students about what inheritance is in " +"other languages." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md msgid "" -"Some `build.rs` actions are automatically supported; others require action:" +"Inheritance is a mechanism where a \"child\" type gains the fields and " +"methods of the \"parent\" types it is inheriting from." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "build script effect" +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md +msgid "Methods are able to be overridden as-needed by the inheriting type." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "Supported by our gn templates" +#: src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md +msgid "Can call methods of inherited-from classes with `super`." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "Work required by you" +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "// methods\n" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "Checking rustc version to configure features on and off" +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "// 🔨❌, Rust does not have inheritance!\n" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "None" +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "// Inherited \"id\" field\n" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "Checking platform or CPU to configure features on and off" +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "" +"// methods, but also includes Id's methods, or maybe overrides to\n" +" // those methods.\n" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -#, fuzzy -msgid "Generating code" -msgstr "āĻœā§‡āύ⧇āϰāĻŋāĻ•āϏ" +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "// ✅\n" +msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "Yes - specify in `gnrt_config.toml`" +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "// All of data's methods that aren't from traits.\n" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "Building C/C++" +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "// Implementations for traits in separate impl blocks.\n" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "Patch around it" +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "Inheritance comes with a number of downsides." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md -msgid "Arbitrary other actions" +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "Heterogeneous by default:" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems.md +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md msgid "" -"Fortunately, most crates don't contain a build script, and fortunately, most " -"build scripts only do the top two actions." +"Class inheritance implicitly allows types of different classes to be used " +"interchangeably, without being able to specify a concrete type or if a type " +"is identical to another." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md msgid "" -"If `ninja` complains about missing files, check the `build.rs` to see if it " -"writes source code files." +"For operations like equality, comparison this allows for comparison and " +"equality that throws and error or otherwise panics." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md msgid "" -"If so, modify [`gnrt_config.toml`](../configuring-gnrt-config-toml.md) to " -"add `build-script-outputs` to the crate. If this is a transitive dependency, " -"that is, one on which Chromium code should not directly depend, also add " -"`allow-first-party-usage=false`. There are several examples already in that " -"file:" +"Multiple sources of truth for what makes up a data structure and how it " +"behaves:" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "A type's fields are obscured by the inheritance hierarchy." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md msgid "" -"```toml\n" -"[crate.unicode-linebreak]\n" -"allow-first-party-usage = false\n" -"build-script-outputs = [\"tables.rs\"]\n" -"```" +"A type's methods could be overriding a parent type or be overridden by a " +"child type, it's hard to tell what the behavior of a type is in complex " +"codebases maintained by multiple parties." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md +msgid "Dynamic dispatch as default adds overhead from vtable lookups:" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md msgid "" -"Now rerun [`gnrt.py -- gen`](../generating-gn-build-rules.md) to regenerate " -"`BUILD.gn` files to inform ninja that this particular output file is input " -"to subsequent build steps." +"For dynamic dispatch to work, there needs to be somewhere to store " +"information on what methods to call and other pieces of runtime-known pieces " +"of information on the type." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md +#: src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md msgid "" -"Some crates use the [`cc`](https://crates.io/crates/cc) crate to build and " -"link C/C++ libraries. Other crates parse C/C++ using [`bindgen`](https://" -"crates.io/crates/bindgen) within their build scripts. These actions can't be " -"supported in a Chromium context --- our gn, ninja and LLVM build system is " -"very specific in expressing relationships between build actions." +"This store is the `vtable` for a value. Method calls will require more " +"dereferences than calling a method for a type that is known at compile time." msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md -msgid "So, your options are:" +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +msgid "// Data\n" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md -msgid "Avoid these crates" +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +msgid "// Concrete behavior\n" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md -msgid "Apply a patch to the crate." +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +msgid "// Abstract behavior\n" msgstr "" -#: src/chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +msgid "// Instanced behavior\n" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md msgid "" -"Patches should be kept in `third_party/rust/chromium_crates_io/patches/" -"` - see for example the [patches against the `cxx` crate](https://" -"source.chromium.org/chromium/chromium/src/+/main:third_party/rust/" -"chromium_crates_io/patches/cxx/) - and will be applied automatically by " -"`gnrt` each time it upgrades the crate." +"From Rust's perspective, one where Inheritance was never there, introducing " +"inheritance would look like muddying the water between types and traits." msgstr "" -#: src/chromium/adding-third-party-crates/depending-on-a-crate.md +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +msgid "A type is a concrete piece of data and its associated behavior." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +msgid "A trait is abstract behavior that must be implemented by a type." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md msgid "" -"Once you've added a third-party crate and generated build rules, depending " -"on a crate is simple. Find your `rust_static_library` target, and add a " -"`dep` on the `:lib` target within your crate." +"A class is a combination of data, behavior, and overrides to that behavior." msgstr "" -#: src/chromium/adding-third-party-crates/depending-on-a-crate.md -msgid "Specifically," +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +msgid "" +"Coming from Rust, an inheritable class looks like a type that is also a " +"trait." msgstr "" -#: src/chromium/adding-third-party-crates/depending-on-a-crate.md +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md +msgid "This is not an upside, as we can no longer reason about concrete types." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md msgid "" -"```bob\n" -" +------------+ +----------------------+\n" -"\"//third_party/rust\" | crate name | \"/v\" | major semver version | \":" -"lib\"\n" -" +------------+ +----------------------+\n" -"```" +"Without being able to separate the two, it becomes difficult to reason about " +"generic behavior vs concrete specifics, because in OOP these two concepts " +"are tied up in each other." msgstr "" -#: src/chromium/adding-third-party-crates/depending-on-a-crate.md +#: src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md msgid "" -"```gn\n" -"rust_static_library(\"my_rust_lib\") {\n" -" crate_root = \"lib.rs\"\n" -" sources = [ \"lib.rs\" ]\n" -" deps = [ \"//third_party/rust/example_rust_crate/v1:lib\" ]\n" -"}\n" -"```" +"The convenience of flat field access and DRY in type definitions is not " +"worth the loss in specificity between writing code that delineates between " +"behavior and data." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md +msgid "\"Inheritance\" in Rust: Supertraits" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md +msgid "" +"In Rust, traits can depend on other traits. We're already familiar with " +"Traits being able to have Supertraits." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md +msgid "This looks superficially similar to inheritance." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md +msgid "" +"This is a mechanism like inheritance, but separates the data from the " +"behavior." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md +msgid "Keeps behavior in a state where it's easy to reason about." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md +msgid "Makes what we aim to achieve with \"multiple inheritance\" easier too:" msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md -msgid "Auditing Third Party Crates" +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md +msgid "" +"We only care about what behavior a type is capable of at the point where we " +"clarify we want that behavior (when bounding a generic by traits)." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md msgid "" -"Adding new libraries is subject to Chromium's standard [policies](https://" -"chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/rust." -"md#Third_party-review), but of course also subject to security review. As " -"you may be bringing in not just a single crate but also transitive " -"dependencies, there may be a lot of code to review. On the other hand, safe " -"Rust code can have limited negative side effects. How should you review it?" +"By specifying multiple traits on a generic, we know that the type has the " +"methods of all those traits." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md msgid "" -"Over time Chromium aims to move to a process based around [cargo vet]" -"(https://mozilla.github.io/cargo-vet/)." +"Does not involve inheritance of fields. A trait doesn't expose fields, only " +"methods and associated types / constants." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/composition.md msgid "" -"Meanwhile, for each new crate addition, we are checking for the following:" +"Rather than mixins or inheritance, we compose types by creating fields of " +"different types." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/composition.md msgid "" -"Understand why each crate is used. What's the relationship between crates? " -"If the build system for each crate contains a `build.rs` or procedural " -"macros, work out what they're for. Are they compatible with the way Chromium " -"is normally built?" +"This has downsides, largely in ergonomics of field access, but gives " +"developers a lot of control and clarity over what a type does and it has " +"access to." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md -msgid "Check each crate seems to be reasonably well maintained" +#: src/idiomatic/polymorphism/from-oop-to-rust/composition.md +msgid "" +"When deriving traits, make sure all the field types of a struct or variant " +"types of an enum implement that trait. Derive macros often assume all types " +"that compose a new type implement that trait already." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md +msgid "`dyn Trait` for Dynamic Dispatch in Rust" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md +msgid "\"Hello dyn!\"" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md msgid "" -"Use `cd third-party/rust/chromium_crates_io; cargo audit` to check for known " -"vulnerabilities (first you'll need to `cargo install cargo-audit`, which " -"ironically involves downloading lots of dependencies from the internet[2](../" -"cargo.md))" +"Dynamic Dispatch is a tool in Object Oriented Programming that is often used " +"in places where one needs to care more about the behavior of a type than " +"what the type is." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md msgid "" -"Ensure any `unsafe` code is good enough for the [Rule of Two](https://" -"chromium.googlesource.com/chromium/src/+/main/docs/security/rule-of-2." -"md#unsafe-code-in-safe-languages)" +"In OOP languages, dynamic dispatch is often an _implicit_ process and not " +"something you can opt out of." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md -msgid "Check for any use of `fs` or `net` APIs" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md +msgid "In Rust, we use `dyn Trait`: an opt-in form of dynamic dispatch." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md msgid "" -"Read all the code at a sufficient level to look for anything out of place " -"that might have been maliciously inserted. (You can't realistically aim for " -"100% perfection here: there's often just too much code.)" +"For any trait that is _dyn compatible_ we can coerce a reference to a value " +"of that trait into a `dyn Trait` value." msgstr "" -#: src/chromium/adding-third-party-crates/reviews-and-audits.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md msgid "" -"These are just guidelines --- work with reviewers from `security@chromium." -"org` to work out the right way to become confident of the crate." +"We call these _trait objects_. Their type is not known at compile time, but " +"their behavior is: what is implemented by the trait itself." msgstr "" -#: src/chromium/adding-third-party-crates/checking-in.md -msgid "Checking Crates into Chromium Source Code" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md +msgid "" +"When you _need_ OOP-style heterogeneous data structures, you can reach for " +"`Box`, but try to keep it homogeneous and generic-based first!" msgstr "" -#: src/chromium/adding-third-party-crates/checking-in.md -msgid "`git status` should reveal:" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +msgid "Dyn-compatible traits" msgstr "" -#: src/chromium/adding-third-party-crates/checking-in.md -msgid "Crate code in `//third_party/rust/chromium_crates_io`" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +msgid "// dyn compatible\n" msgstr "" -#: src/chromium/adding-third-party-crates/checking-in.md -msgid "" -"Metadata (`BUILD.gn` and `README.chromium`) in `//third_party/rust//" -"`" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +msgid "// dyn compatible, but you can't use this method when it's dyn\n" msgstr "" -#: src/chromium/adding-third-party-crates/checking-in.md -msgid "Please also add an `OWNERS` file in the latter location." +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +msgid "// no longer dyn compatible\n" msgstr "" -#: src/chromium/adding-third-party-crates/checking-in.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md msgid "" -"You should land all this, along with your `Cargo.toml` and `gnrt_config." -"toml` changes, into the Chromium repo." +"Not all traits are able to be invoked as trait objects. A trait that can be " +"invoked is referred to as a _dyn compatible_ trait." msgstr "" -#: src/chromium/adding-third-party-crates/checking-in.md -msgid "" -"**Important**: you need to use `git add -f` because otherwise `.gitignore` " -"files may result in some files being skipped." +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +msgid "This was previously called _object safe traits_ or _object safety_." msgstr "" -#: src/chromium/adding-third-party-crates/checking-in.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md msgid "" -"As you do so, you might find presubmit checks fail because of non-inclusive " -"language. This is because Rust crate data tends to include names of git " -"branches, and many projects still use non-inclusive terminology there. So " -"you may need to run:" +"Dynamic dispatch offloads a lot of compile-time type information into " +"runtime vtable information." msgstr "" -#: src/chromium/adding-third-party-crates/keeping-up-to-date.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md msgid "" -"As the OWNER of any third party Chromium dependency, you are [expected to " -"keep it up to date with any security fixes](https://chromium.googlesource." -"com/chromium/src/+/main/docs/adding_to_third_party.md#add-owners). It is " -"hoped that we will soon automate this for Rust crates, but for now, it's " -"still your responsibility just as it is for any other third party dependency." +"If a concept is incompatible with what we can meaningfully store in a " +"vtable, either the trait stops being dyn compatible or those methods are " +"excluded from being able to be used in a dyn context." msgstr "" -#: src/exercises/chromium/third-party.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md msgid "" -"Add [uwuify](https://crates.io/crates/uwuify) to Chromium, turning off the " -"crate's [default features](https://doc.rust-lang.org/cargo/reference/" -"features.html#the-default-feature). Assume that the crate will be used in " -"shipping Chromium, but won't be used to handle untrustworthy input." +"A trait is dyn-compatible when all its supertraits are dyn-compatible and " +"when it has no associated constants/types, and no methods that depend on " +"generics." msgstr "" -#: src/exercises/chromium/third-party.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md msgid "" -"(In the next exercise we'll use uwuify from Chromium, but feel free to skip " -"ahead and do that now if you like. Or, you could create a new " -"[`rust_executable` target](https://source.chromium.org/chromium/chromium/src/" -"+/main:build/rust/rust_executable.gni) which uses `uwuify`)." +"You'll most frequently run into dyn incompatible traits when they have " +"associated types/constants or return values of `Self` (i.e. the Clone trait " +"is not dyn compatible.)" msgstr "" -#: src/exercises/chromium/third-party.md -msgid "Students will need to download lots of transitive dependencies." +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +msgid "" +"This is because the associated data would have to be stored in vtables, " +"taking up extra memory." msgstr "" -#: src/exercises/chromium/third-party.md -msgid "The total crates needed are:" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +msgid "" +"For methods like `clone`, this disqualifies dyn compatibility because the " +"output type depends on the concrete type of `self`." msgstr "" -#: src/exercises/chromium/third-party.md -msgid "`instant`," +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md +msgid "" +"https://doc.rust-lang.org/1.91.1/reference/items/traits.html#r-items.traits." +"dyn-compatible" msgstr "" -#: src/exercises/chromium/third-party.md -msgid "`lock_api`," +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +msgid "Generic Function Parameters vs dyn Trait" msgstr "" -#: src/exercises/chromium/third-party.md -msgid "`parking_lot`," +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +msgid "" +"We have two means of writing polymorphic functions, how do they compare?" msgstr "" -#: src/exercises/chromium/third-party.md -msgid "`parking_lot_core`," +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +msgid "// Monomorphized to a unique function for i32 inputs.\n" msgstr "" -#: src/exercises/chromium/third-party.md -msgid "`redox_syscall`," +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +msgid "// One per\n" msgstr "" -#: src/exercises/chromium/third-party.md -msgid "`scopeguard`," +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +msgid "We can write polymorphic functions over generics or over trait objects." msgstr "" -#: src/exercises/chromium/third-party.md -msgid "`smallvec`, and" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +msgid "" +"When writing functions with generic parameters, for each unique type that " +"substitutes a parameter a new version of that function is generated." msgstr "" -#: src/exercises/chromium/third-party.md -msgid "`uwuify`." +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md +msgid "" +"We went over this in monomorphization: in exchange for binary size, we gain " +"a greater capacity for optimization." msgstr "" -#: src/exercises/chromium/third-party.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md msgid "" -"If students are downloading even more than that, they probably forgot to " -"turn off the default features." +"When writing functions that take a trait object, only one version of that " +"function will exist in the final binary (not counting inlining.)" msgstr "" -#: src/exercises/chromium/third-party.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md msgid "" -"Thanks to [Daniel Liu](https://github.com/Daniel-Liu-c0deb0t) for this crate!" +"Generic parameters are zero-cost other than binary size. Types must be " +"homogenous (all instances of T can only be the same type)." msgstr "" -#: src/exercises/chromium/bringing-it-together.md -msgid "Bringing It Together --- Exercise" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md +msgid "// 4 bytes, owned value\n" msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md +msgid "// 8 bytes, reference\n" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md +msgid "// 16 bytes, wide pointer\n" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md +msgid "Trait objects are a limited way of solving problems." +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md msgid "" -"In this exercise, you're going to add a whole new Chromium feature, bringing " -"together everything you already learned." +"If you want to downcast to a concrete type from a trait object, you will " +"need to specify that the trait in question has Any as a supertrait or that " +"the trait object is over the main trait and `Any`." msgstr "" -#: src/exercises/chromium/bringing-it-together.md -msgid "The Brief from Product Management" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md +msgid "Even then, you will still need to cast a `dyn MyTrait` to `dyn Any`" msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md msgid "" -"A community of pixies has been discovered living in a remote rainforest. " -"It's important that we get Chromium for Pixies delivered to them as soon as " -"possible." +"Trait objects have overhead in memory, they are \"wide pointers\" that need " +"to hold not just the pointer to the data itself but another pointer for the " +"vtable." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md msgid "" -"The requirement is to translate all Chromium's UI strings into Pixie " -"language." +"Trait objects, being dynamically sized types, can only be used practically " +"via reference or pointer types." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md msgid "" -"There's not time to wait for proper translations, but fortunately pixie " -"language is very close to English, and it turns out there's a Rust crate " -"which does the translation." +"There is a baseline overhead of dereferencing the value and relevant trait " +"methods when using trait objects." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md +msgid "Heterogeneous data with `dyn trait`" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md +msgid "\"Îģ\"" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md +msgid "\"Woah\"" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md +msgid "// We know \"item\" implements Display, but we know nothing else!\n" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md +msgid "\"Display output: {}\"" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md msgid "" -"In fact, you already [imported that crate in the previous exercise](https://" -"crates.io/crates/uwuify)." +"`dyn Trait`, being a dynamic dispatch tool, lets us store heterogeneous data " +"in collections." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md msgid "" -"(Obviously, real translations of Chrome require incredible care and " -"diligence. Don't ship this!)" +"In this example, we're storing types that all implement `std::fmt::Display` " +"and printing all items in that collection to screen." msgstr "" -#: src/exercises/chromium/bringing-it-together.md -msgid "Steps" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md +msgid "Any Trait and Downcasting" msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md msgid "" -"Modify `ResourceBundle::MaybeMangleLocalizedString` so that it uwuifies all " -"strings before display. In this special build of Chromium, it should always " -"do this irrespective of the setting of `mangle_localized_strings_`." +"The `Any` trait allows us to downcast values back from dyn values into " +"concrete values." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md msgid "" -"If you've done everything right across all these exercises, congratulations, " -"you should have created Chrome for pixies!" +"This is an auto trait: like Send/Sync/Sized, it is automatically implemented " +"for any type that meets specific criteria." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md msgid "" -"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 using `base::UTF16ToUTF8` and back again." +"The criteria for Any is that a type is `'static`. That is, the type does not " +"contain any non-`'static` lifetimes within it." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md msgid "" -"If students decide to do the conversion on the Rust side, they'll need to " -"consider [`String::from_utf16`](https://doc.rust-lang.org/std/string/struct." -"String.html#method.from_utf16), consider error handling, and consider which " -"[CXX supported types can transfer a lot of u16s](https://cxx.rs/binding/" -"slice.html)." +"Any offers two related behaviors: downcasting, and runtime checking of types " +"being the same." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md msgid "" -"Students may design the C++/Rust boundary in several different ways, e.g. " -"taking and returning strings by value, or taking a mutable reference to a " -"string. If a mutable reference is used, CXX will likely tell the student " -"that they need to use [`Pin`](https://doc.rust-lang.org/std/pin/). You may " -"need to explain what `Pin` does, and then explain why CXX needs it for " -"mutable references to C++ data: the answer is that C++ data can't be moved " -"around like Rust data, because it may contain self-referential pointers." +"In the example above, we see the ability to downcast from `Any` into " +"`ThisImplementsAny` automatically." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md msgid "" -"The C++ target containing `ResourceBundle::MaybeMangleLocalizedString` will " -"need to depend on a `rust_static_library` target. The student probably " -"already did this." +"We also see `Any::is` being used to check to see what type the value is." msgstr "" -#: src/exercises/chromium/bringing-it-together.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md msgid "" -"The `rust_static_library` target will need to depend on `//third_party/rust/" -"uwuify/v0_2:lib`." +"`Any` does not implement reflection for a type, this is all you can do with " +"`Any`." msgstr "" -#: src/exercises/chromium/solutions.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md msgid "" -"Solutions to the Chromium exercises can be found in [this series of CLs]" -"(https://chromium-review.googlesource.com/c/chromium/src/+/5096560)." +"Coming from an OOP background, it's understandable to reach for this dynamic " +"dispatch tool as early as possible." msgstr "" -#: src/bare-metal.md -msgid "Welcome to Bare Metal Rust" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md +msgid "" +"This is not the preferred way of doing things, trait objects put us in a " +"situation where we're exchanging knowledge of a type that both the developer " +"and compiler has for flexibility." msgstr "" -#: src/bare-metal.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md msgid "" -"This is a standalone one-day course about bare-metal Rust, aimed at people " -"who are familiar with the basics of Rust (perhaps from completing the " -"Comprehensive Rust course), and ideally also have some experience with bare-" -"metal programming in some other language such as C." +"The above example takes things to the absurd: If adding numbers were tied up " +"in the dynamic dispatch process, it would be difficult to do anything at all." msgstr "" -#: src/bare-metal.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md msgid "" -"Today we will talk about 'bare-metal' Rust: running Rust code without an OS " -"underneath us. This will be divided into several parts:" +"But dynamic dispatch is often hidden in a lot of programming languages: " +"here's it is more explicit." msgstr "" -#: src/bare-metal.md -msgid "What is `no_std` Rust?" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md +msgid "" +"In the `i32` implementation of `AddDyn`, first we need to attempt to " +"downcast the `rhs` argument to the same type as `i32`, silently failing if " +"this isn't the case." msgstr "" -#: src/bare-metal.md -msgid "Writing firmware for microcontrollers." +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md +msgid "" +"Then we need to allocate the new value on the heap, because if we're keeping " +"this in the world of dynamic dispatch then we need to do this." msgstr "" -#: src/bare-metal.md -msgid "Writing bootloader / kernel code for application processors." +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md +msgid "" +"Once we've added two values together, if we want to view them we must " +"downcast them again into a \"real\" type we can print out given the trait " +"bounds tied up in the operation so far." msgstr "" -#: src/bare-metal.md -msgid "Some useful crates for bare-metal Rust development." +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md +msgid "" +"Ask the class: Why can't we just add Display bounds in `main` to be able to " +"print things as-is?" msgstr "" -#: src/bare-metal.md +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md msgid "" -"For the microcontroller part of the course we will use the [BBC micro:bit]" -"(https://microbit.org/) v2 as an example. It's a [development board](https://" -"tech.microbit.org/hardware/) based on the Nordic nRF51822 microcontroller " -"with some LEDs and buttons, an I2C-connected accelerometer and compass, and " -"an on-board SWD debugger." +"Answer: Because add_dyn returns only a `dyn AddDyn`, we lose information " +"about what the type implements between the argument type and return type. " +"Even if the inputs implement `Display`, the return type does not." msgstr "" -#: src/bare-metal.md -msgid "" -"To get started, install some tools we'll need later. On gLinux or Debian:" +#: src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md +msgid "This leads to less performant code which is harder to understand" msgstr "" -#: src/bare-metal.md +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "Sealed traits for Polymorphism users cannot extend" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md msgid "" -"And give users in the `plugdev` group access to the micro:bit programmer:" +"// crate can access the \"sealed\" module and its trait, but projects that\n" +"// depend on it cannot.\n" msgstr "" -#: src/bare-metal.md src/bare-metal/microcontrollers/debugging.md -msgid "On MacOS:" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "//...\n" msgstr "" -#: src/bare-metal/no_std.md -msgid "`core`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "" +"Motivation: We want trait-driven code in a crate, but we don't want projects " +"that depend on this crate to be able to implement a trait." msgstr "" -#: src/bare-metal/no_std.md -msgid "`std`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "Why?" msgstr "" -#: src/bare-metal/no_std.md -msgid "Slices, `&str`, `CStr`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "" +"The trait could be considered unstable for downstream-implementations at " +"this point in time." msgstr "" -#: src/bare-metal/no_std.md -msgid "`NonZeroU8`..." +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "" +"Alternatively: Domain is high-risk for naive implementations of a trait " +"(such as cryptography)." msgstr "" -#: src/bare-metal/no_std.md -msgid "`Option`, `Result`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "" +"The mechanism we use to do this is restricting access to a supertrait, " +"preventing downstream users from being able to implement that trait for " +"their types." msgstr "" -#: src/bare-metal/no_std.md -msgid "`Display`, `Debug`, `write!`..." +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "Why not just use enums?" msgstr "" -#: src/bare-metal/no_std.md -msgid "`panic!`, `assert_eq!`..." +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "Enums expose implementation details – \"this works for these types\"." msgstr "" -#: src/bare-metal/no_std.md -msgid "`NonNull` and all the usual pointer-related functions" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "Users need to use variant constructors of an enum to use the API." msgstr "" -#: src/bare-metal/no_std.md -msgid "`Future` and `async`/`await`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "" +"Users can use the enum as a type in their own code, and when the enum " +"changes users need to update their code to match those changes." msgstr "" -#: src/bare-metal/no_std.md -msgid "`fence`, `AtomicBool`, `AtomicPtr`, `AtomicU32`..." +#: src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md +msgid "" +"Enums require branching on variants, whereas sealed traits lets the compile " +"specify monomorphized functions for each type." msgstr "" -#: src/bare-metal/no_std.md -msgid "`Duration`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md +msgid "" +"Motivation: API is designed around a specific list of types that are valid " +"for it, users of the API are not expected to extend it." msgstr "" -#: src/bare-metal/no_std.md -msgid "`Box`, `Cow`, `Arc`, `Rc`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md +msgid "" +"Enums in Rust are _algebraic data types_, we can define different structures " +"for each variant." msgstr "" -#: src/bare-metal/no_std.md -msgid "`Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md +msgid "" +"For some domains, this might be enough polymorphism for the problem. " +"Experiment and see what works, what solutions seem to make more sense." msgstr "" -#: src/bare-metal/no_std.md -msgid "`String`, `CString`, `format!`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md +msgid "" +"By having the user-facing part of the API refer to an enum, users know what " +"types are valid inputs and can construct those types using the available " +"methods to do so." msgstr "" -#: src/bare-metal/no_std.md -msgid "`Error`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md +msgid "" +"If the types that make up the enum have invariants that the API internally " +"upholds, and the only way users can construct those types is through " +"constructors that build and maintain those invariants, then you can be sure " +"that inputs to a generic method uphold their invariants." msgstr "" -#: src/bare-metal/no_std.md -msgid "`Mutex`, `Condvar`, `Barrier`, `Once`, `RwLock`, `mpsc`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md +msgid "" +"If the types that make up the enum instead are types the user can freely " +"construct, then sanitisation and interpretation may need to be taken into " +"consideration." msgstr "" -#: src/bare-metal/no_std.md -msgid "`File` and the rest of `fs`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md +msgid "// Crate A\n" msgstr "" -#: src/bare-metal/no_std.md -msgid "`println!`, `Read`, `Write`, `Stdin`, `Stdout` and the rest of `io`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md +msgid "// Crate B, depends on A\n" msgstr "" -#: src/bare-metal/no_std.md -msgid "`Path`, `OsString`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md +msgid "" +"We've already covered normal traits at length, but compared to enums and " +"sealed traits they allow users to extend an API by implementing the behavior " +"that API asks of them." msgstr "" -#: src/bare-metal/no_std.md -msgid "`net`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md +msgid "" +"This ability for users to extend is powerful for a number of domains, from " +"serialization to abstract representations of hardware and type safe linear " +"algebra." msgstr "" -#: src/bare-metal/no_std.md -msgid "`Command`, `Child`, `ExitCode`" +#: src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md +msgid "" +"If a trait is exposed publicly in a crate, a user depending on that crate " +"can implement that trait for types they define." msgstr "" -#: src/bare-metal/no_std.md -msgid "`spawn`, `sleep` and the rest of `thread`" +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "// Problem: implementing a GUI API\n" msgstr "" -#: src/bare-metal/no_std.md -msgid "`SystemTime`, `Instant`" +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "// Question: What's the minimum useful behavior for a drawing API?\n" msgstr "" -#: src/bare-metal/no_std.md -msgid "`HashMap` depends on RNG." +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "\"arc of radius \"" msgstr "" -#: src/bare-metal/no_std.md -msgid "`std` re-exports the contents of both `core` and `alloc`." +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "// Question: What's a good API for users?\n" msgstr "" -#: src/bare-metal/minimal.md -msgid "A minimal `no_std` program" +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "" +"You're already adept at breaking down problems, but you're likely used to " +"reaching for OOP-style methods." msgstr "" -#: src/bare-metal/minimal.md -msgid "This will compile to an empty binary." +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "" +"This isn't a drastic change, it just requires re-ordering the way you " +"approach things." msgstr "" -#: src/bare-metal/minimal.md -msgid "`std` provides a panic handler; without it we must provide our own." +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "Try to solve the problem with either Generics & Traits or Enums first." msgstr "" -#: src/bare-metal/minimal.md -msgid "It can also be provided by another crate, such as `panic-halt`." +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "" +"Does the problem require a specific set of types? An enum may be the " +"cleanest way of solving this problem." msgstr "" -#: src/bare-metal/minimal.md +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md msgid "" -"Depending on the target, you may need to compile with `panic = \"abort\"` to " -"avoid an error about `eh_personality`." +"Does the problem really care about the specifics of the types involved, or " +"can behavior be focused on?" msgstr "" -#: src/bare-metal/minimal.md +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md msgid "" -"Note that there is no `main` or any other entry point; it's up to you to " -"define your own entry point. This will typically involve a linker script and " -"some assembly code to set things up ready for Rust code to run." +"Organize your problem solving around finding a minimum viable amount of " +"knowledge to implement something." msgstr "" -#: src/bare-metal/alloc.md +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "Does a trait already exist for this use case? If so, use it!" +msgstr "" + +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md msgid "" -"To use `alloc` you must implement a [global (heap) allocator](https://doc." -"rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html)." +"If you really do need heterogeneous collections, use them! They exist in " +"Rust as a tool for a reason." msgstr "" -#: src/bare-metal/alloc.md +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md msgid "" -"// Safe because `HEAP` is only used here and `entry` is only called once.\n" +"Be aware of the XY problem: a problem may seem most easily addressable by " +"one solution, but it might not tackle the root cause and could lead to new " +"difficult problems popping up in the future." msgstr "" -#: src/bare-metal/alloc.md -msgid "// Give the allocator some memory to allocate.\n" +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "" +"That is, be certain that dynamic dispatch with trait objects is what you " +"need before you commit to using them." msgstr "" -#: src/bare-metal/alloc.md -msgid "// Now we can do things that require heap allocation.\n" +#: src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md +msgid "" +"Be certain that traits are what you need before you commit to using them." msgstr "" -#: src/bare-metal/alloc.md -#, fuzzy -msgid "\"A string\"" -msgstr "String" +#: src/unsafe-deep-dive/welcome.md +msgid "IMPORTANT: THIS MODULE IS IN AN EARLY STAGE OF DEVELOPMENT" +msgstr "" -#: src/bare-metal/alloc.md +#: src/unsafe-deep-dive/welcome.md msgid "" -"`buddy_system_allocator` is a third-party crate implementing a basic buddy " -"system allocator. Other crates are available, or you can write your own or " -"hook into your existing allocator." +"Please do not consider this module of Comprehensive Rust to be complete. " +"With that in mind, your feedback, comments, and especially your concerns, " +"are very welcome." msgstr "" -#: src/bare-metal/alloc.md +#: src/unsafe-deep-dive/welcome.md msgid "" -"The const parameter of `LockedHeap` is the max order of the allocator; i.e. " -"in this case it can allocate regions of up to 2\\*\\*32 bytes." +"To comment on this module's development, please use the [GitHub issue " +"tracker](https://github.com/google/comprehensive-rust/issues)." msgstr "" -#: src/bare-metal/alloc.md -msgid "" -"If any crate in your dependency tree depends on `alloc` then you must have " -"exactly one global allocator defined in your binary. Usually this is done in " -"the top-level binary crate." +#: src/unsafe-deep-dive/welcome.md +msgid "Welcome to the Unsafe Rust Deep Dive" msgstr "" -#: src/bare-metal/alloc.md +#: src/unsafe-deep-dive/welcome.md msgid "" -"`extern crate panic_halt as _` is necessary to ensure that the `panic_halt` " -"crate is linked in so we get its panic handler." +"This deep dive aims to enable you to work productively with Unsafe Rust." msgstr "" -#: src/bare-metal/alloc.md -msgid "This example will build but not run, as it doesn't have an entry point." +#: src/unsafe-deep-dive/welcome.md +msgid "We’ll work on three areas:" msgstr "" -#: src/bare-metal/microcontrollers.md -msgid "" -"The `cortex_m_rt` crate provides (among other things) a reset handler for " -"Cortex M microcontrollers." +#: src/unsafe-deep-dive/welcome.md +msgid "establishing a mental model of Unsafe Rust" msgstr "" -#: src/bare-metal/microcontrollers.md -msgid "" -"Next we'll look at how to access peripherals, with increasing levels of " -"abstraction." +#: src/unsafe-deep-dive/welcome.md +msgid "practicing reading & writing Unsafe Rust" msgstr "" -#: src/bare-metal/microcontrollers.md +#: src/unsafe-deep-dive/welcome.md +msgid "practicing code review for Unsafe Rust" +msgstr "" + +#: src/unsafe-deep-dive/welcome.md msgid "" -"The `cortex_m_rt::entry` macro requires that the function have type `fn() -" -"> !`, because returning to the reset handler doesn't make sense." +"The goal of this class is to teach you enough Unsafe Rust for you to be able " +"to review easy cases yourself, and distinguish difficult cases that need to " +"be reviewed by more experienced Unsafe Rust engineers." msgstr "" -#: src/bare-metal/microcontrollers.md -msgid "Run the example with `cargo embed --bin minimal`" +#: src/unsafe-deep-dive/welcome.md +msgid "Establishing a mental model of Unsafe Rust" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md -msgid "" -"Most microcontrollers access peripherals via memory-mapped IO. Let's try " -"turning on an LED on our micro:bit:" +#: src/unsafe-deep-dive/welcome.md +msgid "what the `unsafe` keyword means" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md -msgid "/// GPIO port 0 peripheral address\n" +#: src/unsafe-deep-dive/welcome.md +msgid "a shared vocabulary for talking about safety" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md -msgid "// GPIO peripheral offsets\n" +#: src/unsafe-deep-dive/welcome.md +msgid "a mental model of how memory works" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md -msgid "// PIN_CNF fields\n" +#: src/unsafe-deep-dive/welcome.md +msgid "common patterns" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md -#: src/bare-metal/microcontrollers/pacs.md -#: src/bare-metal/microcontrollers/hals.md -msgid "// Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +#: src/unsafe-deep-dive/welcome.md +msgid "expectations for code that uses `unsafe`" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md -msgid "" -"// Safe because the pointers are to valid peripheral control registers, and\n" -" // no aliases exist.\n" +#: src/unsafe-deep-dive/welcome.md +msgid "Practicing working with unsafe" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md -#: src/bare-metal/microcontrollers/pacs.md -#: src/bare-metal/microcontrollers/hals.md -msgid "// Set pin 28 low and pin 21 high to turn the LED on.\n" +#: src/unsafe-deep-dive/welcome.md +msgid "reading and writing both code and documentation" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md -msgid "" -"GPIO 0 pin 21 is connected to the first column of the LED matrix, and pin 28 " -"to the first row." +#: src/unsafe-deep-dive/welcome.md +msgid "using unsafe APIs" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md -#: src/bare-metal/microcontrollers/pacs.md -#: src/bare-metal/microcontrollers/hals.md -#: src/bare-metal/microcontrollers/board-support.md -msgid "Run the example with:" +#: src/unsafe-deep-dive/welcome.md +msgid "designing and implementing them" msgstr "" -#: src/bare-metal/microcontrollers/pacs.md -msgid "Peripheral Access Crates" +#: src/unsafe-deep-dive/welcome.md +msgid "Reviewing code" msgstr "" -#: src/bare-metal/microcontrollers/pacs.md -msgid "" -"[`svd2rust`](https://crates.io/crates/svd2rust) generates mostly-safe Rust " -"wrappers for memory-mapped peripherals from [CMSIS-SVD](https://www.keil.com/" -"pack/doc/CMSIS/SVD/html/index.html) files." +#: src/unsafe-deep-dive/welcome.md +msgid "the confidence to self-review easy cases" msgstr "" -#: src/bare-metal/microcontrollers/pacs.md -msgid "" -"SVD (System View Description) files are XML files typically provided by " -"silicon vendors which describe the memory map of the device." +#: src/unsafe-deep-dive/welcome.md +msgid "the knowledge to detect difficult cases" msgstr "" -#: src/bare-metal/microcontrollers/pacs.md +#: src/unsafe-deep-dive/welcome.md msgid "" -"They are organised by peripheral, register, field and value, with names, " -"descriptions, addresses and so on." +"“We'll be using a spiral model of teaching. This means that we revisit the " +"same topic multiple times with increasing depth.”" msgstr "" -#: src/bare-metal/microcontrollers/pacs.md +#: src/unsafe-deep-dive/welcome.md msgid "" -"SVD files are often buggy and incomplete, so there are various projects " -"which patch the mistakes, add missing details, and publish the generated " -"crates." +"A round of introductions is useful, particularly if the class participants " +"don't know each other well. Ask everyone to introduce themselves, noting " +"down any particular goals for the class." msgstr "" -#: src/bare-metal/microcontrollers/pacs.md -msgid "`cortex-m-rt` provides the vector table, among other things." +#: src/unsafe-deep-dive/welcome.md +msgid "Who are you?" msgstr "" -#: src/bare-metal/microcontrollers/pacs.md -msgid "" -"If you `cargo install cargo-binutils` then you can run `cargo objdump --bin " -"pac -- -d --no-show-raw-insn` to see the resulting binary." +#: src/unsafe-deep-dive/welcome.md +msgid "What are you working on?" msgstr "" -#: src/bare-metal/microcontrollers/hals.md -msgid "HAL crates" +#: src/unsafe-deep-dive/welcome.md +msgid "What are your goals for this class?" msgstr "" -#: src/bare-metal/microcontrollers/hals.md -msgid "" -"[HAL crates](https://github.com/rust-embedded/awesome-embedded-rust#hal-" -"implementation-crates) for many microcontrollers provide wrappers around " -"various peripherals. These generally implement traits from [`embedded-hal`]" -"(https://crates.io/crates/embedded-hal)." +#: src/unsafe-deep-dive/setup.md +msgid "Setting Up" msgstr "" -#: src/bare-metal/microcontrollers/hals.md -msgid "// Create HAL wrapper for GPIO port 0.\n" +#: src/unsafe-deep-dive/setup.md +msgid "Local Rust installation" msgstr "" -#: src/bare-metal/microcontrollers/hals.md +#: src/unsafe-deep-dive/setup.md msgid "" -"`set_low` and `set_high` are methods on the `embedded_hal` `OutputPin` trait." +"You should have a Rust compiler installed that supports the 2024 edition of " +"the language, which is any version of rustc higher than 1.84." msgstr "" -#: src/bare-metal/microcontrollers/hals.md -msgid "" -"HAL crates exist for many Cortex-M and RISC-V devices, including various " -"STM32, GD32, nRF, NXP, MSP430, AVR and PIC microcontrollers." +#: src/unsafe-deep-dive/setup.md +msgid "(Optional) Create a local instance of the course" msgstr "" -#: src/bare-metal/microcontrollers/board-support.md -msgid "Board support crates" +#: src/unsafe-deep-dive/setup.md +msgid "" +"```console\n" +"$ git clone --depth=1 https://github.com/google/comprehensive-rust.git\n" +"Cloning into 'comprehensive-rust'...\n" +"...\n" +"$ cd comprehensive-rust\n" +"$ cargo install-tools\n" +"...\n" +"$ cargo serve # then open http://127.0.0.1:3000/ in a browser\n" +"```" msgstr "" -#: src/bare-metal/microcontrollers/board-support.md +#: src/unsafe-deep-dive/setup.md msgid "" -"Board support crates provide a further level of wrapping for a specific " -"board for convenience." +"Ask everyone to confirm that everyone is able to execute `rustc` with a " +"version newer than 1.87." msgstr "" -#: src/bare-metal/microcontrollers/board-support.md +#: src/unsafe-deep-dive/setup.md msgid "" -"In this case the board support crate is just providing more useful names, " -"and a bit of initialisation." +"For those people who do not, tell them that we'll resolve that in the break." msgstr "" -#: src/bare-metal/microcontrollers/board-support.md +#: src/unsafe-deep-dive/introduction.md msgid "" -"The crate may also include drivers for some on-board devices outside of the " -"microcontroller itself." +"We'll start our course by creating a shared understanding of what Unsafe " +"Rust is and what the `unsafe` keyword does." msgstr "" -#: src/bare-metal/microcontrollers/board-support.md -msgid "`microbit-v2` includes a simple driver for the LED matrix." +#: src/unsafe-deep-dive/introduction.md src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "Outline" msgstr "" -#: src/bare-metal/microcontrollers/type-state.md -msgid "The type state pattern" +#: src/unsafe-deep-dive/introduction.md +msgid "25 minutes" msgstr "" -#: src/bare-metal/microcontrollers/type-state.md -msgid "// let gpio0_01_again = gpio0.p0_01; // Error, moved.\n" +#: src/unsafe-deep-dive/introduction/definition.md +msgid "“Unsafe Rust is a superset of Safe Rust.”" msgstr "" -#: src/bare-metal/microcontrollers/type-state.md -msgid "// ...\n" +#: src/unsafe-deep-dive/introduction/definition.md +msgid "" +"“Unsafe Rust adds extra capabilities, such as allowing you to dereference " +"raw pointers and call functions that can break Rust’s safety guarantees if " +"called incorrectly.”" msgstr "" -#: src/bare-metal/microcontrollers/type-state.md -msgid "// pin_input.is_high(); // Error, moved.\n" +#: src/unsafe-deep-dive/introduction/definition.md +msgid "“These extra capabilities are referred to as _unsafe operations_.”" msgstr "" -#: src/bare-metal/microcontrollers/type-state.md +#: src/unsafe-deep-dive/introduction/definition.md msgid "" -"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." +"“Unsafe operations provide the foundation that the Rust standard library is " +"built on. For example, without the ability to dereference a raw pointer, it " +"would be impossible to implement `Vec` or `Box`.”" msgstr "" -#: src/bare-metal/microcontrollers/type-state.md +#: src/unsafe-deep-dive/introduction/definition.md msgid "" -"Changing the configuration of a pin consumes the old pin instance, so you " -"can’t keep use the old instance afterwards." +"“The compiler will still assist you while writing Unsafe Rust. Borrow " +"checking and type safety still apply. Unsafe operations have their own " +"rules, which we’ll learn about in this class.”" msgstr "" -#: src/bare-metal/microcontrollers/type-state.md +#: src/unsafe-deep-dive/introduction/definition.md msgid "" -"The type of a value indicates the state that 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 without properly configuring it first. Illegal state transitions are " -"caught at compile time." +"The unsafe operations from the [Rust Reference](https://doc.rust-lang.org/" +"reference/unsafety.html) (Avoid spending too much time):" msgstr "" -#: src/bare-metal/microcontrollers/type-state.md +#: src/unsafe-deep-dive/introduction/definition.md msgid "" -"You can call `is_high` on an input pin and `set_high` on an output pin, but " -"not vice-versa." +"The following language level features cannot be used in the safe subset of " +"Rust:" msgstr "" -#: src/bare-metal/microcontrollers/type-state.md -msgid "Many HAL crates follow this pattern." +#: src/unsafe-deep-dive/introduction/definition.md +msgid "Dereferencing a raw pointer." msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md +#: src/unsafe-deep-dive/introduction/definition.md +msgid "Reading or writing a mutable or unsafe external static variable." +msgstr "" + +#: src/unsafe-deep-dive/introduction/definition.md +msgid "Accessing a field of a union, other than to assign to it." +msgstr "" + +#: src/unsafe-deep-dive/introduction/definition.md +msgid "Calling an `unsafe` function." +msgstr "" + +#: src/unsafe-deep-dive/introduction/definition.md msgid "" -"The [`embedded-hal`](https://crates.io/crates/embedded-hal) crate provides a " -"number of traits covering common microcontroller peripherals." +"Calling a safe function marked with a `` from a function " +"that does not have a `` attribute enabling the same features." msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md -msgid "GPIO" +#: src/unsafe-deep-dive/introduction/definition.md +msgid "Implementing an unsafe trait." msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md -msgid "ADC" +#: src/unsafe-deep-dive/introduction/definition.md +msgid "Declaring an extern block." msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md -msgid "I2C, SPI, UART, CAN" +#: src/unsafe-deep-dive/introduction/definition.md +msgid "Applying an unsafe attribute to an item." msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md -msgid "RNG" +#: src/unsafe-deep-dive/introduction/purpose.md +msgid "Why the unsafe keyword exists" msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md -msgid "Timers" +#: src/unsafe-deep-dive/introduction/purpose.md +msgid "Rust ensures safety" msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md -msgid "Watchdogs" +#: src/unsafe-deep-dive/introduction/purpose.md +msgid "But there are limits to what the compiler can do" msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md +#: src/unsafe-deep-dive/introduction/purpose.md msgid "" -"Other crates then implement [drivers](https://github.com/rust-embedded/" -"awesome-embedded-rust#driver-crates) in terms of these traits, e.g. an " -"accelerometer driver might need an I2C or SPI bus implementation." +"The unsafe keyword allows programmers to assume responsibility for Rust’s " +"rules" msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md -msgid "" -"There are implementations for many microcontrollers, as well as other " -"platforms such as Linux on Raspberry Pi." +#: src/unsafe-deep-dive/introduction/purpose.md +msgid "“A fundamental goal of Rust is to ensure memory safety.”" msgstr "" -#: src/bare-metal/microcontrollers/embedded-hal.md +#: src/unsafe-deep-dive/introduction/purpose.md msgid "" -"There is work in progress on an `async` version of `embedded-hal`, but it " -"isn't stable yet." +"“But, there are limits. Some safety considerations cannot be expressed in a " +"programming language. Even if they could be, there are limits to what the " +"Rust compiler can control.”" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md +#: src/unsafe-deep-dive/introduction/purpose.md msgid "" -"[probe-rs](https://probe.rs/) is a handy toolset for embedded debugging, " -"like OpenOCD but better integrated." +"“The `unsafe` keyword shifts the burden of upholding Rust’s rules from the " +"compiler to the programmer.”" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md +#: src/unsafe-deep-dive/introduction/purpose.md msgid "" -"SWD (Serial Wire Debug) and JTAG via CMSIS-DAP, ST-Link and J-Link probes" +"“When you see the `unsafe` keyword, you are seeing responsibility shift from " +"the compiler to the programmer." msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md -msgid "GDB stub and Microsoft DAP (Debug Adapter Protocol) server" +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "The unsafe keyword has two roles" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md -msgid "Cargo integration" +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "_Creating_ APIs with safety considerations" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md -msgid "" -"`cargo-embed` is a cargo subcommand to build and flash binaries, log RTT " -"(Real Time Transfers) output and connect GDB. It's configured by an `Embed." -"toml` file in your project directory." +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "unsafe functions: `unsafe fn get_unchecked(&self) { ... }`" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "unsafe traits: `unsafe trait Send {}`" +msgstr "" + +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "_Using_ APIs with safety considerations" +msgstr "" + +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "invoking built-in unsafe operators: `unsafe { *ptr }`" +msgstr "" + +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "calling unsafe functions: `unsafe { x.get_unchecked() }`" +msgstr "" + +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "implementing unsafe traits: `unsafe impl Send for Counter {}`" +msgstr "" + +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "Two roles:" +msgstr "" + +#: src/unsafe-deep-dive/introduction/two-roles.md msgid "" -"[CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) is " -"an Arm standard protocol over USB for an in-circuit debugger to access the " -"CoreSight Debug Access Port of various Arm Cortex processors. It's what the " -"on-board debugger on the BBC micro:bit uses." +"**Creating** APIs with safety considerations and defining what needs to be " +"considered" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md +#: src/unsafe-deep-dive/introduction/two-roles.md msgid "" -"ST-Link is a range of in-circuit debuggers from ST Microelectronics, J-Link " -"is a range from SEGGER." +"**Using** APIs with safety considerations and confirming that the " +"consideration has been made" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "Creating APIs with safety considerations" +msgstr "" + +#: src/unsafe-deep-dive/introduction/two-roles.md msgid "" -"The Debug Access Port is usually either a 5-pin JTAG interface or 2-pin " -"Serial Wire Debug." +"“First, the unsafe keyword enables you to create APIs that can break Rust’s " +"safety guarantees. Specifically, you need to use the unsafe keyword when " +"defining unsafe functions and unsafe traits." msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md +#: src/unsafe-deep-dive/introduction/two-roles.md msgid "" -"probe-rs is a library which you can integrate into your own tools if you " -"want to." +"“When used in this role, you’re informing users of your API that they need " +"to be careful.”" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md +#: src/unsafe-deep-dive/introduction/two-roles.md msgid "" -"The [Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-" -"adapter-protocol/) lets VSCode and other IDEs debug code running on any " -"supported microcontroller." +"“The creator of the API should communicate what care needs to be taken. " +"Unsafe APIs are not complete without documentation about safety " +"requirements. Callers need to know that they have satisfied any " +"requirements, and that’s impossible if they’re not written down.”" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md -msgid "cargo-embed is a binary built using the probe-rs library." +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "Using APIs with safety considerations" msgstr "" -#: src/bare-metal/microcontrollers/probe-rs.md +#: src/unsafe-deep-dive/introduction/two-roles.md msgid "" -"RTT (Real Time Transfers) is a mechanism to transfer data between the debug " -"host and the target through a number of ringbuffers." +"“The unsafe keyword adopts its other role, using APIs, when it is used " +"nearby to a curly brace." msgstr "" -#: src/bare-metal/microcontrollers/debugging.md -msgid "_Embed.toml_:" +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "" +"“When used in this role, the unsafe keyword means that the author has been " +"careful. They have verified that the code is safe and is providing an " +"assurance to others.”" msgstr "" -#: src/bare-metal/microcontrollers/debugging.md -msgid "In one terminal under `src/bare-metal/microcontrollers/examples/`:" +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "" +"“Unsafe blocks are most common. They allow you to invoke unsafe functions " +"that have been defined using the first role." msgstr "" -#: src/bare-metal/microcontrollers/debugging.md -msgid "In another terminal in the same directory:" +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "" +"“Unsafe blocks also allow you to perform operations which the compiler knows " +"are unsafe, such as dereferencing a raw pointer.”" msgstr "" -#: src/bare-metal/microcontrollers/debugging.md -msgid "On gLinux or Debian:" +#: src/unsafe-deep-dive/introduction/two-roles.md +msgid "" +"“You might also see the unsafe keyword being used to implement unsafe traits." msgstr "" -#: src/bare-metal/microcontrollers/debugging.md -msgid "In GDB, try running:" +#: src/unsafe-deep-dive/introduction/warm-up.md +msgid "Warm-up examples" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -#: src/bare-metal/aps/other-projects.md -msgid "Other projects" +#: src/unsafe-deep-dive/introduction/warm-up.md +msgid "Examples to demonstrate:" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "[RTIC](https://rtic.rs/)" +#: src/unsafe-deep-dive/introduction/warm-up.md +msgid "using an [unsafe block](warm-up/unsafe-block.md) (`unsafe { ... }`)" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "\"Real-Time Interrupt-driven Concurrency\"" +#: src/unsafe-deep-dive/introduction/warm-up.md +msgid "defining an [unsafe function](warm-up/unsafe-fn.md) (`unsafe fn`)" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md +#: src/unsafe-deep-dive/introduction/warm-up.md msgid "" -"Shared resource management, message passing, task scheduling, timer queue" +"[implementing](warm-up/unsafe-impl.md) an unsafe trait (`unsafe impl { ... }" +"`)" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "[Embassy](https://embassy.dev/)" +#: src/unsafe-deep-dive/introduction/warm-up.md +msgid "defining an [unsafe trait](warm-up/unsafe-trait.md) (`unsafe trait`)" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "`async` executors with priorities, timers, networking, USB" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-trait.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-useful.md +#: src/unsafe-deep-dive/introduction/may_overflow.md +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +#: src/unsafe-deep-dive/safety-preconditions/getter.md +#: src/unsafe-deep-dive/safety-preconditions/determining.md +#: src/unsafe-deep-dive/safety-preconditions/references.md +#: src/unsafe-deep-dive/safety-preconditions/ascii.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/crying-wolf.md +#: src/unsafe-deep-dive/initialization/maybeuninit.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md +#: src/unsafe-deep-dive/initialization/maybeuninit/zeroed-method.md +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +#: src/unsafe-deep-dive/initialization/partial-initialization.md +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +#: src/unsafe-deep-dive/pinning/definition-of-pin.md +#: src/unsafe-deep-dive/pinning/phantompinned.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-offset.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-pin.md +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md +#: src/unsafe-deep-dive/ffi/abs.md src/unsafe-deep-dive/ffi/rand.md +#: src/unsafe-deep-dive/ffi/c-library-example.md +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "// Copyright 2026 Google LLC\n" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "[TockOS](https://www.tockos.org/documentation/getting-started)" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md +msgid "" +"Walk through the code. Confirm that the audience is familiar with the " +"dereference operator." msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "" -"Security-focused RTOS with preemptive scheduling and Memory Protection Unit " -"support" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md +msgid "Attempt to compile the code, trigger the compiler error." msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "[Hubris](https://hubris.oxide.computer/)" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md +msgid "Add the unsafe block:" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md msgid "" -"Microkernel RTOS from Oxide Computer Company with memory protection, " -"unprivileged drivers, IPC" +"Prompt audience for a code review. Guide learners towards adding a safety " +"comment." msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "[Bindings for FreeRTOS](https://github.com/lobaro/FreeRTOS-rust)" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md +msgid "Add the safety comment:" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "" -"Some platforms have `std` implementations, e.g. [esp-idf](https://esp-rs." -"github.io/book/overview/using-the-standard-library.html)." +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md +msgid "// SAFETY: `i` must be within 0..numbers.len()\n" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "RTIC can be considered either an RTOS or a concurrency framework." +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-block.md +#: src/unsafe-deep-dive/safety-preconditions/references.md +#: src/unsafe-deep-dive/ffi/c-library-example.md +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "_Suggested Solution_" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "It doesn't include any HALs." +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md +msgid "" +"/// Convert a nullable pointer to a reference.\n" +"///\n" +"/// Returns `None` when `p` is null, otherwise wraps `val` in `Some`.\n" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md +msgid "// SAFETY: `ptr` is non-null\n" +msgstr "" + +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md msgid "" -"It uses the Cortex-M NVIC (Nested Virtual Interrupt Controller) for " -"scheduling rather than a proper kernel." +"“This looks as though it’s safe code, however it actually requires an unsafe " +"block.”" msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md -msgid "Cortex-M only." +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md +msgid "Highlight the dereference operation, i.e. `*p` within the unsafe block." msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md msgid "" -"Google uses TockOS on the Haven microcontroller for Titan security keys." +"“Callers must ensure that the `ptr` is null, or that it may be converted to " +"a reference." msgstr "" -#: src/bare-metal/microcontrollers/other-projects.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md msgid "" -"FreeRTOS is mostly written in C, but there are Rust bindings for writing " -"applications." +"“It may be counter-intuitive, but many pointers cannot be converted to " +"references." msgstr "" -#: src/exercises/bare-metal/morning.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md msgid "" -"We will read the direction from an I2C compass, and log the readings to a " -"serial port." +"“Among other issues, a pointer could be created that points to some " +"arbitrary bits rather than a valid value. That’s not something that Rust " +"allows and something that this function needs to protect itself against." msgstr "" -#: src/exercises/bare-metal/morning.md src/exercises/concurrency/morning.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md msgid "" -"After looking at the exercises, you can look at the [solutions](solutions-" -"morning.md) provided." +"“So we, as API designers, have two paths. We can either try to assume " +"responsibility for guarding against invalid inputs, or we can shift that " +"responsibility to the caller with the unsafe keyword.”" msgstr "" -#: src/exercises/bare-metal/compass.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md msgid "" -"We will read the direction from an I2C compass, and log the readings to a " -"serial port. If you have time, try displaying it on the LEDs somehow too, or " -"use the buttons somehow." +"“The first path is a difficult one. We’re accepting a generic type T, which " +"is all possible types that implement Sized. That’s a lot of types!" msgstr "" -#: src/exercises/bare-metal/compass.md -msgid "Hints:" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md +msgid "“Therefore, the second path makes more sense." msgstr "" -#: src/exercises/bare-metal/compass.md -msgid "" -"Check the documentation for the [`lsm303agr`](https://docs.rs/lsm303agr/" -"latest/lsm303agr/) and [`microbit-v2`](https://docs.rs/microbit-v2/latest/" -"microbit/) crates, as well as the [micro:bit hardware](https://tech.microbit." -"org/hardware/)." +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md +msgid "_Extra content (time permitting)_" msgstr "" -#: src/exercises/bare-metal/compass.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md msgid "" -"The LSM303AGR Inertial Measurement Unit is connected to the internal I2C bus." +"“By the way, if you’re interested in the details of pointers and what the " +"rules of converting them to references are, the standard library has a lot " +"of useful documentation. You should also look into the source code of many " +"of the methods on std::pointer." msgstr "" -#: src/exercises/bare-metal/compass.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md msgid "" -"TWI is another name for I2C, so the I2C master peripheral is called TWIM." +"“For example, the `ptr_to_ref` function on this slide actually exists in the " +"standard library as the `as_mut` method on pointers.”" msgstr "" -#: src/exercises/bare-metal/compass.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-fn.md msgid "" -"The LSM303AGR driver needs something implementing the `embedded_hal::" -"blocking::i2c::WriteRead` trait. The [`microbit::hal::Twim`](https://docs.rs/" -"microbit-v2/latest/microbit/hal/struct.Twim.html) struct implements this." +"Open the documentation for [std::pointer.as_mut](https://doc.rust-lang.org/" +"std/primitive.pointer.html#method.as_mut) and highlight the Safety section." msgstr "" -#: src/exercises/bare-metal/compass.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md msgid "" -"You have a [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/" -"struct.Board.html) struct with fields for the various pins and peripherals." +"“Before we take a look at the code, we should double check that everyone " +"knows what a trait is. Is anyone able to explain traits for the rest of the " +"class?" msgstr "" -#: src/exercises/bare-metal/compass.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md msgid "" -"You can also look at the [nRF52833 datasheet](https://infocenter.nordicsemi." -"com/pdf/nRF52833_PS_v1.5.pdf) if you want, but it shouldn't be necessary for " -"this exercise." +"“Traits are often described as a way to create shared behavior. Thinking " +"about traits as shared behavior focuses on the syntax of methods and their " +"signatures." msgstr "" -#: src/exercises/bare-metal/compass.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md msgid "" -"Download the [exercise template](../../comprehensive-rust-exercises.zip) and " -"look in the `compass` directory for the following files." -msgstr "" - -#: src/exercises/bare-metal/compass.md src/exercises/bare-metal/rtc.md -msgid "_src/main.rs_:" +"“There’s also a deeper way to think of traits: as sets of requirements. This " +"emphasizes the shared semantics of the implementing types." msgstr "" -#: src/exercises/bare-metal/compass.md src/exercises/bare-metal/rtc.md -msgid "_Cargo.toml_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md +msgid "“Can anyone explain what the `Send` and `Sync` traits are?" msgstr "" -#: src/exercises/bare-metal/compass.md -msgid "_Embed.toml_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md +msgid "If no" msgstr "" -#: src/exercises/bare-metal/compass.md src/exercises/bare-metal/rtc.md -msgid "_.cargo/config.toml_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md +msgid "" +"“Send and Sync relate to concurrency. There are many details, but broadly " +"speaking, Send types can be shared between threads by value. Sync types must " +"be shared by reference." msgstr "" -#: src/exercises/bare-metal/compass.md -msgid "See the serial output on Linux with:" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md +msgid "" +"There are many rules to follow to ensure that it’s safe to share data across " +"thread boundaries. Those rules cannot be checked by the compiler, and " +"therefore the code author must take responsibility for upholding them." msgstr "" -#: src/exercises/bare-metal/compass.md +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md msgid "" -"Or on Mac OS something like (the device name may be slightly different):" +"Arc implements Send and Sync, therefore it’s safe for our clock to as well." msgstr "" -#: src/exercises/bare-metal/compass.md -msgid "Use Ctrl+A Ctrl+Q to quit picocom." +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-impl.md +msgid "" +"It may be useful to point out that the word _atomic_ has the meaning of " +"“indivisible” or “whole” from Ancient Greek, rather than the contemporary " +"English sense of “tiny particle”." msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "Bare Metal Rust Morning Exercise" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-trait.md +msgid "/// Indicates that the type uses 32 bits of memory.\n" msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "([back to exercise](compass.md))" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-trait.md +msgid "“Now let’s define our own unsafe trait.”" msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "// Configure serial port.\n" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-trait.md +msgid "Add the unsafe keyword and compile the code." msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "// Use the system timer as a delay provider.\n" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-trait.md +msgid "" +"“If the requirements of the trait are semantic, then your trait may not need " +"any methods at all. The documentation is essential, however.”" msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "// Set up the I2C controller and Inertial Measurement Unit.\n" +#: src/unsafe-deep-dive/introduction/warm-up/unsafe-trait.md +msgid "" +"“Traits without methods are called marker traits. When implementing them for " +"types, you are adding information to the type system. You have now given the " +"compiler the ability to talk about types that meet the requirements " +"described in the documentation.”" msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "\"Setting up IMU...\"" +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust.md +msgid "Characteristics of unsafe" msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "// Set up display and timer.\n" +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust.md +msgid "[Dangerous](characteristics-of-unsafe-rust/dangerous.md)" msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "\"Ready.\"" +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust.md +msgid "" +"[Sometimes necessary](characteristics-of-unsafe-rust/sometimes-necessary.md)" msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "// Read compass data and log it to the serial port.\n" +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust.md +msgid "[Sometimes useful](characteristics-of-unsafe-rust/sometimes-useful.md)" msgstr "" -#: src/exercises/bare-metal/solutions-morning.md -msgid "\"{},{},{}\\t{},{},{}\"" +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/dangerous.md +msgid "Unsafe is dangerous" msgstr "" -#: src/exercises/bare-metal/solutions-morning.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/dangerous.md msgid "" -"// If button A is pressed, switch to the next mode and briefly blink all " -"LEDs\n" -" // on.\n" +"“Use-after-free (UAF), integer overflows, and out of bounds (OOB) reads/" +"writes comprise 90% of vulnerabilities with OOB being the most common.”" msgstr "" -#: src/bare-metal/aps.md -msgid "Application processors" +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/dangerous.md +msgid "" +"\\--- **Jeff Vander Stoep and Chong Zang**, Google. \"[Queue the Hardening " +"Enhancements](https://security.googleblog.com/2019/05/queue-hardening-" +"enhancements.html)\"" msgstr "" -#: src/bare-metal/aps.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/dangerous.md msgid "" -"So far we've talked about microcontrollers, such as the Arm Cortex-M series. " -"Now let's try writing something for Cortex-A. For simplicity we'll just work " -"with QEMU's aarch64 ['virt'](https://qemu-project.gitlab.io/qemu/system/arm/" -"virt.html) board." +"“The software industry has gathered lots of evidence that unsafe code is " +"difficult to write correctly and creates very serious problems.”" msgstr "" -#: src/bare-metal/aps.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/dangerous.md msgid "" -"Broadly speaking, microcontrollers don't have an MMU or multiple levels of " -"privilege (exception levels on Arm CPUs, rings on x86), while application " -"processors do." +"“The issues in this list are eliminated by Rust. The unsafe keyword lets " +"them back into your source code.”" msgstr "" -#: src/bare-metal/aps.md -msgid "" -"QEMU supports emulating various different machines or board models for each " -"architecture. The 'virt' board doesn't correspond to any particular real " -"hardware, but is designed purely for virtual machines." +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/dangerous.md +msgid "“Be careful.”" msgstr "" -#: src/bare-metal/aps/entry-point.md -msgid "" -"Before we can start running Rust code, we need to do some initialisation." +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md +msgid "Unsafe is sometimes necessary" msgstr "" -#: src/bare-metal/aps/entry-point.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md msgid "" -"```armasm\n" -".section .init.entry, \"ax\"\n" -".global entry\n" -"entry:\n" -" /*\n" -" * Load and apply the memory management configuration, ready to enable " -"MMU and\n" -" * caches.\n" -" */\n" -" adrp x30, idmap\n" -" msr ttbr0_el1, x30\n" -"\n" -" mov_i x30, .Lmairval\n" -" msr mair_el1, x30\n" -"\n" -" mov_i x30, .Ltcrval\n" -" /* Copy the supported PA range into TCR_EL1.IPS. */\n" -" mrs x29, id_aa64mmfr0_el1\n" -" bfi x30, x29, #32, #4\n" -"\n" -" msr tcr_el1, x30\n" -"\n" -" mov_i x30, .Lsctlrval\n" -"\n" -" /*\n" -" * Ensure everything before this point has completed, then invalidate " -"any\n" -" * potentially stale local TLB entries before they start being used.\n" -" */\n" -" isb\n" -" tlbi vmalle1\n" -" ic iallu\n" -" dsb nsh\n" -" isb\n" -"\n" -" /*\n" -" * Configure sctlr_el1 to enable MMU and cache and don't proceed until " -"this\n" -" * has completed.\n" -" */\n" -" msr sctlr_el1, x30\n" -" isb\n" -"\n" -" /* Disable trapping floating point access in EL1. */\n" -" mrs x30, cpacr_el1\n" -" orr x30, x30, #(0x3 << 20)\n" -" msr cpacr_el1, x30\n" -" isb\n" -"\n" -" /* Zero out the bss section. */\n" -" adr_l x29, bss_begin\n" -" adr_l x30, bss_end\n" -"0: cmp x29, x30\n" -" b.hs 1f\n" -" stp xzr, xzr, [x29], #16\n" -" b 0b\n" -"\n" -"1: /* Prepare the stack. */\n" -" adr_l x30, boot_stack_end\n" -" mov sp, x30\n" -"\n" -" /* Set up exception vector. */\n" -" adr x30, vector_table_el1\n" -" msr vbar_el1, x30\n" -"\n" -" /* Call into Rust code. */\n" -" bl main\n" -"\n" -" /* Loop forever waiting for interrupts. */\n" -"2: wfi\n" -" b 2b\n" -"```" +"The Rust compiler can only enforce its rules for code that it has compiled." msgstr "" -#: src/bare-metal/aps/entry-point.md -msgid "" -"This is the same as it would be for C: initialising the processor state, " -"zeroing the BSS, and setting up the stack pointer." +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md +msgid "\"{pid}\"" msgstr "" -#: src/bare-metal/aps/entry-point.md -msgid "" -"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 " -"on zeroes. The compiler assumes that the loader will take care of zeroing " -"them." +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md +msgid "“There are some activities that _require_ unsafe." msgstr "" -#: src/bare-metal/aps/entry-point.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md msgid "" -"The BSS may already be zeroed, depending on how memory is initialised and " -"the image is loaded, but we zero it to be sure." +"“The Rust compiler cannot verify that external functions comply with Rust's " +"memory guarantees. Therefore, invoking external functions requires an unsafe " +"block.”" msgstr "" -#: src/bare-metal/aps/entry-point.md -msgid "" -"We need to enable the MMU and cache before reading or writing any memory. If " -"we don't:" +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md +msgid "Optional:" msgstr "" -#: src/bare-metal/aps/entry-point.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md msgid "" -"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." +"“Working with the external environment often involves sharing memory. The " +"interface that computers provide is a memory address (a pointer).”" msgstr "" -#: src/bare-metal/aps/entry-point.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md msgid "" -"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 " -"doesn't explicitly access the memory, speculative accesses can lead to cache " -"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.)" +"“Here's an example that asks the Linux kernel to write to memory that we " +"control:" msgstr "" -#: src/bare-metal/aps/entry-point.md -msgid "" -"For simplicity, we just use a hardcoded pagetable (see `idmap.S`) which " -"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." +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md +msgid "\"{buf:?}\"" msgstr "" -#: src/bare-metal/aps/entry-point.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-necessary.md msgid "" -"We also set up the exception vector (`vbar_el1`), which we'll see more about " -"later." +"“This FFI call reaches into the operating system to fill our buffer (`buf`). " +"As well as calling an external function, we must mark the boundary as " +"`unsafe` because the compiler cannot verify how the OS touches that memory.”" msgstr "" -#: src/bare-metal/aps/entry-point.md -msgid "" -"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." +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-useful.md +msgid "Unsafe is sometimes useful" +msgstr "" + +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-useful.md +msgid "Your code can go faster!" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "Inline assembly" +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-useful.md +msgid "Code using `unsafe` _might_ be faster." msgstr "" -#: src/bare-metal/aps/inline-assembly.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-useful.md msgid "" -"Sometimes we need to use assembly to do things that aren't possible with " -"Rust code. For example, to make an HVC (hypervisor call) to tell the " -"firmware to power off the system:" +"`fast_sum()` skips bounds checks. However, benchmarking is necessary to " +"validate performance claims. For cases like this, Rust's iterators can " +"usually elide bounds checks anyway." msgstr "" -#: src/bare-metal/aps/inline-assembly.md +#: src/unsafe-deep-dive/introduction/characteristics-of-unsafe-rust/sometimes-useful.md msgid "" -"// Safe because this only uses the declared registers and doesn't do\n" -" // anything with memory.\n" +"Optional: [show identical generated assembly](https://rust.godbolt.org/z/" +"d48v1Y5aj) for the two functions." msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "\"hvc #0\"" +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +msgid "Unsafe keyword shifts responsibility" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "\"w0\"" +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +msgid "Is Memory Safe?" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "\"w1\"" +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +msgid "Responsibility for Memory Safety" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "\"w2\"" +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +msgid "Compiler" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "\"w3\"" +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +msgid "Programmer" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "\"w4\"" +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +msgid "Who has responsibility for memory safety?" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "\"w5\"" +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +msgid "Safe Rust → compiler" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "\"w6\"" +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +msgid "Unsafe Rust → programmer" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "\"w7\"" +#: src/unsafe-deep-dive/introduction/responsibility-shift.md +msgid "" +"“While writing safe Rust, you cannot create memory safety problems. The " +"compiler will ensure that a program with mistakes will not build.”" msgstr "" -#: src/bare-metal/aps/inline-assembly.md +#: src/unsafe-deep-dive/introduction/responsibility-shift.md msgid "" -"(If you actually want to do this, use the [`smccc`](https://crates.io/crates/" -"smccc) crate which has wrappers for all these functions.)" +"“The `unsafe` keyword shifts responsibility for maintaining memory safety " +"from the compiler to programmers. It signals that there are preconditions " +"that must be satisfied." msgstr "" -#: src/bare-metal/aps/inline-assembly.md +#: src/unsafe-deep-dive/introduction/responsibility-shift.md msgid "" -"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." +"“To uphold that responsibility, programmers must ensure that they've " +"understood what the preconditions are and that their code will always " +"satisfy them." msgstr "" -#: src/bare-metal/aps/inline-assembly.md +#: src/unsafe-deep-dive/introduction/responsibility-shift.md msgid "" -"The `0 => _` syntax means initialise 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." +"“Throughout this course, we'll use the term _safety preconditions_ to " +"describe this situation.”" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "" -"This `main` function needs to be `#[no_mangle]` and `extern \"C\"` because " -"it is called from our entry point in `entry.S`." +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md +msgid "Impact on workflow" msgstr "" -#: src/bare-metal/aps/inline-assembly.md -msgid "" -"`_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. " -"According to the standard aarch64 calling convention (which is what `extern " -"\"C\"` specifies to use), registers `x0`–`x7` are used for the first 8 " -"arguments passed to a function, so `entry.S` doesn't need to do anything " -"special except make sure it doesn't change these registers." +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md +msgid "While writing code" msgstr "" -#: src/bare-metal/aps/inline-assembly.md +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md msgid "" -"Run the example in QEMU with `make qemu_psci` under `src/bare-metal/aps/" -"examples`." +"Verify that you understand the preconditions of any `unsafe` functions/traits" msgstr "" -#: src/bare-metal/aps/mmio.md -msgid "Volatile memory access for MMIO" +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md +msgid "Check that the preconditions are satisfied" msgstr "" -#: src/bare-metal/aps/mmio.md -msgid "Use `pointer::read_volatile` and `pointer::write_volatile`." +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md +msgid "Document your reasoning in safety comments" msgstr "" -#: src/bare-metal/aps/mmio.md -msgid "Never hold a reference." +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md +msgid "Enhanced code review" msgstr "" -#: src/bare-metal/aps/mmio.md -msgid "" -"`addr_of!` lets you get fields of structs without creating an intermediate " -"reference." +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md +msgid "Self-review → peer reviewer → unsafe Rust expert (when needed)" msgstr "" -#: src/bare-metal/aps/mmio.md +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md +msgid "Escalate to a person who is comfortable with your code and reasoning" +msgstr "" + +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md msgid "" -"Volatile access: read or write operations may have side-effects, so prevent " -"the compiler or hardware from reordering, duplicating or eliding them." +"“The unsafe keyword places more responsibility on the programmer; therefore " +"it requires a stronger development workflow." msgstr "" -#: src/bare-metal/aps/mmio.md +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md msgid "" -"Usually if you write and then read, e.g. via a mutable reference, the " -"compiler may assume that the value read is the same as the value just " -"written, and not bother actually reading memory." +"“This class assumes a specific software development workflow where code " +"review is mandatory, and where the author and primary reviewer have access " +"to an unsafe Rust expert.”" msgstr "" -#: src/bare-metal/aps/mmio.md +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md msgid "" -"Some existing crates for volatile access to hardware do hold references, but " -"this is unsound. Whenever a reference exist, the compiler may choose to " -"dereference it." +"“The author and primary reviewer will verify simple unsafe Rust code " +"themselves, and punt to an unsafe expert when necessary.”" msgstr "" -#: src/bare-metal/aps/mmio.md +#: src/unsafe-deep-dive/introduction/impact-on-workflow.md msgid "" -"Use the `addr_of!` macro to get struct field pointers from a pointer to the " -"struct." +"“There are only a few unsafe Rust experts, and they are very busy, so we " +"need to optimally use their time.”" msgstr "" -#: src/bare-metal/aps/uart.md -msgid "Let's write a UART driver" +#: src/unsafe-deep-dive/introduction/may_overflow.md +msgid "Example: may_overflow function" msgstr "" -#: src/bare-metal/aps/uart.md -msgid "" -"The QEMU 'virt' machine has a [PL011](https://developer.arm.com/" -"documentation/ddi0183/g) UART, so let's write a driver for that." +#: src/unsafe-deep-dive/introduction/may_overflow.md +msgid "/// Adds 2^31 - 1 to negative numbers.\n" msgstr "" -#: src/bare-metal/aps/uart.md -msgid "/// Minimal driver for a PL011 UART.\n" +#: src/unsafe-deep-dive/introduction/may_overflow.md +msgid "\"{x}\"" msgstr "" -#: src/bare-metal/aps/uart.md src/bare-metal/aps/better-uart/driver.md +#: src/unsafe-deep-dive/introduction/may_overflow.md msgid "" -"/// Constructs a new instance of the UART driver for a PL011 device at the\n" -" /// given base address.\n" -" ///\n" -" /// # Safety\n" -" ///\n" -" /// The given base address must point to the 8 MMIO control registers of " -"a\n" -" /// PL011 device, which must be mapped into the address space of the " -"process\n" -" /// as device memory and not have any other aliases.\n" +"“The `unsafe` keyword may have a subtly different meaning than what some " +"people assume.”" msgstr "" -#: src/bare-metal/aps/uart.md src/bare-metal/aps/better-uart/driver.md -msgid "/// Writes a single byte to the UART.\n" +#: src/unsafe-deep-dive/introduction/may_overflow.md +msgid "" +"“The code author believes that the code is correct. In principle, the code " +"is safe.”" msgstr "" -#: src/bare-metal/aps/uart.md src/bare-metal/aps/better-uart/driver.md -msgid "// Wait until there is room in the TX buffer.\n" +#: src/unsafe-deep-dive/introduction/may_overflow.md +msgid "" +"“In this toy example, the `may_overflow` function is only intended to be " +"called with negative numbers." msgstr "" -#: src/bare-metal/aps/uart.md +#: src/unsafe-deep-dive/introduction/may_overflow.md msgid "" -"// Safe because we know that the base address points to the control\n" -" // registers of a PL011 device which is appropriately mapped.\n" +"Ask learners if they can explain why `may_overflow` requires the unsafe " +"keyword." msgstr "" -#: src/bare-metal/aps/uart.md src/bare-metal/aps/better-uart/driver.md -msgid "// Write to the TX buffer.\n" +#: src/unsafe-deep-dive/introduction/may_overflow.md +msgid "" +"“In case you’re unsure what the problem is, let’s pause briefly to explain. " +"An `i32` only has 31 bits available for positive numbers. When an operation " +"produces a result that requires more than 31 bits, then the program is put " +"into an invalid state. And it’s not just a numerical problem. Compilers " +"optimize code on the basis that invalid states are impossible. This causes " +"code paths to be deleted, producing erratic runtime behavior while also " +"introducing security vulnerabilities." msgstr "" -#: src/bare-metal/aps/uart.md src/bare-metal/aps/better-uart/driver.md -msgid "// Wait until the UART is no longer busy.\n" +#: src/unsafe-deep-dive/introduction/may_overflow.md +msgid "" +"Compile and run the code, producing a panic. Then run the example in the " +"playground to run under `--release` mode to trigger UB." msgstr "" -#: src/bare-metal/aps/uart.md +#: src/unsafe-deep-dive/introduction/may_overflow.md msgid "" -"Note that `Uart::new` is unsafe while the other methods are safe. This is " -"because as long as the caller of `Uart::new` guarantees that its safety " -"requirements are met (i.e. that there is only ever one instance of the " -"driver for a given UART, and nothing else aliasing its address space), then " -"it is always safe to call `write_byte` later because we can assume the " -"necessary preconditions." +"“This code can be used correctly, however, improper usage is highly " +"dangerous.”" msgstr "" -#: src/bare-metal/aps/uart.md +#: src/unsafe-deep-dive/introduction/may_overflow.md msgid "" -"We could have done it the other way around (making `new` safe but " -"`write_byte` unsafe), but that would be much less convenient to use as every " -"place that calls `write_byte` would need to reason about the safety" +"“And it's impossible for the compiler to verify that the usage is correct.”" msgstr "" -#: src/bare-metal/aps/uart.md +#: src/unsafe-deep-dive/introduction/may_overflow.md msgid "" -"This is a common pattern for writing safe wrappers of unsafe code: moving " -"the burden of proof for soundness from a large number of places to a smaller " -"number of places." +"This is what we mean when we say that the `unsafe` keyword marks the " +"location where responsibility for memory safety shifts from the compiler to " +"the programmer." msgstr "" -#: src/bare-metal/aps/uart/traits.md -msgid "More traits" +#: src/unsafe-deep-dive/safety-preconditions.md +msgid "" +"Safety preconditions are conditions on an action that must be satisfied " +"before that action will be safe." msgstr "" -#: src/bare-metal/aps/uart/traits.md +#: src/unsafe-deep-dive/safety-preconditions.md +#: src/unsafe-deep-dive/safety-preconditions/getter.md msgid "" -"We derived the `Debug` trait. It would be useful to implement a few more " -"traits too." +"“Safety preconditions are conditions on code that must be satisfied to " +"maintain Rust's safety guarantees" msgstr "" -#: src/bare-metal/aps/uart/traits.md -#: src/exercises/bare-metal/solutions-afternoon.md +#: src/unsafe-deep-dive/safety-preconditions.md +#: src/unsafe-deep-dive/safety-preconditions/getter.md msgid "" -"// Safe because it just contains a pointer to device memory, which can be\n" -"// accessed from any context.\n" +"“You're likely to see a strong affinity between safety preconditions and the " +"rules of Safe Rust.”" msgstr "" -#: src/bare-metal/aps/uart/traits.md -msgid "" -"Implementing `Write` lets us use the `write!` and `writeln!` macros with our " -"`Uart` type." +#: src/unsafe-deep-dive/safety-preconditions.md +msgid "Q: Can you list any?" msgstr "" -#: src/bare-metal/aps/uart/traits.md -msgid "" -"Run the example in QEMU with `make qemu_minimal` under `src/bare-metal/aps/" -"examples`." +#: src/unsafe-deep-dive/safety-preconditions.md +msgid "(Fuller list in the next slide)" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "A better UART driver" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Common safety preconditions" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "" -"The PL011 actually has [a bunch more registers](https://developer.arm.com/" -"documentation/ddi0183/g/programmers-model/summary-of-registers), 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." +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Aliasing and Mutability" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "Offset" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Alignment" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "Register name" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Array access is in-bound" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "Width" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Pointer provenance" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x00" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Validity" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "DR" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Memory" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "12" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"Avoid spending too much time explaining every precondition: we will be " +"working through the details during the course. The intent is to show that " +"there are several." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x04" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"\"An incomplete list, but these are a few of the major safety preconditions " +"to get us thinking.\"" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "RSR" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"Validity. Values must be valid values of the type that they represent. " +"Rust's references may not be null. Creating one with `unsafe` causes the." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x18" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Alignment. References to values must be well-aligned, which means th" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "FR" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"Aliasing. All Rust code must uphold Rust's borrowing rules. If you are " +"manually creating mutable references (`&mut T`) from pointers, then you may " +"only create one" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "9" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"Initialization. All instances of Rust types must be fully initialized. To " +"create a value from raw memory, we need to make sure that we've written" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x20" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"Pointer provenance. The origin of a pointer is important. Casting a `usize` " +"to a raw pointer is no longer allowed." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "ILPR" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Lifetimes. References must not outlive their referent." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x24" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Some conditions are even more subtle than they first seem." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "IBRD" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"Consider \"in-bounds array access\". Reading from the memory location, i.e. " +"dereferencing, is not required to break the program. Creating an out-of-" +"bounds reference already breaks the compiler's assumptions, leading to " +"erratic behavior." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "16" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"Rust tells LLVM to use its `getelementptr inbounds` assumption. That " +"assumption will cause later optimization passes within the compiler to " +"misbehave (because out-of-bounds memory access cannot occur)." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x28" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"Optional: open [the playground](https://play.rust-lang.org/?" +"version=stable&mode=release&edition=2024&gist=4116c4de01c863cac918f193448210b1), " +"which shows the code below. Explain that this is essentially a C function " +"written in Rust syntax that gets items from an array. Generate the LLVM IR " +"with the **Show LLVM IR** button. Highlight `getelementptr inbounds i32, ptr " +"%array, i64 %offset`." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "FBRD" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "Expected output (the line to highlight starts with \\`%\\_3):" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x2c" +#: src/unsafe-deep-dive/safety-preconditions/common-preconditions.md +msgid "" +"Bounds: You correctly noted that creating an out-of-bounds pointer (beyond " +"the \"one-past-the-end\" rule) is UB, even without dereferencing, due to " +"LLVM's inbounds assumptions." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "LCR_H" +#: src/unsafe-deep-dive/safety-preconditions/getter.md +msgid "/// Return the element at `index` from `arr`\n" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x30" +#: src/unsafe-deep-dive/safety-preconditions/getter.md +msgid "Ask: “What are the safety preconditions of `get`?”" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "CR" +#: src/unsafe-deep-dive/safety-preconditions/getter.md +msgid "" +"The pointer `arr` is non-null, well-aligned and refers to an array of `i32`" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x34" +#: src/unsafe-deep-dive/safety-preconditions/getter.md +msgid "`index` is in-bounds" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "IFLS" +#: src/unsafe-deep-dive/safety-preconditions/getter.md +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Add safety comments:" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x38" +#: src/unsafe-deep-dive/safety-preconditions/getter.md +msgid "" +"/// Return the element at `index` from `arr`\n" +"///\n" +"/// # Safety\n" +"///\n" +"/// - `arr` is non-null, correctly aligned and points to a valid `i32`\n" +"/// - `index` is in-bounds for the array\n" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "IMSC" +#: src/unsafe-deep-dive/safety-preconditions/getter.md +msgid "// SAFETY: Caller guarantees that index is inbounds\n" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "11" +#: src/unsafe-deep-dive/safety-preconditions/getter.md +msgid "" +"Optional: Add runtime checks can be added in debug builds to provide some " +"extra robustness." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x3c" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "Determining Preconditions" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "RIS" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "Where do you find the safety preconditions?" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x40" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "" +"Attempt to compile the program to trigger the compiler error " +"(\"error\\[E0133\\]: call to unsafe function ...\")." msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "MIS" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "" +"Ask: “Where would you look if you wanted to know the preconditions for a " +"function? Here we need to understand when it's safe to convert from a null " +"pointer to a mutable reference.”" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x44" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "Locations to look:" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "ICR" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "A function's API documentation, especially its safety section" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "0x48" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "The source code and its internal safety comments" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "DMACR" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "Module documentation" msgstr "" -#: src/bare-metal/aps/better-uart.md -msgid "There are also some ID registers which have been omitted for brevity." +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "Rust Reference" msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md +#: src/unsafe-deep-dive/safety-preconditions/determining.md msgid "" -"The [`bitflags`](https://crates.io/crates/bitflags) crate is useful for " -"working with bitflags." +"Consult [the documentation](https://doc.rust-lang.org/std/primitive.pointer." +"html#method.as_mut) for the `as_mut` method." msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// Flags from the UART flag register.\n" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "Highlight Safety section." msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// Clear to send.\n" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "**Safety**" msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// Data set ready.\n" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "" +"When calling this method, you have to ensure that either the pointer is null " +"or the pointer is convertible to a reference." msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// Data carrier detect.\n" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "" +"Click the \"convertible to a reference\" hyperlink to the \"Pointer to " +"reference conversion\"" msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// UART busy transmitting data.\n" +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "" +"Track down the rules for converting a pointer to a reference, i.e., whether " +"it is \"dereferenceable\"." +msgstr "" + +#: src/unsafe-deep-dive/safety-preconditions/determining.md +msgid "" +"Consider the implications of this excerpt (Rust 1.90.0) \"You must enforce " +"Rust’s aliasing rules. The exact aliasing rules are not decided yet, ...\"" +msgstr "" + +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Example: References" +msgstr "" + +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Confirm understanding of the syntax" +msgstr "" + +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "" +"`Box` type is a reference to an integer on the heap that is owned by " +"the box." +msgstr "" + +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "" +"`*mut i32` type is a so-called raw pointer to an integer that the compiler " +"does not know the ownership of. Programmers need to ensure the rules are " +"enforced without assistance from the compiler." msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// Receive FIFO is empty.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "" +"Note: raw pointers do not provide ownership info to Rust. A pointer can be " +"semantically owning the data, or semantically borrowing, but that " +"information only exists in the programmer's mind." msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// Transmit FIFO is full.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "`&mut *boxed as *mut _` expression:" msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// Receive FIFO is full.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "`*boxed` is ..." msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// Transmit FIFO is empty.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "`&mut *boxed` is ..." msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md -msgid "/// Ring indicator.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "finally, `as *mut i32` casts the reference to a pointer." msgstr "" -#: src/bare-metal/aps/better-uart/bitflags.md +#: src/unsafe-deep-dive/safety-preconditions/references.md msgid "" -"The `bitflags!` macro creates a newtype something like `Flags(u16)`, along " -"with a bunch of method implementations to get and set flags." +"References, such as `&mut i32`, \"borrow\" their referent. This is Rust's " +"ownership system." msgstr "" -#: src/bare-metal/aps/better-uart/registers.md -msgid "Multiple registers" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Confirm understanding of ownership" msgstr "" -#: src/bare-metal/aps/better-uart/registers.md -msgid "" -"We can use a struct to represent the memory layout of the UART's registers." +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Step through code:" msgstr "" -#: src/bare-metal/aps/better-uart/registers.md +#: src/unsafe-deep-dive/safety-preconditions/references.md msgid "" -"[`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-" -"representation) tells the compiler to lay the struct fields out in order, " -"following the same rules as C. This is necessary for our struct to have a " -"predictable layout, as default Rust representation allows the compiler to " -"(among other things) reorder fields however it sees fit." +"(Line 3) Creates raw pointer to the `123` by dereferencing the box, creating " +"a new reference and casting the new reference as a pointer." msgstr "" -#: src/bare-metal/aps/better-uart/driver.md -msgid "Now let's use the new `Registers` struct in our driver." +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "(Line 4) Creates raw pointer with a NULL value" msgstr "" -#: src/bare-metal/aps/better-uart/driver.md -msgid "/// Driver for a PL011 UART.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "(Line 7) Converts the raw pointer to an Option with `.as_mut()`" msgstr "" -#: src/bare-metal/aps/better-uart/driver.md -msgid "" -"// Safe because we know that self.registers points to the control\n" -" // registers of a PL011 device which is appropriately mapped.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Highlight that pointers are nullable in Rust (unlike references)." msgstr "" -#: src/bare-metal/aps/better-uart/driver.md -msgid "" -"/// Reads and returns a pending byte, or `None` if nothing has been\n" -" /// received.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Compile to reveal the error messages." msgstr "" -#: src/bare-metal/aps/better-uart/driver.md -msgid "// TODO: Check for error conditions in bits 8-11.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Discuss" msgstr "" -#: src/bare-metal/aps/better-uart/driver.md -msgid "" -"Note the use of `addr_of!` / `addr_of_mut!` to get pointers to individual " -"fields without creating an intermediate reference, which would be unsound." +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "(Line 6) `println!(\"{:?}\", *a);`" msgstr "" -#: src/bare-metal/aps/better-uart/using.md src/bare-metal/aps/logging/using.md -msgid "Using it" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Prefix star dereferences a raw pointer." msgstr "" -#: src/bare-metal/aps/better-uart/using.md +#: src/unsafe-deep-dive/safety-preconditions/references.md msgid "" -"Let's write a small program using our driver to write to the serial console, " -"and echo incoming bytes." +"It is an explicit operation. Whereas regular references have implicit " +"dereferencing most of the time thanks to the Deref trait. This is referred " +"to as \"auto-deref\"." msgstr "" -#: src/bare-metal/aps/better-uart/using.md src/bare-metal/aps/logging/using.md -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Base address of the primary PL011 UART.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Dereferencing a raw pointer is an unsafe operation." msgstr "" -#: src/bare-metal/aps/better-uart/using.md src/bare-metal/aps/logging/using.md -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "" -"// Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" -" // and nothing else accesses that address range.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Requires an unsafe block." msgstr "" -#: src/bare-metal/aps/better-uart/using.md src/bare-metal/aps/logging/using.md -msgid "\"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\"" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "(Line 7) `println!(\"{:?}\", b.as_mut());`" msgstr "" -#: src/bare-metal/aps/better-uart/using.md -msgid "b'\\r'" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "`as_mut()` is an unsafe function." msgstr "" -#: src/bare-metal/aps/better-uart/using.md src/async/pitfalls/cancellation.md -msgid "b'\\n'" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Calling an unsafe function requires an unsafe block." msgstr "" -#: src/bare-metal/aps/better-uart/using.md -msgid "b'q'" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "" +"Demonstrate: Fix the code (add unsafe blocks) and compile again to show the " +"working program." msgstr "" -#: src/bare-metal/aps/better-uart/using.md -msgid "\"Bye!\"" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "" +"Demonstrate: Replace `as *mut i32` with `as *mut _`, show that it compiles." msgstr "" -#: src/bare-metal/aps/better-uart/using.md +#: src/unsafe-deep-dive/safety-preconditions/references.md msgid "" -"As in the [inline assembly](../inline-assembly.md) example, this `main` " -"function is called from our entry point code in `entry.S`. See the speaker " -"notes there for details." +"We can partially omit the target type in the cast. The Rust compiler knows " +"that the source of the cast is a `&mut i32`. This reference type can only be " +"converted to one pointer type, `*mut i32`." msgstr "" -#: src/bare-metal/aps/better-uart/using.md +#: src/unsafe-deep-dive/safety-preconditions/references.md msgid "" -"Run the example in QEMU with `make qemu` under `src/bare-metal/aps/examples`." +"We said that the unsafe code marks the responsibility shift from the " +"compiler to the programmer." msgstr "" -#: src/bare-metal/aps/logging.md +#: src/unsafe-deep-dive/safety-preconditions/references.md msgid "" -"It would be nice to be able to use the logging macros from the [`log`]" -"(https://crates.io/crates/log) crate. We can do this by implementing the " -"`Log` trait." +"How do we convey that we thought about our unusual responsibilities while " +"writing unsafe code? Safety comments." msgstr "" -#: src/bare-metal/aps/logging.md -msgid "\"[{}] {}\"" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Safety comments explain why unsafe code is correct." msgstr "" -#: src/bare-metal/aps/logging.md -msgid "/// Initialises UART logger.\n" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Without a safety comment, unsafe code is not safe." msgstr "" -#: src/bare-metal/aps/logging.md -msgid "" -"The unwrap in `log` is safe because we initialise `LOGGER` before calling " -"`set_logger`." +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Discuss: Whether to use one large unsafe block or two smaller ones:" msgstr "" -#: src/bare-metal/aps/logging/using.md -msgid "We need to initialise the logger before we use it." +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Possibility of using a single unsafe block rather than multiple." msgstr "" -#: src/bare-metal/aps/logging/using.md -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "\"{info}\"" +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "Using more allows safety comments as specific as possible." msgstr "" -#: src/bare-metal/aps/logging/using.md -msgid "Note that our panic handler can now log details of panics." +#: src/unsafe-deep-dive/safety-preconditions/references.md +msgid "" +"// SAFETY: `a` is a non-null pointer to i32, it is initialized and still\n" +" // allocated.\n" msgstr "" -#: src/bare-metal/aps/logging/using.md +#: src/unsafe-deep-dive/safety-preconditions/references.md msgid "" -"Run the example in QEMU with `make qemu_logger` under `src/bare-metal/aps/" -"examples`." +"// SAFETY: `b` is a null pointer, which `as_mut()` converts to `None`.\n" msgstr "" -#: src/bare-metal/aps/exceptions.md +#: src/unsafe-deep-dive/safety-preconditions/defining.md +msgid "User-defined types are entitled to have their own safety preconditions" +msgstr "" + +#: src/unsafe-deep-dive/safety-preconditions/defining.md msgid "" -"AArch64 defines an exception vector table with 16 entries, for 4 types of " -"exceptions (synchronous, IRQ, FIQ, SError) from 4 states (current EL with " -"SP0, current EL with SPx, lower EL using AArch64, lower EL using AArch32). " -"We implement this in assembly to save volatile registers to the stack before " -"calling into Rust code:" +"Include documentation so that they can later be determined and satisfied" msgstr "" -#: src/bare-metal/aps/exceptions.md -msgid "EL is exception level; all our examples this afternoon run in EL1." +#: src/unsafe-deep-dive/safety-preconditions/ascii.md +msgid "/// Text that is guaranteed to be encoded within 7-bit ASCII.\n" msgstr "" -#: src/bare-metal/aps/exceptions.md +#: src/unsafe-deep-dive/safety-preconditions/ascii.md msgid "" -"For simplicity we aren't distinguishing between SP0 and SPx for the current " -"EL exceptions, or between AArch32 and AArch64 for the lower EL exceptions." +"/// Creates a new `Ascii` from a byte slice without checking for ASCII\n" +" /// validity.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// Providing non-ASCII bytes results in undefined behavior.\n" msgstr "" -#: src/bare-metal/aps/exceptions.md +#: src/unsafe-deep-dive/safety-preconditions/ascii.md msgid "" -"For this example we just log the exception and power down, as we don't " -"expect any of them to actually happen." +"\"The `Ascii` type is a minimal wrapper around a byte slice. Internally, " +"they share the same representation. However, `Ascii` requires that the high " +"bit must not be used.\"" msgstr "" -#: src/bare-metal/aps/exceptions.md +#: src/unsafe-deep-dive/safety-preconditions/ascii.md msgid "" -"We can think of exception handlers and our main execution context more or " -"less like different threads. [`Send` and `Sync`](../../concurrency/send-sync." -"md) will control what we can share between them, just like with threads. For " -"example, if we want to share some value between exception handlers and the " -"rest of the program, and it's `Send` but not `Sync`, then we'll need to wrap " -"it in something like a `Mutex` and put it in a static." +"Optional: Extend the example to mention that it's possible to use " +"`debug_assert!` to test the preconditions during tests without impacting " +"release builds." msgstr "" -#: src/bare-metal/aps/other-projects.md -msgid "[oreboot](https://github.com/oreboot/oreboot)" +#: src/unsafe-deep-dive/rules-of-the-game.md +msgid "" +"“We've seen many examples of code that has problems in the class, but we " +"lack consistent terminology." msgstr "" -#: src/bare-metal/aps/other-projects.md -msgid "\"coreboot without the C\"" +#: src/unsafe-deep-dive/rules-of-the-game.md +msgid "" +"“The goal of the next section is to introduce some terms that describe many " +"of the concepts that we have been thinking about." msgstr "" -#: src/bare-metal/aps/other-projects.md -msgid "Supports x86, aarch64 and RISC-V." +#: src/unsafe-deep-dive/rules-of-the-game.md +msgid "undefined behavior" msgstr "" -#: src/bare-metal/aps/other-projects.md -msgid "Relies on LinuxBoot rather than having many drivers itself." +#: src/unsafe-deep-dive/rules-of-the-game.md +msgid "sound" msgstr "" -#: src/bare-metal/aps/other-projects.md -msgid "" -"[Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-" -"raspberrypi-OS-tutorials)" +#: src/unsafe-deep-dive/rules-of-the-game.md +msgid "unsound" msgstr "" -#: src/bare-metal/aps/other-projects.md +#: src/unsafe-deep-dive/rules-of-the-game.md msgid "" -"Initialisation, UART driver, simple bootloader, JTAG, exception levels, " -"exception handling, page tables" +"“Given that many safety preconditions are semantic rather than syntactic, " +"it's important to use a shared vocabulary. That way we can agree on " +"semantics." msgstr "" -#: src/bare-metal/aps/other-projects.md +#: src/unsafe-deep-dive/rules-of-the-game.md msgid "" -"Some dodginess around cache maintenance and initialisation in Rust, not " -"necessarily a good example to copy for production code." +"“The overarching goal is to develop a mental framework of what soundness is " +"and ensure that Rust code that contains unsafe remains sound.”" msgstr "" -#: src/bare-metal/aps/other-projects.md -msgid "[`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)" +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md +msgid "Soundness is fundamental to Rust" msgstr "" -#: src/bare-metal/aps/other-projects.md -msgid "Static analysis to determine maximum stack usage." +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md +msgid "Soundness ≈ impossible to cause memory safety problems" msgstr "" -#: src/bare-metal/aps/other-projects.md -msgid "" -"The RaspberryPi OS tutorial runs Rust code before the MMU and caches are " -"enabled. This will read and write memory (e.g. the stack). However:" +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md +msgid "Sound functions have common “shapes”" msgstr "" -#: src/bare-metal/aps/other-projects.md -msgid "" -"Without the MMU and cache, unaligned accesses will fault. It builds with " -"`aarch64-unknown-none` which sets `+strict-align` to prevent the compiler " -"generating unaligned accesses so it should be alright, but this is not " -"necessarily the case in general." +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md +msgid "“A fundamental principle of Rust code is that it is sound." msgstr "" -#: src/bare-metal/aps/other-projects.md +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md msgid "" -"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 " -"doesn't explicitly access the memory, speculative accesses can lead to cache " -"fills, and then changes from one or the other will get lost. Again this is " -"alright in this particular case (running directly on the hardware with no " -"hypervisor), but isn't a good pattern in general." +"“We’ll create a formal definition of the term soundness shortly. In the " +"meantime, think of sound code as code that cannot trigger memory safety " +"problems." msgstr "" -#: src/bare-metal/useful-crates.md -msgid "Useful crates" -msgstr "āĻĻāϰāĻ•āĻžāϰ⧀ āĻ•ā§āϰ⧇āϟ-āϏāĻŽā§‚āĻš" +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md +msgid "“Sound code is made up of _sound functions_ and _sound operations_." +msgstr "" -#: src/bare-metal/useful-crates.md +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md msgid "" -"We'll go over a few crates which solve some common problems in bare-metal " -"programming." +"“A sound function is a function where none of its possible inputs could " +"provoke soundness problems." msgstr "" -#: src/bare-metal/useful-crates/zerocopy.md -msgid "" -"The [`zerocopy`](https://docs.rs/zerocopy/) crate (from Fuchsia) provides " -"traits and macros for safely converting between byte sequences and other " -"types." +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md +msgid "Sound functions have common shapes." msgstr "" -#: src/bare-metal/useful-crates/zerocopy.md -msgid "" -"This is not suitable for MMIO (as it doesn't use volatile reads and writes), " -"but can be useful for working with structures shared with hardware e.g. by " -"DMA, or sent over some external interface." +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md +msgid "Those shapes are what we’ll look at now." msgstr "" -#: src/bare-metal/useful-crates/zerocopy.md +#: src/unsafe-deep-dive/rules-of-the-game/rust-is-sound.md msgid "" -"`FromBytes` can be implemented for types for which any byte pattern is " -"valid, and so can safely be converted from an untrusted sequence of bytes." +"“We’ll start with one that’s implemented in Safe Rust, and then see what " +"could happen when we introduce `unsafe` to different parts." msgstr "" -#: src/bare-metal/useful-crates/zerocopy.md -msgid "" -"Attempting to derive `FromBytes` for these types would fail, because " -"`RequestType` doesn't use all possible u32 values as discriminants, so not " -"all byte patterns are valid." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory.md +msgid "Copying memory - Introduction" msgstr "" -#: src/bare-metal/useful-crates/zerocopy.md -msgid "" -"`zerocopy::byteorder` has types for byte-order aware numeric primitives." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory.md +msgid "/// Reads bytes from `source` and writes them to `dest`\n" msgstr "" -#: src/bare-metal/useful-crates/zerocopy.md -msgid "" -"Run the example with `cargo run` under `src/bare-metal/useful-crates/" -"zerocopy-example/`. (It won't run in the Playground because of the crate " -"dependency.)" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory.md +msgid "“Here is our initial function prototype.”" msgstr "" -#: src/bare-metal/useful-crates/aarch64-paging.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory.md msgid "" -"The [`aarch64-paging`](https://crates.io/crates/aarch64-paging) crate lets " -"you create page tables according to the AArch64 Virtual Memory System " -"Architecture." +"“`copy` accepts two slices as arguments. `dest` (destination) is mutable, " +"whereas `source` is not.”" msgstr "" -#: src/bare-metal/useful-crates/aarch64-paging.md -msgid "// Create a new page table with identity mapping." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory.md +msgid "“Let's see the shapes of sound Rust code.”" msgstr "" -#: src/bare-metal/useful-crates/aarch64-paging.md -msgid "// Map a 2 MiB region of memory as read-only." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +msgid "“The implementation only uses safe Rust." msgstr "" -#: src/bare-metal/useful-crates/aarch64-paging.md -msgid "// Set `TTBR0_EL1` to activate the page table." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +msgid "What can we learn from this?" msgstr "" -#: src/bare-metal/useful-crates/aarch64-paging.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md msgid "" -"For now it only supports EL1, but support for other exception levels should " -"be straightforward to add." +"“It is impossible for `copy` to trigger memory safety issues when " +"implemented in Safe Rust. This is true for all possible input arguments.”" msgstr "" -#: src/bare-metal/useful-crates/aarch64-paging.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md msgid "" -"This is used in Android for the [Protected VM Firmware](https://cs.android." -"com/android/platform/superproject/+/master:packages/modules/Virtualization/" -"pvmfw/)." +"“For example, by using Rust’s iterators, we can ensure that we’ll never " +"trigger errors relating to handling pointers directly, such as needing null " +"pointer or bounds checks.”" msgstr "" -#: src/bare-metal/useful-crates/aarch64-paging.md -msgid "" -"There's no easy way to run this example, as it needs to run on real hardware " -"or under QEMU." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +msgid "Ask: “Can you think of any others?”" msgstr "" -#: src/bare-metal/useful-crates/buddy_system_allocator.md -msgid "" -"[`buddy_system_allocator`](https://crates.io/crates/buddy_system_allocator) " -"is a third-party crate implementing a basic buddy system allocator. It can " -"be used both for [`LockedHeap`](https://docs.rs/buddy_system_allocator/0.9.0/" -"buddy_system_allocator/struct.LockedHeap.html) implementing [`GlobalAlloc`]" -"(https://doc.rust-lang.org/core/alloc/trait.GlobalAlloc.html) so you can use " -"the standard `alloc` crate (as we saw [before](../alloc.md)), or for " -"allocating other address space. For example, we might want to allocate MMIO " -"space for PCI BARs:" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +msgid "No aliasing issues" msgstr "" -#: src/bare-metal/useful-crates/buddy_system_allocator.md -msgid "PCI BARs always have alignment equal to their size." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +msgid "Dangling pointers are impossible" msgstr "" -#: src/bare-metal/useful-crates/buddy_system_allocator.md -msgid "" -"Run the example with `cargo run` under `src/bare-metal/useful-crates/" -"allocator-example/`. (It won't run in the Playground because of the crate " -"dependency.)" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +msgid "Alignment will be correct" msgstr "" -#: src/bare-metal/useful-crates/tinyvec.md -msgid "" -"Sometimes you want something which can be resized like a `Vec`, but without " -"heap allocation. [`tinyvec`](https://crates.io/crates/tinyvec) provides " -"this: a vector backed by an array or slice, which could be statically " -"allocated or on the stack, which keeps track of how many elements are used " -"and panics if you try to use more than are allocated." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md +msgid "Cannot accidentally read from uninitialized memory" msgstr "" -#: src/bare-metal/useful-crates/tinyvec.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md msgid "" -"`tinyvec` requires that the element type implement `Default` for " -"initialisation." +"“We can say that the `copy` function is _sound_ because Rust ensures that " +"all of the safety preconditions are satisfied.”" msgstr "" -#: src/bare-metal/useful-crates/tinyvec.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md msgid "" -"The Rust Playground includes `tinyvec`, so this example will run fine inline." +"“From the point of view of the programmer, as this function is implemented " +"in safe Rust, we can think of it as having no safety preconditions.”" msgstr "" -#: src/bare-metal/useful-crates/spin.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/safe.md msgid "" -"`std::sync::Mutex` and the other synchronisation primitives from `std::sync` " -"are not available in `core` or `alloc`. How can we manage synchronisation or " -"interior mutability, such as for sharing state between different CPUs?" +"“This does not mean that `copy` will always do what the caller might want. " +"If there is insufficient space available in the `dest` slice, then data will " +"not be copied across.”" msgstr "" -#: src/bare-metal/useful-crates/spin.md -msgid "" -"The [`spin`](https://crates.io/crates/spin) crate provides spinlock-based " -"equivalents of many of these primitives." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md +msgid "// SAFETY: `i` must be in-bounds as it was produced by source.len()\n" msgstr "" -#: src/bare-metal/useful-crates/spin.md -msgid "Be careful to avoid deadlock if you take locks in interrupt handlers." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md +msgid "// SAFETY: `i` must be in-bounds as it was produced by dest.len()\n" msgstr "" -#: src/bare-metal/useful-crates/spin.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md msgid "" -"`spin` also has a ticket lock mutex implementation; equivalents of `RwLock`, " -"`Barrier` and `Once` from `std::sync`; and `Lazy` for lazy initialisation." +"“Here we have a safe function that encapsulates unsafe blocks that are used " +"internally." msgstr "" -#: src/bare-metal/useful-crates/spin.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md msgid "" -"The [`once_cell`](https://crates.io/crates/once_cell) crate also has some " -"useful types for late initialisation with a slightly different approach to " -"`spin::once::Once`." +"“This implementation avoids iterators. Instead, the implementor is accessing " +"memory manually.”" msgstr "" -#: src/bare-metal/useful-crates/spin.md -msgid "" -"The Rust Playground includes `spin`, so this example will run fine inline." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md +msgid "“Is this correct?” “Are there any problems?”" msgstr "" -#: src/bare-metal/android.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md msgid "" -"To build a bare-metal Rust binary in AOSP, you need to use a " -"`rust_ffi_static` Soong rule to build your Rust code, then a `cc_binary` " -"with a linker script to produce the binary itself, and then a `raw_binary` " -"to convert the ELF to a raw binary ready to be run." +"“Who has responsibility for ensuring that correctness? The author of the " +"function." msgstr "" -#: src/bare-metal/android/vmbase.md -msgid "vmbase" -msgstr "vmbase" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/encapsulated-unsafe.md +msgid "" +"“A Safe Rust function that contains unsafe blocks remains sound if it’s " +"impossible for an input to cause memory safety issues." +msgstr "" -#: src/bare-metal/android/vmbase.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md msgid "" -"For VMs running under crosvm on aarch64, the [vmbase](https://android." -"googlesource.com/platform/packages/modules/Virtualization/+/refs/heads/" -"master/vmbase/) library provides a linker script and useful defaults for the " -"build rules, along with an entry point, UART console logging and more." +"The functionality of copying bytes from one place to the next remains the " +"same." msgstr "" -#: src/bare-metal/android/vmbase.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md msgid "" -"The `main!` macro marks your main function, to be called from the `vmbase` " -"entry point." +"“However, we need to manually create a slice. To do that, we first need to " +"find the end of the data." msgstr "" -#: src/bare-metal/android/vmbase.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md msgid "" -"The `vmbase` entry point handles console initialisation, and issues a " -"PSCI_SYSTEM_OFF to shutdown the VM if your main function returns." +"“As we’re working with text, we’ll use the C convention of a null-terminated " +"string." msgstr "" -#: src/exercises/bare-metal/afternoon.md -msgid "We will write a driver for the PL031 real-time clock device." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "Compile the code. See that the output remains the same." msgstr "" -#: src/exercises/bare-metal/afternoon.md src/exercises/concurrency/afternoon.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md msgid "" -"After looking at the exercises, you can look at the [solutions](solutions-" -"afternoon.md) provided." +"“An unsound function can still work correctly for some inputs. Just because " +"your tests pass, does not mean that you have a sound function.”" msgstr "" -#: src/exercises/bare-metal/rtc.md -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "RTC driver" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "“Can anyone spot any issues?”" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "" -"The QEMU aarch64 virt machine has a [PL031](https://developer.arm.com/" -"documentation/ddi0224/c) real-time clock at 0x9010000. For this exercise, " -"you should write a driver for it." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "Readability: difficult to quickly scan code" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "" -"Use it to print the current time to the serial console. You can use the " -"[`chrono`](https://crates.io/crates/chrono) crate for date/time formatting." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "`source` pointer might be null" msgstr "" -#: src/exercises/bare-metal/rtc.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md msgid "" -"Use the match register and raw interrupt status to busy-wait until a given " -"time, e.g. 3 seconds in the future. (Call [`core::hint::spin_loop`](https://" -"doc.rust-lang.org/core/hint/fn.spin_loop.html) inside the loop.)" +"`source` pointer might be dangling, i.e. point to freed or uninitialized " +"memory" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "" -"_Extension if you have time:_ Enable and handle the interrupt generated by " -"the RTC match. You can use the driver provided in the [`arm-gic`](https://" -"docs.rs/arm-gic/) crate to configure the Arm Generic Interrupt Controller." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "`source` might not be null-terminated" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "Use the RTC interrupt, which is wired to the GIC as `IntId::spi(2)`." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "" +"“Assume that we cannot change the function signature, what improvements " +"could we make to the code to address these issues?”" msgstr "" -#: src/exercises/bare-metal/rtc.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md msgid "" -"Once the interrupt is enabled, you can put the core to sleep via `arm_gic::" -"wfi()`, which will cause the core to sleep until it receives an interrupt." +"Null pointer: Add null check with early return (`if source.is_null() " +"{ return; }`)" msgstr "" -#: src/exercises/bare-metal/rtc.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md msgid "" -"Download the [exercise template](../../comprehensive-rust-exercises.zip) and " -"look in the `rtc` directory for the following files." +"Readability: Use a well-tested library rather than implementing “find first " +"null byte” ourselves" msgstr "" -#: src/exercises/bare-metal/rtc.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md msgid "" -"_src/exceptions.rs_ (you should only need to change this for the 3rd part of " -"the exercise):" +"“Some safety requirements are impossible to defensively check for, however, " +"i.e.:”" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "_src/logger.rs_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "dangling pointer" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "_src/pl011.rs_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "no null termination byte" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "_build.rs_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "“How can we make this function sound?”" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "_entry.S_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "Either" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "_exceptions.S_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "" +"Change the type of the `source` input argument to something that has a known " +"length, i.e. use a slice like the previous example." msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "_idmap.S_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "Or" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "_image.ld_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "Mark the function as unsafe" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "_Makefile_ (you shouldn't need to change this):" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/exposed-unsafe.md +msgid "Document the safety preconditions" msgstr "" -#: src/exercises/bare-metal/rtc.md -msgid "Run the code in QEMU with `make qemu`." +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "" +"/// ...\n" +"///\n" +"/// # Safety\n" +"///\n" +"/// This function can easily trigger undefined behavior. Ensure that:\n" +"///\n" +"/// - `source` pointer is non-null and non-dangling\n" +"/// - `source` data ends with a null byte within its memory allocation\n" +"/// - `source` data is not freed (its lifetime invariants are preserved)\n" +"/// - `source` data contains fewer than `isize::MAX` bytes\n" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "Bare Metal Rust Afternoon" -msgstr "Bare Metal Rust: āĻŦāĻŋāĻ•āĻžāϞ" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "// SAFETY: Caller has provided a non-null pointer\n" +msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "([back to exercise](rtc.md))" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "// SAFETY: Caller has provided a data with length < isize:MAX\n" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "_main.rs_:" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "// SAFETY: Caller maintains lifetime and aliasing requirements\n" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Base addresses of the GICv3.\n" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "Changes to previous iterations:" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Base address of the PL031 RTC.\n" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "`copy` marked as unsafe" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// The IRQ used by the PL031 RTC.\n" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "Safety preconditions are documented" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "\"main({:#x}, {:#x}, {:#x}, {:#x})\"" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "inline safety comments" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md msgid "" -"// Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base\n" -" // addresses of a GICv3 distributor and redistributor respectively, and\n" -" // nothing else accesses those address ranges.\n" +"An unsafe function is sound when both its safety preconditions and its " +"internal unsafe blocks are documented." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "Fixes needed in `main`." +msgstr "" + +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md msgid "" -"// Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 device,\n" -" // and nothing else accesses that address range.\n" +"`a` does not satisfy one of the preconditions of `copy` (source\\` data ends " +"with a null byte within its memory allocation)" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "\"RTC: {time}\"" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md +msgid "SAFETY comment needed" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "// Wait for 3 seconds, without interrupts.\n" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/crying-wolf.md +msgid "“It is also possible to create so-called crying wolf functions." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "\"Waiting for {}\"" +#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/crying-wolf.md +msgid "" +"“These are functions which are tagged as unsafe, but which have no safety " +"preconditions that programmers need to check." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "\"matched={}, interrupt_pending={}\"" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "3 Shapes of Sound Rust" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "\"Finished waiting\"" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "Functions written only in Safe Rust" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "// Wait another 3 seconds for an interrupt.\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "Functions that contain `unsafe` blocks which are impossible to misuse" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "_pl031.rs_:" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "Unsafe functions that have their safety preconditions documented" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Data register\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "We want to write sound code." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Match register\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "Sound code can only have the following shapes:" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Load register\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "safe functions that contain no unsafe blocks" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Control register\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "" +"safe functions that completely encapsulate unsafe blocks, meaning that the " +"caller does not need to know about them" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Interrupt Mask Set or Clear register\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "" +"unsafe functions that contain unsafe blocks but don't encapsulate them, and " +"pass the proof burden to their caller" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Raw Interrupt Status\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "Burden of proof" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Masked Interrupt Status\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "safe functions with only Safe Rust -> compiler" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Interrupt Clear Register\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "safe functions with unsafe blocks -> function author" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Driver for a PL031 real-time clock.\n" +#: src/unsafe-deep-dive/rules-of-the-game/3-shapes-of-sound-rust.md +msgid "unsafe functions -> function caller" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/soundness.md +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/unsoundness.md msgid "" -"/// Constructs a new instance of the RTC driver for a PL031 device at the\n" -" /// given base address.\n" -" ///\n" -" /// # Safety\n" -" ///\n" -" /// The given base address must point to the MMIO control registers of " -"a\n" -" /// PL031 device, which must be mapped into the address space of the " -"process\n" -" /// as device memory and not have any other aliases.\n" +"A sound function is one that can't trigger UB if its safety preconditions " +"are satisfied." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Reads the current RTC value.\n" +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/soundness.md +msgid "Read the definition of sound functions." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/soundness.md msgid "" -"// Safe because we know that self.registers points to the control\n" -" // registers of a PL031 device which is appropriately mapped.\n" +"Remind the students that the programmer who implements the caller is " +"responsible for satisfying the safety precondition; the compiler is not " +"helping." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/soundness.md msgid "" -"/// Writes a match value. When the RTC value matches this then an interrupt\n" -" /// will be generated (if it is enabled).\n" +"Translate into informal terms. Soundness means that the function is nice and " +"plays by the rules. It documents its safety preconditions, and when the " +"caller satisfies them, the function behaves well (no UB)." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "" -"/// Returns whether the match register matches the RTC value, whether or " -"not\n" -" /// the interrupt is enabled.\n" +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md +msgid "Soundness Proof (Part 2)" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "" -"/// Returns whether there is currently an interrupt pending.\n" -" ///\n" -" /// This should be true if and only if `matched` returns true and the\n" -" /// interrupt is masked.\n" +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md +msgid "Corollary: All functions implemented in pure safe Rust are sound." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md +msgid "Proof:" +msgstr "" + +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md +msgid "Safe Rust code has no safety preconditions." +msgstr "" + +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md msgid "" -"/// Sets or clears the interrupt mask.\n" -" ///\n" -" /// When the mask is true the interrupt is enabled; when it is false " -"the\n" -" /// interrupt is disabled.\n" +"Therefore, callers of functions implemented in pure safe Rust always " +"trivially satisfy the empty set of preconditions." msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md -msgid "/// Clears a pending interrupt, if any.\n" +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md +msgid "Safe Rust code can't trigger UB." msgstr "" -#: src/concurrency.md -msgid "Welcome to Concurrency in Rust" +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md +msgid "QED." msgstr "" -#: src/concurrency.md -msgid "" -"Rust has full support for concurrency using OS threads with mutexes and " -"channels." +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md +msgid "Read the corollary." +msgstr "" + +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md +msgid "Explain the proof." msgstr "" -#: src/concurrency.md +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/corollary.md msgid "" -"The Rust type system plays an important role in making many concurrency bugs " -"compile time bugs. This is often referred to as _fearless concurrency_ since " -"you can rely on the compiler to ensure correctness at runtime." +"Translate into informal terms: all safe Rust code is nice. It does not have " +"safety preconditions that the programmer has to think of, always plays by " +"the rules, and never triggers UB." msgstr "" -#: src/concurrency/threads.md -msgid "Rust threads work similarly to threads in other languages:" +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/unsoundness.md +msgid "" +"An unsound function can trigger UB even if you satisfy the documented safety " +"preconditions." msgstr "" -#: src/concurrency/threads.md -msgid "\"Count in thread: {i}!\"" +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/unsoundness.md +msgid "Unsound code is _bad_." msgstr "" -#: src/concurrency/threads.md -msgid "\"Main thread: {i}\"" +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/unsoundness.md +msgid "Read the definition of unsound functions." msgstr "" -#: src/concurrency/threads.md -msgid "Threads are all daemon threads, the main thread does not wait for them." +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/unsoundness.md +msgid "" +"Translate into informal terms: unsound code is not nice. No, that's an " +"understatement. Unsound code is BAD. Even if you play by the documented " +"rules, unsound code can still trigger UB!" msgstr "" -#: src/concurrency/threads.md -msgid "Thread panics are independent of each other." +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/unsoundness.md +msgid "We don't want any unsound code in our repositories." msgstr "" -#: src/concurrency/threads.md -msgid "Panics can carry a payload, which can be unpacked with `downcast_ref`." +#: src/unsafe-deep-dive/rules-of-the-game/soundness-proof/unsoundness.md +msgid "Finding unsound code is the **primary** goal of the code review." msgstr "" -#: src/concurrency/threads.md +#: src/unsafe-deep-dive/memory-lifecycle.md msgid "" -"Notice that the thread is stopped before it reaches 10 --- the main thread " -"is not waiting." +"Memory moves through different phases as objects (values) are created and " +"destroyed." msgstr "" -#: src/concurrency/threads.md -msgid "" -"Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for " -"the thread to finish." +#: src/unsafe-deep-dive/memory-lifecycle.md +msgid "Memory State" msgstr "" -#: src/concurrency/threads.md -msgid "Trigger a panic in the thread, notice how this doesn't affect `main`." +#: src/unsafe-deep-dive/memory-lifecycle.md +msgid "Readable from Safe Rust?" msgstr "" -#: src/concurrency/threads.md -msgid "" -"Use the `Result` return value from `handle.join()` to get access to the " -"panic payload. This is a good time to talk about [`Any`](https://doc.rust-" -"lang.org/std/any/index.html)." +#: src/unsafe-deep-dive/memory-lifecycle.md +msgid "Available" msgstr "" -#: src/concurrency/scoped-threads.md -msgid "Normal threads cannot borrow from their environment:" +#: src/unsafe-deep-dive/memory-lifecycle.md +msgid "Allocated" msgstr "" -#: src/concurrency/scoped-threads.md -msgid "" -"However, you can use a [scoped thread](https://doc.rust-lang.org/std/thread/" -"fn.scope.html) for this:" +#: src/unsafe-deep-dive/memory-lifecycle.md +msgid "Initialized" msgstr "" -#: src/concurrency/scoped-threads.md +#: src/unsafe-deep-dive/memory-lifecycle.md msgid "" -"The reason for that is that when the `thread::scope` function completes, all " -"the threads are guaranteed to be joined, so they can return borrowed data." +"This section discusses what happens as memory from the operating system " +"becomes a valid variable in the program." msgstr "" -#: src/concurrency/scoped-threads.md +#: src/unsafe-deep-dive/memory-lifecycle.md msgid "" -"Normal Rust borrowing rules apply: you can either borrow mutably by one " -"thread, or immutably by any number of threads." +"When memory is available, the operating system has provided our program with " +"it." msgstr "" -#: src/concurrency/channels.md +#: src/unsafe-deep-dive/memory-lifecycle.md msgid "" -"Rust channels have two parts: a `Sender` and a `Receiver`. The two " -"parts are connected via the channel, but you only see the end-points." +"When memory is allocated, it is reserved for values to be written to it. We " +"call this uninitialized memory." msgstr "" -#: src/concurrency/channels.md -msgid "\"Received: {:?}\"" +#: src/unsafe-deep-dive/memory-lifecycle.md +msgid "When memory is initialized, it is safe to read from." msgstr "" -#: src/concurrency/channels.md -msgid "" -"`mpsc` stands for Multi-Producer, Single-Consumer. `Sender` and `SyncSender` " -"implement `Clone` (so you can make multiple producers) but `Receiver` does " -"not." +#: src/unsafe-deep-dive/initialization/maybeuninit.md +msgid "`MaybeUninit` allows Rust to refer to uninitialized memory." msgstr "" -#: src/concurrency/channels.md +#: src/unsafe-deep-dive/initialization/maybeuninit.md +msgid "\"{uninit:?}\"" +msgstr "" + +#: src/unsafe-deep-dive/initialization/maybeuninit.md +msgid "“Safe Rust is unable to refer to data that’s potentially uninitialized”" +msgstr "" + +#: src/unsafe-deep-dive/initialization/maybeuninit.md +msgid "“Yet, all data arrives at the program as uninitialized.”" +msgstr "" + +#: src/unsafe-deep-dive/initialization/maybeuninit.md msgid "" -"`send()` and `recv()` return `Result`. If they return `Err`, it means the " -"counterpart `Sender` or `Receiver` is dropped and the channel is closed." +"“Therefore, we need some bridge in the type system to allow memory to " +"transition. `MaybeUninit` is that type.”" msgstr "" -#: src/concurrency/channels/unbounded.md -msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" +#: src/unsafe-deep-dive/initialization/maybeuninit.md +msgid "" +"“`MaybeUninit` is very similar to the `Option` type, although its " +"semantics are very different. The equivalent of `Option::None` for " +"`MaybeUninit` is uninitialized memory, which is only safe to write to.”" msgstr "" -#: src/concurrency/channels/unbounded.md src/concurrency/channels/bounded.md -msgid "\"Message {i}\"" +#: src/unsafe-deep-dive/initialization/maybeuninit.md +msgid "“Reading from memory that may be uninitialized is extremely dangerous.”" msgstr "" -#: src/concurrency/channels/unbounded.md src/concurrency/channels/bounded.md -msgid "\"{thread_id:?}: sent Message {i}\"" +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md +msgid "MaybeUninit and arrays" msgstr "" -#: src/concurrency/channels/unbounded.md src/concurrency/channels/bounded.md -msgid "\"{thread_id:?}: done\"" +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md +msgid "b\"RUST\"" msgstr "" -#: src/concurrency/channels/unbounded.md src/concurrency/channels/bounded.md -msgid "\"Main: got {msg}\"" +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md +msgid "// Initialize elements by writing values to the memory\n" msgstr "" -#: src/concurrency/channels/bounded.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md msgid "" -"With bounded (synchronous) channels, `send` can block the current thread:" +"// When a portion of an array is initialized, one can\n" +" // use unsafe to isolate it\n" msgstr "" -#: src/concurrency/channels/bounded.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md +#: src/unsafe-deep-dive/initialization/partial-initialization.md +msgid "\"{text}\"" +msgstr "" + +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md +msgid "// We must manually drop the initialized elements\n" +msgstr "" + +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md msgid "" -"Calling `send` will block the current thread until there is space in the " -"channel for the new message. The thread can be blocked indefinitely if there " -"is nobody who reads from the channel." +"To create an array of uninitialized memory, the `::uninit()` constructor can " +"be used within a `const` context." msgstr "" -#: src/concurrency/channels/bounded.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md +msgid "Use `ptr::write` to initialize values as per normal." +msgstr "" + +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md msgid "" -"A call to `send` will abort with an error (that is why it returns `Result`) " -"if the channel is closed. A channel is closed when the receiver is dropped." +"`.assume_init()` does not work as easily for arrays. It requires every value " +"to be initialized, which may not occur when reusing a buffer. This example " +"uses a pointer to isolate the initialized bytes to create a string slice." msgstr "" -#: src/concurrency/channels/bounded.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md msgid "" -"A bounded channel with a size of zero is called a \"rendezvous channel\". " -"Every send will block the current thread until another thread calls `read`." +"When creating a sub-slice of a partially-initialized array, be careful with " +"ownership and correctly implementing drop. Reminder: `MaybeUninit` will " +"not call drop on its `T`." msgstr "" -#: src/concurrency/send-sync.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md msgid "" -"How does Rust know to forbid shared access across threads? The answer is in " -"two traits:" +"`MaybeUninit<[u8;2048]>` is distinct from `[MaybeUninit::; 2048]`. This " +"is the difference between an array of uninitialized memory and an array that " +"contains uninitialized elements." msgstr "" -#: src/concurrency/send-sync.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md msgid "" -"[`Send`](https://doc.rust-lang.org/std/marker/trait.Send.html): a type `T` " -"is `Send` if it is safe to move a `T` across a thread boundary." +"`MaybeUninit<[u8;2048]>` is \"all or nothing\". You either fully initialize " +"the whole array and then call `assume_init`, or you must keep it as " +"`MaybeUninit<[u8; 2048]>` and avoid touching it as `[u8; 2048]`." msgstr "" -#: src/concurrency/send-sync.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md msgid "" -"[`Sync`](https://doc.rust-lang.org/std/marker/trait.Sync.html): a type `T` " -"is `Sync` if it is safe to move a `&T` across a thread boundary." +"`[MaybeUninit; 2048]` lets you initialize elements one at a time, then " +"take a sub-slice of just the initialized prefix and treat it as `[u8]` via " +"`std::slice::from_raw_parts`." msgstr "" -#: src/concurrency/send-sync.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md msgid "" -"`Send` and `Sync` are [unsafe traits](../unsafe/unsafe-traits.md). The " -"compiler will automatically derive them for your types as long as they only " -"contain `Send` and `Sync` types. You can also implement them manually when " -"you know it is valid." +"`slice_assume_init_ref` is safe only when every element in the slice is " +"initialized. For this example, we only pass `&buf[..input.len()]` after " +"writing exactly those bytes." msgstr "" -#: src/concurrency/send-sync.md +#: src/unsafe-deep-dive/initialization/maybeuninit/arrays.md msgid "" -"One can think of these traits as markers that the type has certain thread-" -"safety properties." +"When `T` needs drop, you must manually call `assume_init_drop()` for the " +"initialized elements. Skipping this leaks memory. However, calling it on an " +"uninitialized element is undefined behavior." msgstr "" -#: src/concurrency/send-sync.md -msgid "They can be used in the generic constraints as normal traits." +#: src/unsafe-deep-dive/initialization/maybeuninit/zeroed-method.md +msgid "// SAFETY: All values of `x` have been written to\n" msgstr "" -#: src/concurrency/send-sync/send.md -msgid "" -"A type `T` is [`Send`](https://doc.rust-lang.org/std/marker/trait.Send.html) " -"if it is safe to move a `T` value to another thread." +#: src/unsafe-deep-dive/initialization/maybeuninit/zeroed-method.md +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "\"{x:?}\"" msgstr "" -#: src/concurrency/send-sync/send.md +#: src/unsafe-deep-dive/initialization/maybeuninit/zeroed-method.md msgid "" -"The effect of moving ownership to another thread is that _destructors_ will " -"run in that thread. So the question is when you can allocate a value in one " -"thread and deallocate it in another." +"“MaybeUninit::zeroed() is an alternative constructor to MaybeUninit::" +"uninit(). It instructs the compiler to fill the bits of T with zeros.”" msgstr "" -#: src/concurrency/send-sync/send.md +#: src/unsafe-deep-dive/initialization/maybeuninit/zeroed-method.md msgid "" -"As an example, a connection to the SQLite library must only be accessed from " -"a single thread." +"Q: “Although the memory has been written to, the type remains " +"`MaybeUninit`. Can anyone think of why?”" msgstr "" -#: src/concurrency/send-sync/sync.md +#: src/unsafe-deep-dive/initialization/maybeuninit/zeroed-method.md msgid "" -"A type `T` is [`Sync`](https://doc.rust-lang.org/std/marker/trait.Sync.html) " -"if it is safe to access a `T` value from multiple threads at the same time." +"A: Some types require their values to be non-zero or non-null. The classic " +"case is references, but this applies to many other types as well. Consider " +"the `NonZeroUsize` integer type and others in its family." msgstr "" -#: src/concurrency/send-sync/sync.md -msgid "More precisely, the definition is:" +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "MaybeUninit.write() vs assignment" msgstr "" -#: src/concurrency/send-sync/sync.md -msgid "`T` is `Sync` if and only if `&T` is `Send`" +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "// Initialize\n" msgstr "" -#: src/concurrency/send-sync/sync.md -msgid "" -"This statement is essentially a shorthand way of saying that if a type is " -"thread-safe for shared use, it is also thread-safe to pass references of it " -"across threads." +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "// Overwrite\n" msgstr "" -#: src/concurrency/send-sync/sync.md -msgid "" -"This is because if a type is Sync it means that it can be shared across " -"multiple threads without the risk of data races or other synchronization " -"issues, so it is safe to move it to another thread. A reference to the type " -"is also safe to move to another thread, because the data it references can " -"be accessed from any thread safely." +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "\"Hi again\"" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`Send + Sync`" +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "// Assignment replaces the whole MaybeUninit value.\n" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "Most types you come across are `Send + Sync`:" +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "\"Goodbye\"" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`i8`, `f32`, `bool`, `char`, `&str`, ..." +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "// Ensure inner value is dropped\n" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`(T1, T2)`, `[T; N]`, `&[T]`, `struct { x: T }`, ..." +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "" +"Replacing inner values can cause memory leaks because the drop semantics " +"differ from most types. `MaybeUninit` does not call the destructor on its " +"`T`." msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`String`, `Option`, `Vec`, `Box`, ..." +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "" +"`MaybeUninit::write()` uses `ptr::write`: it initializes the memory in place " +"without reading or dropping the old contents. That is exactly what you want " +"when the memory might be uninitialized, but it also means you will leak if " +"there was already a live value there." msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`Arc`: Explicitly thread-safe via atomic reference count." +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "" +"Assignment, e.g. `buf = MaybeUninit::new(value)`, replaces the whole " +"`MaybeUninit`. The old `MaybeUninit` is moved and then dropped, but " +"`MaybeUninit` has no destructor for `T`, so the inner value is not dropped. " +"If the old slot held an initialized value, it is leaked just like with " +"`write()`." msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`Mutex`: Explicitly thread-safe via internal locking." +#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md +msgid "" +"If you need normal drop behavior, you need to tell Rust that the value is " +"initialized with `assume_init` or one of the related methods." msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`AtomicBool`, `AtomicU8`, ...: Uses special atomic instructions." +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "How to Initialize Memory" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "" -"The generic types are typically `Send + Sync` when the type parameters are " -"`Send + Sync`." +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "Steps:" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`Send + !Sync`" +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "Create `MaybeUninit`" +msgstr "" + +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "Write a value to it" +msgstr "" + +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "Notify Rust that the memory is initialized" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "" -"These types can be moved to other threads, but they're not thread-safe. " -"Typically because of interior mutability:" +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "// Step 1: Create MaybeUninit\n" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`mpsc::Sender`" +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "// Step 2: Write a valid value to the memory\n" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`mpsc::Receiver`" +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "// Step 3: Inform the type system that the memory location is valid\n" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`Cell`" +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "\"{init}\"" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`RefCell`" +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "" +"To work with uninitialized memory, follow this general workflow: create, " +"write, confirm." msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`!Send + Sync`" +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md +msgid "" +"Create `MaybeUninit`. The `::uninit()` constructor is the most general-" +"purpose one, but there are others which perform a write as well." msgstr "" -#: src/concurrency/send-sync/examples.md +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md msgid "" -"These types are thread-safe, but they cannot be moved to another thread:" +"Write a value of T. Notice that this is available from safe Rust. Staying in " +"safe Rust is useful because you must ensure that the value you write is " +"valid." msgstr "" -#: src/concurrency/send-sync/examples.md +#: src/unsafe-deep-dive/initialization/how-to-initialize-memory.md msgid "" -"`MutexGuard`: Uses OS level primitives which must be deallocated on " -"the thread which created them." +"Confirm to the type system that the memory is now initialized with the `." +"assume_init()` method." msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "`!Send + !Sync`" +#: src/unsafe-deep-dive/initialization/partial-initialization.md +msgid "Partial Initialization" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "These types are not thread-safe and cannot be moved to other threads:" +#: src/unsafe-deep-dive/initialization/partial-initialization.md +msgid "// let mut buf = [0u8; 2048];\n" msgstr "" -#: src/concurrency/send-sync/examples.md -msgid "" -"`Rc`: each `Rc` has a reference to an `RcBox`, which contains a non-" -"atomic reference count." +#: src/unsafe-deep-dive/initialization/partial-initialization.md +msgid "b\"Hello, Rust!\"" msgstr "" -#: src/concurrency/send-sync/examples.md +#: src/unsafe-deep-dive/initialization/partial-initialization.md msgid "" -"`*const T`, `*mut T`: Rust assumes raw pointers may have special concurrency " -"considerations." +"// SAFETY: We initialized exactly 'len' bytes of `buf` with UTF-8 text\n" +msgstr "" + +#: src/unsafe-deep-dive/initialization/partial-initialization.md +msgid "This code simulates receiving data from some external source." msgstr "" -#: src/concurrency/shared_state.md +#: src/unsafe-deep-dive/initialization/partial-initialization.md msgid "" -"Rust uses the type system to enforce synchronization of shared data. This is " -"primarily done via two types:" +"When reading bytes from an external source into a buffer, you typically " +"don't know how many bytes you'll receive. Using `MaybeUninit` lets you " +"allocate the buffer once without paying for a redundant initialization pass." msgstr "" -#: src/concurrency/shared_state.md +#: src/unsafe-deep-dive/initialization/partial-initialization.md msgid "" -"[`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html), atomic " -"reference counted `T`: handles sharing between threads and takes care to " -"deallocate `T` when the last reference is dropped," +"If we were to create the array with the standard syntax (`buf = [0u8; " +"2048]`), the whole buffer would be flushed with zeroes. `MaybeUninit` " +"tells the compiler to reserve space, but not to touch the memory yet." msgstr "" -#: src/concurrency/shared_state.md +#: src/unsafe-deep-dive/initialization/partial-initialization.md msgid "" -"[`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html): ensures " -"mutually exclusive access to the `T` value." +"Q: Which part of the code snippet is performing a similar role to `." +"assume_init()`? A: The pointer cast and the implicit read." msgstr "" -#: src/concurrency/shared_state/arc.md +#: src/unsafe-deep-dive/initialization/partial-initialization.md msgid "" -"[`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) allows shared " -"read-only access via `Arc::clone`:" +"We cannot call `assume_init()` on the whole array. That would be unsound " +"because most elements remain uninitialized. Instead, we cast the pointer " +"from `*const MaybeUninit` to `*const u8` and build a slice covering only " +"the initialised portion." msgstr "" -#: src/concurrency/shared_state/arc.md -msgid "\"{thread_id:?}: {v:?}\"" +#: src/unsafe-deep-dive/pinning.md +msgid "This segment of the course covers:" msgstr "" -#: src/concurrency/shared_state/arc.md src/concurrency/shared_state/example.md -msgid "\"v: {v:?}\"" +#: src/unsafe-deep-dive/pinning.md +msgid "What \"pinning\" is" msgstr "" -#: src/concurrency/shared_state/arc.md -msgid "" -"`Arc` stands for \"Atomic Reference Counted\", a thread safe version of `Rc` " -"that uses atomic operations." +#: src/unsafe-deep-dive/pinning.md +msgid "Why it is necessary" msgstr "" -#: src/concurrency/shared_state/arc.md -msgid "" -"`Arc` implements `Clone` whether or not `T` does. It implements `Send` " -"and `Sync` if and only if `T` implements them both." +#: src/unsafe-deep-dive/pinning.md +msgid "How Rust implements it" msgstr "" -#: src/concurrency/shared_state/arc.md -msgid "" -"`Arc::clone()` has the cost of atomic operations that get executed, but " -"after that the use of the `T` is free." +#: src/unsafe-deep-dive/pinning.md +msgid "How it interacts with unsafe and FFI" msgstr "" -#: src/concurrency/shared_state/arc.md -msgid "" -"Beware of reference cycles, `Arc` does not use a garbage collector to detect " -"them." +#: src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "This segment should take about 1 hour and 20 minutes. It contains:" msgstr "" -#: src/concurrency/shared_state/arc.md -msgid "`std::sync::Weak` can help." +#: src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/definition-of-pin.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "Definition of Pin" msgstr "" -#: src/concurrency/shared_state/mutex.md -msgid "" -"[`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) ensures " -"mutual exclusion _and_ allows mutable access to `T` behind a read-only " -"interface (another form of [interior mutability](../../borrowing/interior-" -"mutability)):" +#: src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/phantompinned.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "PhantomPinned" msgstr "" -#: src/concurrency/shared_state/mutex.md -msgid "\"v: {:?}\"" +#: src/unsafe-deep-dive/pinning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "Pin and Drop" msgstr "" -#: src/concurrency/shared_state/mutex.md +#: src/unsafe-deep-dive/pinning.md msgid "" -"Notice how we have a [`impl Sync for Mutex`](https://doc.rust-" -"lang.org/std/sync/struct.Mutex.html#impl-Sync-for-Mutex%3CT%3E) blanket " -"implementation." +"\"Pinning, or holding a value's memory address in a fixed location,is one of " +"the more challenging concepts in Rust.\"" msgstr "" -#: src/concurrency/shared_state/mutex.md +#: src/unsafe-deep-dive/pinning.md msgid "" -"`Mutex` in Rust looks like a collection with just one element --- the " -"protected data." +"\"Normally only seen within async code, i.e. [`poll(self: Pin<&mut Self>)`]" +"(https://doc.rust-lang.org/std/future/trait.Future.html#tymethod.poll), " +"pinning has wider applicability.\"" msgstr "" -#: src/concurrency/shared_state/mutex.md +#: src/unsafe-deep-dive/pinning.md msgid "" -"It is not possible to forget to acquire the mutex before accessing the " -"protected data." +"Some data structures that are difficult or impossible to write without the " +"unsafe keyword, including self-referential structs and intrusive data " +"structures." msgstr "" -#: src/concurrency/shared_state/mutex.md +#: src/unsafe-deep-dive/pinning.md msgid "" -"You can get an `&mut T` from an `&Mutex` by taking the lock. The " -"`MutexGuard` ensures that the `&mut T` doesn't outlive the lock being held." +"FFI with C++ is a prominent use case that's related to this. Rust must " +"assume that any C++ with a reference might be a self-referential data " +"structure." msgstr "" -#: src/concurrency/shared_state/mutex.md +#: src/unsafe-deep-dive/pinning.md msgid "" -"`Mutex` implements both `Send` and `Sync` iff (if and only if) `T` " -"implements `Send`." +"\"To understand this conflict in more detail, we'll first need to make sure " +"that we have a strong understanding of Rust's move semantics.\"" msgstr "" -#: src/concurrency/shared_state/mutex.md -msgid "A read-write lock counterpart: `RwLock`." +#: src/unsafe-deep-dive/pinning/what-pinning-is.md +msgid "A pinned type cannot change its memory address (move)" msgstr "" -#: src/concurrency/shared_state/mutex.md -msgid "Why does `lock()` return a `Result`?" +#: src/unsafe-deep-dive/pinning/what-pinning-is.md +msgid "The pointed-to value cannot be moved by safe code" msgstr "" -#: src/concurrency/shared_state/mutex.md +#: src/unsafe-deep-dive/pinning/what-pinning-is.md msgid "" -"If the thread that held the `Mutex` panicked, the `Mutex` becomes " -"\"poisoned\" to signal that the data it protected might be in an " -"inconsistent state. Calling `lock()` on a poisoned mutex fails with a " -"[`PoisonError`](https://doc.rust-lang.org/std/sync/struct.PoisonError.html). " -"You can call `into_inner()` on the error to recover the data regardless." +"`Pin` makes use of the ownership system to control how the pinned value " +"is accessed. Rather than changing the language, Rust's ownership system is " +"used to enforce pinning. `Pin` owns its contents and nothing in its safe API " +"triggers a move." msgstr "" -#: src/concurrency/shared_state/example.md -msgid "Let us see `Arc` and `Mutex` in action:" +#: src/unsafe-deep-dive/pinning/what-pinning-is.md +msgid "This is explained in" msgstr "" -#: src/concurrency/shared_state/example.md -msgid "// use std::sync::{Arc, Mutex};" +#: src/unsafe-deep-dive/pinning/what-pinning-is.md +msgid "Conceptually, pinning prevents the default movement behavior." msgstr "" -#: src/concurrency/shared_state/example.md -msgid "Possible solution:" +#: src/unsafe-deep-dive/pinning/what-pinning-is.md +msgid "This appears to be a change in the language itself." msgstr "" -#: src/concurrency/shared_state/example.md -msgid "Notable parts:" +#: src/unsafe-deep-dive/pinning/what-pinning-is.md +msgid "" +"However, the `Pin` wrapper doesn't actually change anything fundamental " +"about the language." msgstr "" -#: src/concurrency/shared_state/example.md +#: src/unsafe-deep-dive/pinning/what-pinning-is.md msgid "" -"`v` is wrapped in both `Arc` and `Mutex`, because their concerns are " -"orthogonal." +"`Pin` doesn't expose safe APIs that would allow a move. Thus, it can prevent " +"bitwise copy." msgstr "" -#: src/concurrency/shared_state/example.md +#: src/unsafe-deep-dive/pinning/what-pinning-is.md msgid "" -"Wrapping a `Mutex` in an `Arc` is a common pattern to share mutable state " -"between threads." +"Unsafe APIs allow library authors to wrap types that do not implement " +"`Unpin`, but they must uphold the same guarantees." +msgstr "" + +#: src/unsafe-deep-dive/pinning/what-pinning-is.md +msgid "The documentation of `Pin` uses the term \"pointer types\"." msgstr "" -#: src/concurrency/shared_state/example.md +#: src/unsafe-deep-dive/pinning/what-pinning-is.md msgid "" -"`v: Arc<_>` needs to be cloned as `v2` before it can be moved into another " -"thread. Note `move` was added to the lambda signature." +"The term \"pointer type\" is much more broad than the pointer primitive type " +"in the language." msgstr "" -#: src/concurrency/shared_state/example.md +#: src/unsafe-deep-dive/pinning/what-pinning-is.md msgid "" -"Blocks are introduced to narrow the scope of the `LockGuard` as much as " -"possible." +"A \"pointer type\" wraps every type that implements `Deref` with a target " +"that implements `Unpin`." msgstr "" -#: src/exercises/concurrency/morning.md -msgid "Let us practice our new concurrency skills with" +#: src/unsafe-deep-dive/pinning/what-pinning-is.md +msgid "" +"Rust style note: This trait bound is enforced through trait bounds on the `::" +"new()` constructor, rather than on the type itself." msgstr "" -#: src/exercises/concurrency/morning.md -msgid "Dining philosophers: a classic problem in concurrency." +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "What a move is in Rust" msgstr "" -#: src/exercises/concurrency/morning.md -msgid "" -"Multi-threaded link checker: a larger project where you'll use Cargo to " -"download dependencies and then check links in parallel." +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "Always a bitwise copy, even for types that do not implement `Copy`:" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -msgid "The dining philosophers problem is a classic problem in concurrency:" +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "b'R'" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -msgid "" -"Five philosophers dine together at the same table. Each philosopher has " -"their own place at the table. There is a fork between each plate. The dish " -"served is a kind of spaghetti which has to be eaten with two forks. Each " -"philosopher can only alternately think and eat. Moreover, a philosopher can " -"only eat their spaghetti when they have both a left and right fork. Thus two " -"forks will only be available when their two nearest neighbors are thinking, " -"not eating. After an individual philosopher finishes eating, they will put " -"down both forks." +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "b'U'" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -msgid "" -"You will need a local [Cargo installation](../../cargo/running-locally.md) " -"for this exercise. Copy the code below to a file called `src/main.rs`, fill " -"out the blanks, and test that `cargo run` does not deadlock:" +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "b'S'" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "// left_fork: ..." +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "b'T'" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "// right_fork: ..." +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "" +"Generated [LLVM IR](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2024&gist=6f587283e8e0ec02f1ea8e871fc9ac72) " +"for calling `move_and_expect()`:" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "// thoughts: ..." +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "`memcpy` from variable `%b` to `%_12`" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/solutions-morning.md -#: src/exercises/concurrency/dining-philosophers-async.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"Eureka! {} has a new idea!\"" +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "Call to `move_and_inspect` with `%_12` (the copy)" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -msgid "// Pick up forks..." +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "Note that `DynamicBuffer` does not implement `Copy`." msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/solutions-morning.md -#: src/exercises/concurrency/dining-philosophers-async.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"{} is eating...\"" +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "Implication: a value's memory address is not stable." msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/solutions-morning.md -#: src/exercises/concurrency/dining-philosophers-async.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"Socrates\"" +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "" +"To show movement as a bitwise copy, either [open the code in the playground]" +"(https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2024&gist=6f587283e8e0ec02f1ea8e871fc9ac72) " +"and look at the or [the Compiler Explorer](https://rust.godbolt.org/" +"z/6o6nP7do4)." msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/solutions-morning.md -#: src/exercises/concurrency/dining-philosophers-async.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"Hypatia\"" +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "Optional for those who prefer assembly output:" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/solutions-morning.md -#: src/exercises/concurrency/dining-philosophers-async.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"Plato\"" +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "" +"The Compiler Explorer is useful for discussing the generated assembly and " +"focus the cursor assembly output in the `main` function on lines 128-136 " +"(should be highlighted in pink)." msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/solutions-morning.md -#: src/exercises/concurrency/dining-philosophers-async.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"Aristotle\"" +#: src/unsafe-deep-dive/pinning/what-a-move-is.md +msgid "Relevant code generated output `move_and_inspect`:" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/solutions-morning.md -#: src/exercises/concurrency/dining-philosophers-async.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"Pythagoras\"" +#: src/unsafe-deep-dive/pinning/definition-of-pin.md +msgid "" +"`Pin` is a minimal wrapper around a _pointer type_, which is defined as a " +"type that implements `Deref`." msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "// Create forks" +#: src/unsafe-deep-dive/pinning/definition-of-pin.md +msgid "" +"However, `Pin::new()` only accepts types that dereference into a target that " +"implements `Unpin` (`Deref`). This allows `Pin` to rely on " +"the type system to enforce its guarantees." msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "// Create philosophers" +#: src/unsafe-deep-dive/pinning/definition-of-pin.md +msgid "" +"Types that do not implement `Unpin`, i.e., types that require pinning, must " +"create a `Pin` via the unsafe `Pin::new_unchecked()`." msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -msgid "// Make each of them think and eat 100 times" +#: src/unsafe-deep-dive/pinning/definition-of-pin.md +msgid "" +"Aside: Unlike other `new()`/`new_unchecked()` method pairs, `new` does not " +"do any runtime checking. The check is a zero-cost compile-time check." msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "// Output their thoughts" +#: src/unsafe-deep-dive/pinning/why-difficult.md +msgid "Why Pin is difficult to use" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md -msgid "You can use the following `Cargo.toml`:" +#: src/unsafe-deep-dive/pinning/why-difficult.md +msgid "`Pin` is \"just\" a type defined in the standard library" msgstr "" -#: src/exercises/concurrency/dining-philosophers.md +#: src/unsafe-deep-dive/pinning/why-difficult.md msgid "" -"```toml\n" -"[package]\n" -"name = \"dining-philosophers\"\n" -"version = \"0.1.0\"\n" -"edition = \"2021\"\n" -"```" +"This satisfied the needs of its original audience, the creators of async " +"runtimes, without needing to extending the core language" msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/why-difficult.md msgid "" -"Let us use our new knowledge to create a multi-threaded link checker. It " -"should start at a webpage and check that links on the page are valid. It " -"should recursively check other pages on the same domain and keep doing this " -"until all pages have been validated." +"That audience could accept some of its ergonomic downsides, as users of " +"`async` would rarely interact with `Pin` directly" msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/why-difficult.md msgid "" -"For this, you will need an HTTP client such as [`reqwest`](https://docs.rs/" -"reqwest/). Create a new Cargo project and `reqwest` it as a dependency with:" +"\"You might wonder why Pin is so awkward to use. The answer is largely " +"historical.\"" msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/why-difficult.md msgid "" -"If `cargo add` fails with `error: no such subcommand`, then please edit the " -"`Cargo.toml` file by hand. Add the dependencies listed below." +"\"`Pin` offered a simpler implementation for the Rust project than " +"alternatives\"." msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/why-difficult.md msgid "" -"You will also need a way to find links. We can use [`scraper`](https://docs." -"rs/scraper/) for that:" +"\"Pin was designed primarily for the ~100 people in the world who write " +"async runtimes. The Rust team chose a simpler (for the compiler) but less " +"ergonomic design.\"" msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/why-difficult.md msgid "" -"Finally, we'll need some way of handling errors. We use [`thiserror`]" -"(https://docs.rs/thiserror/) for that:" +"\"More user-friendly proposals existed but were rejected as too complex for " +"the primary audience, who could handle the complexity.\"" +msgstr "" + +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "Unpin trait" msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/unpin-trait.md msgid "" -"The `cargo add` calls will update the `Cargo.toml` file to look like this:" +"`Unpin` type allows types to move freely, even when they're wrapped by a " +"`Pin`" msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "Most types implement `Unpin`, because it is an \"`auto trait`\"" +msgstr "" + +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "`auto trait` behavior can be changed:" +msgstr "" + +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "`!Unpin` types must never move" +msgstr "" + +#: src/unsafe-deep-dive/pinning/unpin-trait.md msgid "" -"```toml\n" -"[package]\n" -"name = \"link-checker\"\n" -"version = \"0.1.0\"\n" -"edition = \"2021\"\n" -"publish = false\n" -"\n" -"[dependencies]\n" -"reqwest = { version = \"0.11.12\", features = [\"blocking\", \"rustls-" -"tls\"] }\n" -"scraper = \"0.13.0\"\n" -"thiserror = \"1.0.37\"\n" -"```" +"Types containing a `PhantomPinned` field do not implement `Unpin` by default" msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/unpin-trait.md msgid "" -"You can now download the start page. Try with a small site such as `https://" -"www.google.org/`." +"Explain that when a trait implements `Unpin`, the pinning behavior of " +"`Pin` does not get invoked. The value is free to move." msgstr "" -#: src/exercises/concurrency/link-checker.md -msgid "Your `src/main.rs` file should look something like this:" +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "" +"Explain that almost all types implement `Unpin`; automatically implemented " +"by the compiler." msgstr "" -#: src/exercises/concurrency/link-checker.md -#: src/exercises/concurrency/solutions-morning.md -msgid "\"request error: {0}\"" +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "" +"Types implementing `Unpin` are saying: 'I promise I have no self-references, " +"so moving me is always safe.'" msgstr "" -#: src/exercises/concurrency/link-checker.md -#: src/exercises/concurrency/solutions-morning.md -msgid "\"bad http response: {0}\"" +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "Ask: What types might be `!Unpin`?" msgstr "" -#: src/exercises/concurrency/link-checker.md -#: src/exercises/concurrency/solutions-morning.md -msgid "\"Checking {:#}\"" +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "Compiler-generated futures" msgstr "" -#: src/exercises/concurrency/link-checker.md -#: src/exercises/concurrency/solutions-morning.md -msgid "\"href\"" +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "Types containing a `PhantomPinned` field" msgstr "" -#: src/exercises/concurrency/link-checker.md -#: src/exercises/concurrency/solutions-morning.md -msgid "\"On {base_url:#}: ignored unparsable {href:?}: {err}\"" +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "Some types wrapping C++ objects" msgstr "" -#: src/exercises/concurrency/link-checker.md -#: src/exercises/concurrency/solutions-morning.md -msgid "\"https://www.google.org\"" +#: src/unsafe-deep-dive/pinning/unpin-trait.md +msgid "`!Unpin` types cannot be moved once pinned" msgstr "" -#: src/exercises/concurrency/link-checker.md -msgid "\"Links: {links:#?}\"" +#: src/unsafe-deep-dive/pinning/phantompinned.md +msgid "Definition" msgstr "" -#: src/exercises/concurrency/link-checker.md -msgid "\"Could not extract links: {err:#}\"" +#: src/unsafe-deep-dive/pinning/phantompinned.md +msgid "Usage" msgstr "" -#: src/exercises/concurrency/link-checker.md -msgid "Run the code in `src/main.rs` with" +#: src/unsafe-deep-dive/pinning/phantompinned.md +msgid "`PhantomPinned` is a marker type." msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/phantompinned.md msgid "" -"Use threads to check the links in parallel: send the URLs to be checked to a " -"channel and let a few threads check the URLs in parallel." +"If a type contains a `PhantomPinned`, it will not implement `Unpin` by " +"default." msgstr "" -#: src/exercises/concurrency/link-checker.md +#: src/unsafe-deep-dive/pinning/phantompinned.md msgid "" -"Extend this to recursively extract links from all pages on the `www.google." -"org` domain. Put an upper limit of 100 pages or so so that you don't end up " -"being blocked by the site." +"This has the effect of enforcing pinning when `DynamicBuffer` is wrapped by " +"`Pin`." msgstr "" -#: src/exercises/concurrency/solutions-morning.md -msgid "Concurrency Morning Exercise" +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "" +"A \"self-referential buffer\" is a type that has a reference to one of its " +"own fields:" msgstr "" -#: src/exercises/concurrency/solutions-morning.md -msgid "([back to exercise](dining-philosophers.md))" +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "" +"This kind of structure is not typical in Rust, because there's no way to " +"update the cursor's address when instances of `SelfReferentialBuffer` move." msgstr "" -#: src/exercises/concurrency/solutions-morning.md -msgid "\"{} is trying to eat\"" +#: src/unsafe-deep-dive/pinning/self-referential-buffer.md +msgid "" +"However, this kind of setup is more natural in other languages that provide " +"garbage collection, and also C++ that allows users to define their own " +"behavior during moves and copies." msgstr "" -#: src/exercises/concurrency/solutions-morning.md -msgid "" -"// To avoid a deadlock, we have to break the symmetry\n" -" // somewhere. This will swap the forks without deinitializing\n" -" // either of them.\n" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/cpp.md +msgid "Modelled in C++" msgstr "" -#: src/exercises/concurrency/solutions-morning.md -msgid "\"{thought}\"" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/cpp.md +msgid "" msgstr "" -#: src/exercises/concurrency/solutions-morning.md -#, fuzzy -msgid "Link Checker" -msgstr "āĻŽāĻžāĻ˛ā§āϟāĻŋ āĻĨā§āϰ⧇āĻĄā§‡āĻĄ āϞāĻŋāĻ™ā§āĻ• āĻšā§‡āĻ•āĻžāϰ" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/cpp.md +msgid "" +msgstr "" -#: src/exercises/concurrency/solutions-morning.md -msgid "([back to exercise](link-checker.md))" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/cpp.md +msgid "Investigate on [Compiler Explorer](https://godbolt.org/z/ascME6aje)" msgstr "" -#: src/exercises/concurrency/solutions-morning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/cpp.md msgid "" -"/// Determine whether links within the given page should be extracted.\n" +"The `SelfReferentialBuffer` contains two members, `data` is a kilobyte of " +"memory and `cursor` is a pointer into the former." msgstr "" -#: src/exercises/concurrency/solutions-morning.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/cpp.md msgid "" -"/// Mark the given page as visited, returning false if it had already\n" -" /// been visited.\n" +"Its move constructor ensures that cursor is updated to the new memory " +"address." msgstr "" -#: src/exercises/concurrency/solutions-morning.md -msgid "// The sender got dropped. No more commands coming in.\n" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/cpp.md +msgid "This type can't be expressed easily in Rust." msgstr "" -#: src/exercises/concurrency/solutions-morning.md -msgid "\"Got crawling error: {:#}\"" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md +msgid "/// Raw pointers\n" msgstr "" -#: src/exercises/concurrency/solutions-morning.md -msgid "\"Bad URLs: {:#?}\"" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md +msgid "/// Integer offsets\n" msgstr "" -#: src/async.md -msgid "Async Rust" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md +msgid "/// Pinning\n" msgstr "" -#: src/async.md -msgid "" -"\"Async\" is a concurrency model where multiple tasks are executed " -"concurrently by executing each task until it would block, then switching to " -"another task that is ready to make progress. The model allows running a " -"larger number of tasks on a limited number of threads. This is because the " -"per-task overhead is typically very low and operating systems provide " -"primitives for efficiently identifying I/O that is able to proceed." +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md +msgid "Original C++ class definition for reference" msgstr "" -#: src/async.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md msgid "" -"Rust's asynchronous operation is based on \"futures\", which represent work " -"that may be completed in the future. Futures are \"polled\" until they " -"signal that they are complete." +"The next few slides show three approaches to creating a Rust type with the " +"same semantics as the original C++." msgstr "" -#: src/async.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md msgid "" -"Futures are polled by an async runtime, and several different runtimes are " -"available." +"Using raw pointers: matches C++ very closely, but using the resulting type " +"is extremely hazardous" msgstr "" -#: src/async.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md msgid "" -"Python has a similar model in its `asyncio`. However, its `Future` type is " -"callback-based, and not polled. Async Python programs require a \"loop\", " -"similar to a runtime in Rust." +"Storing integer offsets: more natural in Rust, but references need to be " +"created manually" msgstr "" -#: src/async.md -msgid "" -"JavaScript's `Promise` is similar, but again callback-based. The language " -"runtime implements the event loop, so many of the details of Promise " -"resolution are hidden." +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust.md +msgid "Pinning: allows raw pointers with fewer `unsafe` blocks" msgstr "" -#: src/async/async-await.md -msgid "" -"At a high level, async Rust code looks very much like \"normal\" sequential " -"code:" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +msgid "// Danger: must be called after every move\n" msgstr "" -#: src/async/async-await.md -msgid "\"Count is: {i}!\"" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-pin.md +msgid "\"cursor is out of bounds\"" msgstr "" -#: src/async/async-await.md -msgid "" -"Note that this is a simplified example to show the syntax. There is no long " -"running operation or any real concurrency in it!" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +msgid "Avoid spending too much time here." msgstr "" -#: src/async/async-await.md -msgid "What is the return type of an async call?" +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +msgid "Talking points:" msgstr "" -#: src/async/async-await.md -msgid "Use `let future: () = async_main(10);` in `main` to see the type." +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +msgid "" +"Emphasize that `unsafe` appears frequently. This is a hint that another " +"design may be more appropriate." msgstr "" -#: src/async/async-await.md -msgid "" -"The \"async\" keyword is syntactic sugar. The compiler replaces the return " -"type with a future." +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +msgid "`unsafe` blocks lack safety comments. Therefore, this code is unsound." msgstr "" -#: src/async/async-await.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md msgid "" -"You cannot make `main` async, without additional instructions to the " -"compiler on how to use the returned future." +"`unsafe` blocks are too broad. Good practice uses smaller `unsafe` blocks " +"with specific behavior, specific preconditions and specific safety comments." msgstr "" -#: src/async/async-await.md -msgid "" -"You need an executor to run async code. `block_on` blocks the current thread " -"until the provided future has run to completion." +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md +msgid "Questions:" msgstr "" -#: src/async/async-await.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-raw-pointers.md msgid "" -"`.await` asynchronously waits for the completion of another operation. " -"Unlike `block_on`, `.await` doesn't block the current thread." +"Q: Should the `read()` and `write()` methods be marked as unsafe? \n" +"A: Yes, because `self.cursor` will be a null pointer unless written to." msgstr "" -#: src/async/async-await.md -msgid "" -"`.await` can only be used inside an `async` function (or block; these are " -"introduced later)." +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-offset.md +msgid "With Offset" msgstr "" -#: src/async/futures.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-offset.md msgid "" -"[`Future`](https://doc.rust-lang.org/std/future/trait.Future.html) is a " -"trait, implemented by objects that represent an operation that may not be " -"complete yet. A future can be polled, and `poll` returns a [`Poll`](https://" -"doc.rust-lang.org/std/task/enum.Poll.html)." +"In Rust, it's more idiomatic to use an offset variable and to create " +"references on-demand." msgstr "" -#: src/async/futures.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-pin.md msgid "" -"An async function returns an `impl Future`. It's also possible (but " -"uncommon) to implement `Future` for your own types. For example, the " -"`JoinHandle` returned from `tokio::spawn` implements `Future` to allow " -"joining to it." +"Pinning allows Rust programmers to create a type which is much more similar " +"to C++ classes." msgstr "" -#: src/async/futures.md -msgid "" -"The `.await` keyword, applied to a Future, causes the current async function " -"to pause until that Future is ready, and then evaluates to its output." +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-pin.md +msgid "/// A self-referential buffer that cannot be moved.\n" msgstr "" -#: src/async/futures.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-pin.md msgid "" -"The `Future` and `Poll` types are implemented exactly as shown; click the " -"links to show the implementations in the docs." +"Note that the function signatures have now changed. For example, `::new()` " +"returns `Pin>` rather than `Self`. This incurs a heap allocation " +"because `Pin` must work with a pointer type like `Box`." msgstr "" -#: src/async/futures.md +#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-pin.md msgid "" -"We will not get to `Pin` and `Context`, as we will focus on writing async " -"code, rather than building new async primitives. Briefly:" +"In `::new()`, we use `Pin::get_unchecked_mut()` to get a mutable reference " +"to the buffer _after_ it has been pinned. This is `unsafe` because we are " +"breaking the pinning guarantee for a moment to initialize the `cursor`. We " +"must make sure not to move the `SelfReferentialBuffer` after this point. The " +"safety contract of `Pin` is that once a value is pinned, its memory location " +"is fixed until it is dropped." msgstr "" -#: src/async/futures.md -msgid "" -"`Context` allows a Future to schedule itself to be polled again when an " -"event occurs." +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "Pin\\ and Drop" msgstr "" -#: src/async/futures.md +#: src/unsafe-deep-dive/pinning/pin-and-drop.md msgid "" -"`Pin` ensures that the Future isn't moved in memory, so that pointers into " -"that future remain valid. This is required to allow references to remain " -"valid after an `.await`." +"A key challenge with pinned, `!Unpin` types is implementing the `Drop` " +"trait. The `drop` method takes `&mut self`, which allows moving the value. " +"However, pinned values must not be moved." msgstr "" -#: src/async/runtimes.md -msgid "" -"A _runtime_ provides support for performing operations asynchronously (a " -"_reactor_) and is responsible for executing futures (an _executor_). Rust " -"does not have a \"built-in\" runtime, but several options are available:" +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "An Incorrect `Drop` Implementation" msgstr "" -#: src/async/runtimes.md +#: src/unsafe-deep-dive/pinning/pin-and-drop.md msgid "" -"[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." +"It's easy to accidentally move a value inside `drop`. Operations like " +"assignment, `ptr::read`, and `mem::replace` can silently break the pinning " +"guarantee." msgstr "" -#: src/async/runtimes.md +#: src/unsafe-deep-dive/pinning/pin-and-drop.md msgid "" -"[async-std](https://async.rs/): aims to be a \"std for async\", and includes " -"a basic runtime in `async::task`." +"// BAD: `ptr::read` moves `self.data` out of `self`.\n" +" // When `_dupe` is dropped at the end of the function, it's a double " +"free!\n" msgstr "" -#: src/async/runtimes.md -msgid "[smol](https://docs.rs/smol/latest/smol/): simple and lightweight" +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "" +"Pinned types make guarantees about memory stability. Operations like `ptr::" +"read` and `mem::replace` can silently break these guarantees by moving or " +"duplicating data, invalidating internal pointers without the type system's " +"knowledge." msgstr "" -#: src/async/runtimes.md +#: src/unsafe-deep-dive/pinning/pin-and-drop.md msgid "" -"Several larger applications have their own runtimes. For example, [Fuchsia]" -"(https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/lib/fuchsia-" -"async/src/lib.rs) already has one." +"In this `drop()` method, `_dupe` is a bitwise copy of `self.data`. At the " +"end of the method, it will be dropped along with `self`. This double drop is " +"undefined behavior." msgstr "" -#: src/async/runtimes.md -msgid "" -"Note that of the listed runtimes, only Tokio is supported in the Rust " -"playground. The playground also does not permit any I/O, so most interesting " -"async things can't run in the playground." +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "A Correct `Drop` Implementation" msgstr "" -#: src/async/runtimes.md +#: src/unsafe-deep-dive/pinning/pin-and-drop.md msgid "" -"Futures are \"inert\" in that they do not do anything (not even start an I/O " -"operation) unless there is an executor polling them. This differs from JS " -"Promises, for example, which will run to completion even if they are never " -"used." +"To implement `Drop` correctly for a `!Unpin` type, you must ensure that the " +"value is not moved. A common pattern is to create a helper function that " +"operates on `Pin<&mut T>`." msgstr "" -#: src/async/runtimes/tokio.md -msgid "Tokio provides:" +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "// SAFETY: `this` is pinned before we create the self-reference.\n" msgstr "" -#: src/async/runtimes/tokio.md -msgid "A multi-threaded runtime for executing asynchronous code." +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "// This function can only be called on a pinned `SelfRef`.\n" msgstr "" -#: src/async/runtimes/tokio.md -msgid "An asynchronous version of the standard library." +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "// `self` is pinned, so we must not move out of it.\n" msgstr "" -#: src/async/runtimes/tokio.md -msgid "A large ecosystem of libraries." +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "\"dropping {}\"" msgstr "" -#: src/async/runtimes/tokio.md -msgid "\"Count in task: {i}!\"" +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "" +"// We can safely call `drop_pinned` because `drop` is the last time\n" +" // the value is used. We use `new_unchecked` because we know `self`\n" +" // will not be moved again.\n" msgstr "" -#: src/async/runtimes/tokio.md -msgid "\"Main task: {i}\"" +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "\"Hello, \"" msgstr "" -#: src/async/runtimes/tokio.md -msgid "With the `tokio::main` macro we can now make `main` async." +#: src/unsafe-deep-dive/pinning/pin-and-drop.md +msgid "// `Drop` runs without moving the pinned value\n" msgstr "" -#: src/async/runtimes/tokio.md -msgid "The `spawn` function creates a new, concurrent \"task\"." +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "Worked Example: Implementing `Drop` for `!Unpin` types" +msgstr "" + +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "// SAFETY: Safe because we are reading bytes from a String\n" msgstr "" -#: src/async/runtimes/tokio.md -msgid "Note: `spawn` takes a `Future`, you don't call `.await` on `count_to`." +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "\"Rust đŸĻ€\"" msgstr "" -#: src/async/runtimes/tokio.md -msgid "**Further exploration:**" +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "\"Batch: {:?}\"" msgstr "" -#: src/async/runtimes/tokio.md +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md msgid "" -"Why does `count_to` not (usually) get to 10? This is an example of async " -"cancellation. `tokio::spawn` returns a handle which can be awaited to wait " -"until it finishes." +"This example uses the `Drop` trait to add data for some post-processing, " +"such as telemetry or logging." msgstr "" -#: src/async/runtimes/tokio.md -msgid "Try `count_to(10).await` instead of spawning." +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "" +"**The Safety comment is incorrect.** `ptr::read` creates a bitwise copy, " +"leaving `self.data` in an invalid state. `self.data` will be dropped again " +"at the end of the method, which is a double free." msgstr "" -#: src/async/runtimes/tokio.md -msgid "Try awaiting the task returned from `tokio::spawn`." +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "Ask the class to fix the code." msgstr "" -#: src/async/tasks.md -msgid "Rust has a task system, which is a form of lightweight threading." +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "**Suggestion 0: Redesign**" msgstr "" -#: src/async/tasks.md -msgid "" -"A task has a single top-level future which the executor polls to make " -"progress. That future may have one or more nested futures that its `poll` " -"method polls, corresponding loosely to a call stack. Concurrency within a " -"task is possible by polling multiple child futures, such as racing a timer " -"and an I/O operation." +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "Redesign the post-processing system to work without `Drop`." msgstr "" -#: src/async/tasks.md -msgid "\"127.0.0.1:0\"" +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "**Suggestion 1: Clone**" msgstr "" -#: src/async/tasks.md -msgid "\"listening on port {}\"" +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "Using `.clone()` is an obvious first choice, but it allocates memory." msgstr "" -#: src/async/tasks.md -msgid "\"connection from {addr:?}\"" +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "**Suggestion 2: ManuallyDrop**" msgstr "" -#: src/async/tasks.md -msgid "b\"Who are you?\\n\"" +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "" +"Wrapping `CustomString` in `ManuallyDrop` prevents the (second) automatic " +"drop at the end of the `Drop` impl." msgstr "" -#: src/async/tasks.md -msgid "\"socket error\"" +#: src/unsafe-deep-dive/pinning/drop-and-not-unpin-worked-example.md +msgid "// SAFETY: self.data\n" msgstr "" -#: src/async/tasks.md -msgid "\"Thanks for dialing in, {name}!\\n\"" +#: src/unsafe-deep-dive/ffi/language-interop.md +msgid "Ideal scenario:" msgstr "" -#: src/async/tasks.md src/async/control-flow/join.md +#: src/unsafe-deep-dive/ffi/language-interop.md +#: src/unsafe-deep-dive/ffi/strategies.md msgid "" -"Copy this example into your prepared `src/main.rs` and run it from there." +"```bob\n" +"╭────────────╮ ╭────────────╮\n" +"│ │ │ │\n" +"│ │ <--------------------------------------> │ │\n" +"│ │ │ │\n" +"╰────────────╯ ╰────────────╯\n" +" Rust \"C++\"\n" +"```" msgstr "" -#: src/async/tasks.md +#: src/unsafe-deep-dive/ffi/language-interop.md msgid "" -"Try connecting to it with a TCP connection tool like [nc](https://www.unix." -"com/man-page/linux/1/nc/) or [telnet](https://www.unix.com/man-page/linux/1/" -"telnet/)." +"This section of the course covers interacting with Rust and external " +"languages via its foreign-function interface (FFI), with a special focus on " +"interoperability with C++." msgstr "" -#: src/async/tasks.md +#: src/unsafe-deep-dive/ffi/language-interop.md msgid "" -"Ask students to visualize what the state of the example server would be with " -"a few connected clients. What tasks exist? What are their Futures?" +"Ideally, users of Rust and the external language (in this case C++) could " +"call each others’ methods directly." msgstr "" -#: src/async/tasks.md -msgid "" -"This is the first time we've seen an `async` block. This is similar to a " -"closure, but does not take any arguments. Its return value is a Future, " -"similar to an `async fn`." +#: src/unsafe-deep-dive/ffi/language-interop.md +msgid "This ideal scenario is very difficult to achieve:" msgstr "" -#: src/async/tasks.md +#: src/unsafe-deep-dive/ffi/language-interop.md msgid "" -"Refactor the async block into a function, and improve the error handling " -"using `?`." +"Different languages have different semantics and mapping between them " +"implies trade-offs Neither Rust nor C++ offer ABI stability[^1], making it " +"difficult to build from a stable foundation" msgstr "" -#: src/async/channels.md +#: src/unsafe-deep-dive/ffi/language-interop.md msgid "" -"Several crates have support for asynchronous channels. For instance `tokio`:" +"Some C++ compiler vendors provide support for ABI stability within their " +"toolchain." msgstr "" -#: src/async/channels.md -msgid "\"Received {count} pings so far.\"" +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "Strategies of interop" msgstr "" -#: src/async/channels.md -msgid "\"ping_handler complete\"" +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "Sharing data structures and symbols directly is very difficult:" msgstr "" -#: src/async/channels.md -msgid "\"Failed to send ping.\"" +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "FFI through the C ABI is much more feasible:" msgstr "" -#: src/async/channels.md -msgid "\"Sent {} pings so far.\"" +#: src/unsafe-deep-dive/ffi/strategies.md +#: src/unsafe-deep-dive/ffi/language-differences.md +msgid "" +"````````bob\n" +"╭────────────╮ ╭───╮ ╭───╮ ╭────────────╮\n" +"│ │ │ │ │ │ │ │\n" +"│ │ <-----> │ │ <~~~~~~~> │ │ <------> │ │ \n" +"│ │ │ │ │ │ │ │\n" +"╰────────────╯ ╰───╯ ╰───╯ ╰────────────╯\n" +" Rust C C \"C++\"\n" +"````````" msgstr "" -#: src/async/channels.md -msgid "\"Something went wrong in ping handler task.\"" +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "Other strategies:" msgstr "" -#: src/async/channels.md -msgid "Change the channel size to `3` and see how it affects the execution." +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "Distributed system (RPC)" msgstr "" -#: src/async/channels.md -msgid "" -"Overall, the interface is similar to the `sync` channels as seen in the " -"[morning class](concurrency/channels.md)." +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "Custom ABI (i.e. WebAssembly Interface Types)" msgstr "" -#: src/async/channels.md -msgid "Try removing the `std::mem::drop` call. What happens? Why?" +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "_High-fidelity interop_" msgstr "" -#: src/async/channels.md -msgid "" -"The [Flume](https://docs.rs/flume/latest/flume/) crate has channels that " -"implement both `sync` and `async` `send` and `recv`. This can be convenient " -"for complex applications with both IO and heavy CPU processing tasks." +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "The ideal scenario is currently experimental." msgstr "" -#: src/async/channels.md +#: src/unsafe-deep-dive/ffi/strategies.md msgid "" -"What makes working with `async` channels preferable is the ability to " -"combine them with other `future`s to combine them and create complex control " -"flow." +"Two projects exploring this are [crubit](https://github.com/google/crubit) " +"and [Zngur](https://hkalbasi.github.io/zngur/). The first provides glue code " +"on each side for enabling compatible types to work seamlessly across " +"domains. The second relies on dynamic dispatch and imports C++ objects into " +"Rust as trait objects." msgstr "" -#: src/async/control-flow.md -msgid "Futures Control Flow" +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "_Low-fidelity interop_ work through a C API" msgstr "" -#: src/async/control-flow.md +#: src/unsafe-deep-dive/ffi/strategies.md msgid "" -"Futures can be combined together to produce concurrent compute flow graphs. " -"We have already seen tasks, that function as independent threads of " -"execution." +"The typical strategy for interop is to use the C language as the interface. " +"C is a lossy codec. This strategy typically results in complicated code on " +"both sides." msgstr "" -#: src/async/control-flow.md -msgid "[Join](control-flow/join.md)" +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "_Other strategies_ are less viable in a zero cost environment." msgstr "" -#: src/async/control-flow.md -msgid "[Select](control-flow/select.md)" +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "_Distributed systems_ impose runtime costs." msgstr "" -#: src/async/control-flow/join.md +#: src/unsafe-deep-dive/ffi/strategies.md msgid "" -"A join operation waits until all of a set of futures are ready, and returns " -"a collection of their results. This is similar to `Promise.all` in " -"JavaScript or `asyncio.gather` in Python." +"They incur significant overhead as calling a method in a foreign library " +"incurs a round trip of serialization/transport/deserialization. Generally " +"speaking, a transparent RPC is not a good idea. There’s network in the " +"middle." msgstr "" -#: src/async/control-flow/join.md -msgid "\"https://google.com\"" +#: src/unsafe-deep-dive/ffi/strategies.md +msgid "" +"_Custom ABI_, such as wasm require a runtime or significant implementation " +"cost." msgstr "" -#: src/async/control-flow/join.md -msgid "\"https://httpbin.org/ip\"" +#: src/unsafe-deep-dive/ffi/language-differences.md +msgid "" +"Using C as the lowest common denominator means that lots of the richness " +"available to Rust and C++ is lost." msgstr "" -#: src/async/control-flow/join.md -msgid "\"https://play.rust-lang.org/\"" +#: src/unsafe-deep-dive/ffi/language-differences.md +msgid "" +"Each translation has the potential for semantic loss, runtime overhead, and " +"subtle bugs." msgstr "" -#: src/async/control-flow/join.md -msgid "\"BAD_URL\"" +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "b\"Hello, C\\0\"" msgstr "" -#: src/async/control-flow/join.md -msgid "" -"For multiple futures of disjoint types, you can use `std::future::join!` but " -"you must know how many futures you will have at compile time. This is " -"currently in the `futures` crate, soon to be stabilised in `std::future`." +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "b\"Hello, C++\\0\"" msgstr "" -#: src/async/control-flow/join.md -msgid "" -"The risk of `join` is that one of the futures may never resolve, this would " -"cause your program to stall." +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "b\"Hello, Rust\"" msgstr "" -#: src/async/control-flow/join.md +#: src/unsafe-deep-dive/ffi/language-differences/representations.md msgid "" -"You can also combine `join_all` with `join!` for instance to join all " -"requests to an http service as well as a database query. Try adding a " -"`tokio::time::sleep` to the future, using `futures::join!`. This is not a " -"timeout (that requires `select!`, explained in the next chapter), but " -"demonstrates `join!`." +"Each language has its own opinion about how to implement things, which can " +"lead to confusion and bugs. Consider three ways to represent text." msgstr "" -#: src/async/control-flow/select.md -msgid "" -"A select operation waits until any of a set of futures is ready, and " -"responds to that future's result. In JavaScript, this is similar to `Promise." -"race`. In Python, it compares to `asyncio.wait(task_set, return_when=asyncio." -"FIRST_COMPLETED)`." +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "Show how to convert the raw representations to a Rust string slice:" msgstr "" -#: src/async/control-flow/select.md -msgid "" -"Similar to a match statement, the body of `select!` has a number of arms, " -"each of the form `pattern = future => statement`. When a `future` is ready, " -"its return value is destructured by the `pattern`. The `statement` is then " -"run with the resulting variables. The `statement` result becomes the result " -"of the `select!` macro." +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "// C representation to Rust\n" msgstr "" -#: src/async/control-flow/select.md -msgid "\"Felix\"" +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "\"{c}\"" msgstr "" -#: src/async/control-flow/select.md -msgid "\"Failed to send cat.\"" +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "// C++ representation to Rust \n" msgstr "" -#: src/async/control-flow/select.md -msgid "\"Rex\"" +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "\"{cc}\"" msgstr "" -#: src/async/control-flow/select.md -msgid "\"Failed to send dog.\"" +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "// Rust representation (bytes) to string slice\n" msgstr "" -#: src/async/control-flow/select.md -msgid "\"Failed to receive winner\"" +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "\"{rust}\"" msgstr "" -#: src/async/control-flow/select.md -msgid "\"Winner is {winner:?}\"" +#: src/unsafe-deep-dive/ffi/language-differences/representations.md +msgid "" +"Aside: Rust has a c-prefixed string literal. It appends a null byte at the " +"end, e.g. `c\"Rust\" == b\"Rust\\0\"`." msgstr "" -#: src/async/control-flow/select.md -msgid "" -"In this example, we have a race between a cat and a dog. " -"`first_animal_to_finish_race` listens to both channels and will pick " -"whichever arrives first. Since the dog takes 50ms, it wins against the cat " -"that take 500ms." +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md +msgid "/// Create a formatted time based on timestamp `t`.\n" msgstr "" -#: src/async/control-flow/select.md +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md msgid "" -"You can use `oneshot` channels in this example as the channels are supposed " -"to receive only one `send`." +"// SAFETY: `seconds` is generated by the system clock and will not cause\n" +" // overflow\n" msgstr "" -#: src/async/control-flow/select.md +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md msgid "" -"Try adding a deadline to the race, demonstrating selecting different sorts " -"of futures." +"// SAFETY: ctime returns a pointer to a preallocated (non-null) buffer\n" msgstr "" -#: src/async/control-flow/select.md -msgid "" -"Note that `select!` drops unmatched branches, which cancels their futures. " -"It is easiest to use when every execution of `select!` creates new futures." +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md +msgid "// SAFETY: ctime uses valid UTF-8\n" msgstr "" -#: src/async/control-flow/select.md -msgid "" -"An alternative is to pass `&mut future` instead of the future itself, but " -"this can lead to issues, further discussed in the pinning slide." +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md +msgid "\"{t:?}\"" msgstr "" -#: src/async/pitfalls.md -msgid "Pitfalls of async/await" +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md +msgid "" +"Some constructs that other languages allow cannot be expressed in the Rust " +"language." msgstr "" -#: src/async/pitfalls.md +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md msgid "" -"Async / await provides convenient and efficient abstraction for concurrent " -"asynchronous programming. However, the async/await model in Rust also comes " -"with its share of pitfalls and footguns. We illustrate some of them in this " -"chapter:" +"The `ctime` function modifies an internal buffer shared between calls. This " +"cannot be represented as Rust’s lifetimes." msgstr "" -#: src/async/pitfalls.md -msgid "[Blocking the Executor](pitfalls/blocking-executor.md)" +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md +msgid "`'static` does not apply, as the semantics are different" msgstr "" -#: src/async/pitfalls.md -msgid "[Pin](pitfalls/pin.md)" +#: src/unsafe-deep-dive/ffi/language-differences/semantics.md +msgid "`'a` does not apply, as the buffer outlives each call" msgstr "" -#: src/async/pitfalls.md -msgid "[Async Traits](pitfalls/async-traits.md)" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Concern" msgstr "" -#: src/async/pitfalls.md -msgid "[Cancellation](pitfalls/cancellation.md)" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Rust" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "Blocking the executor" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "C" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "" -"Most async runtimes only allow IO tasks to run concurrently. This means that " -"CPU blocking tasks will block the executor and prevent other tasks from " -"being executed. An easy workaround is to use async equivalent methods where " -"possible." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "**Errors**" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "\"future {id} slept for {duration_ms}ms, finished after {}ms\"" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "`Result`, `Option`" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "\"current_thread\"" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Magic return values, out-parameters, global `errno`" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "" -"Run the code and see that the sleeps happen consecutively rather than " -"concurrently." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "**Strings**" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "" -"The `\"current_thread\"` flavor puts all tasks on a single thread. This " -"makes the effect more obvious, but the bug is still present in the multi-" -"threaded flavor." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "`&str`/`String` (UTF-8, length-known)" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "" -"Switch the `std::thread::sleep` to `tokio::time::sleep` and await its result." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Null-terminated `char*`, encoding undefined" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "" -"Another fix would be to `tokio::task::spawn_blocking` which spawns an actual " -"thread and transforms its handle into a future without blocking the executor." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "**Nullability**" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "" -"You should not think of tasks as OS threads. They do not map 1 to 1 and most " -"executors will allow many tasks to run on a single OS thread. This is " -"particularly problematic when interacting with other libraries via FFI, " -"where that library might depend on thread-local storage or map to specific " -"OS threads (e.g., CUDA). Prefer `tokio::task::spawn_blocking` in such " -"situations." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Explicit via `Option`" msgstr "" -#: src/async/pitfalls/blocking-executor.md -msgid "" -"Use sync mutexes with care. Holding a mutex over an `.await` may cause " -"another task to block, and that task may be running on the same thread." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Any pointer may be null" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"Async blocks and functions return types implementing the `Future` trait. The " -"type returned is the result of a compiler transformation which turns local " -"variables into data stored inside the future." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "**Ownership**" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"Some of those variables can hold pointers to other local variables. Because " -"of that, the future should never be moved to a different memory location, as " -"it would invalidate those pointers." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Affine types, lifetimes" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"To prevent moving the future type in memory, it can only be polled through a " -"pinned pointer. `Pin` is a wrapper around a reference that disallows all " -"operations that would move the instance it points to into a different memory " -"location." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Conventions" msgstr "" -#: src/async/pitfalls/pin.md -msgid "// A work item. In this case, just sleep for the given time and respond" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "**Callbacks**" msgstr "" -#: src/async/pitfalls/pin.md -msgid "// with a message on the `respond_on` channel." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "`Fn`/`FnMut`/`FnOnce` closures" msgstr "" -#: src/async/pitfalls/pin.md -msgid "// A worker which listens for work on a queue and performs it." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Function pointer + `void* userdata`" msgstr "" -#: src/async/pitfalls/pin.md -msgid "// Pretend to work." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "**Panics**" msgstr "" -#: src/async/pitfalls/pin.md -msgid "\"failed to send response\"" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Stack unwinding (or abort)" msgstr "" -#: src/async/pitfalls/pin.md -msgid "// TODO: report number of iterations every 100ms" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Abort" msgstr "" -#: src/async/pitfalls/pin.md -msgid "// A requester which requests work and waits for it to complete." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "" +"Errors: Must convert `Result` to abide by C conventions; easy to forget to " +"check errors on C side." msgstr "" -#: src/async/pitfalls/pin.md -msgid "\"failed to send on work queue\"" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "" +"Strings: Conversion cost; null bytes in Rust strings cause truncation; UTF-8 " +"validation on ingress." msgstr "" -#: src/async/pitfalls/pin.md -msgid "\"failed waiting for response\"" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "" +"Nullability: Every pointer from C must be checked to create an " +"`Option>`, implying unsafe blocks or runtime cost." msgstr "" -#: src/async/pitfalls/pin.md -msgid "\"work result for iteration {i}: {resp}\"" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md +msgid "Ownership: Must document and enforce object lifetimes manually." msgstr "" -#: src/async/pitfalls/pin.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md msgid "" -"You may recognize this as an example of the actor pattern. Actors typically " -"call `select!` in a loop." +"Callbacks: Must decompose closures into fn pointer + context; lifetime of " +"context is manual." msgstr "" -#: src/async/pitfalls/pin.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-c.md msgid "" -"This serves as a summation of a few of the previous lessons, so take your " -"time with it." +"Panics: Panic across FFI boundary is undefined behavior; must catch at " +"boundary with `catch_unwind`." msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"Naively add a `_ = sleep(Duration::from_millis(100)) => { println!(..) }` to " -"the `select!`. This will never execute. Why?" +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "C++" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"Instead, add a `timeout_fut` containing that future outside of the `loop`:" +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "**Overloading**" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"This still doesn't work. Follow the compiler errors, adding `&mut` to the " -"`timeout_fut` in the `select!` to work around the move, then using `Box::" -"pin`:" +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "Manual/ad-hoc" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"This compiles, but once the timeout expires it is `Poll::Ready` on every " -"iteration (a fused future would help with this). Update to reset " -"`timeout_fut` every time it expires." +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "Automatic" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"Box allocates on the heap. In some cases, `std::pin::pin!` (only recently " -"stabilized, with older code often using `tokio::pin!`) is also an option, " -"but that is difficult to use for a future that is reassigned." +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "**Exceptions**" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"Another alternative is to not use `pin` at all but spawn another task that " -"will send to a `oneshot` channel every 100ms." +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "\\-" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"Data that contains pointers to itself is called self-referential. Normally, " -"the Rust borrow checker would prevent self-referential data from being " -"moved, as the references cannot outlive the data they point to. However, the " -"code transformation for async blocks and functions is not verified by the " -"borrow checker." +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "Stack unwinding" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"`Pin` is a wrapper around a reference. An object cannot be moved from its " -"place using a pinned pointer. However, it can still be moved through an " -"unpinned pointer." +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "**Destructors**" msgstr "" -#: src/async/pitfalls/pin.md -msgid "" -"The `poll` method of the `Future` trait uses `Pin<&mut Self>` instead of " -"`&mut Self` to refer to the instance. That's why it can only be called on a " -"pinned pointer." +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "Manual cleanup" msgstr "" -#: src/async/pitfalls/async-traits.md -msgid "" -"Async methods in traits are not yet supported in the stable channel ([An " -"experimental feature exists in nightly and should be stabilized in the mid " -"term.](https://blog.rust-lang.org/inside-rust/2022/11/17/async-fn-in-trait-" -"nightly.html))" +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "Automatic via destructors (RAII)" msgstr "" -#: src/async/pitfalls/async-traits.md -msgid "" -"The crate [async_trait](https://docs.rs/async-trait/latest/async_trait/) " -"provides a workaround through a macro:" +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "**Non-POD types**" +msgstr "" + +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "Objects with constructors, vtables, virtual bases" msgstr "" -#: src/async/pitfalls/async-traits.md -msgid "\"running all sleepers..\"" +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "**Templates**" msgstr "" -#: src/async/pitfalls/async-traits.md -msgid "\"slept for {}ms\"" +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "Compile-time code generation" msgstr "" -#: src/async/pitfalls/async-traits.md +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md msgid "" -"`async_trait` is easy to use, but note that it's using heap allocations to " -"achieve this. This heap allocation has performance overhead." +"C++ includes a number of features that don't exist in C with an FFI impact:" msgstr "" -#: src/async/pitfalls/async-traits.md +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md msgid "" -"The challenges in language support for `async trait` are deep Rust and " -"probably not worth describing in-depth. Niko Matsakis did a good job of " -"explaining them in [this post](https://smallcultfollowing.com/babysteps/" -"blog/2019/10/26/async-fn-in-traits-are-hard/) if you are interested in " -"digging deeper." +"Overloading: Overloads become impossible to express because of name mangling" msgstr "" -#: src/async/pitfalls/async-traits.md +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md msgid "" -"Try creating a new sleeper struct that will sleep for a random amount of " -"time and adding it to the Vec." +"Exceptions: Must catch exceptions at the FFI boundary and convert them to " +"error codes, as escaping exceptions in `extern \"C\"` functions constitute " +"undefined behavior" msgstr "" -#: src/async/pitfalls/cancellation.md +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md msgid "" -"Dropping a future implies it can never be polled again. This is called " -"_cancellation_ and it can occur at any `await` point. Care is needed to " -"ensure the system works correctly even when futures are cancelled. For " -"example, it shouldn't deadlock or lose data." +"Destructors: C callers won't run destructors; must expose explicit " +"`*_destroy()` functions" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "\"not UTF-8\"" +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "" +"Non-POD types: Must use opaque pointers across the FFI boundary as pass by " +"value does not make sense" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "\"hi\\nthere\\n\"" +#: src/unsafe-deep-dive/ffi/language-differences/cpp-and-c.md +msgid "" +"Templates: Cannot expose directly; must instantiate explicitly and wrap each " +"specialization" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "\"tick!\"" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "**Trivial relocatability**" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "" -"The compiler doesn't help with cancellation-safety. You need to read API " -"documentation and consider what state your `async fn` holds." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "All moves are `memcpy`" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "" -"Unlike `panic` and `?`, cancellation is part of normal control flow (vs " -"error-handling)." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Self-referential types, move constructors can have side effects" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "The example loses parts of the string." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "**Destruction safety**" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "" -"Whenever the `tick()` branch finishes first, `next()` and its `buf` are " -"dropped." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "`Drop::drop()` on original location only" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "" -"`LinesReader` can be made cancellation-safe by making `buf` part of the " -"struct:" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Destructor may run on moved-from objects" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "// prefix buf and bytes with self." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "**Exception safety**" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "" -"[`Interval::tick`](https://docs.rs/tokio/latest/tokio/time/struct.Interval." -"html#method.tick) is cancellation-safe because it keeps track of whether a " -"tick has been 'delivered'." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Panics (abort or unwind)" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "" -"[`AsyncReadExt::read`](https://docs.rs/tokio/latest/tokio/io/trait." -"AsyncReadExt.html#method.read) is cancellation-safe because it either " -"returns or doesn't read data." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Exceptions (unwind)" msgstr "" -#: src/async/pitfalls/cancellation.md -msgid "" -"[`AsyncBufReadExt::read_line`](https://docs.rs/tokio/latest/tokio/io/trait." -"AsyncBufReadExt.html#method.read_line) is similar to the example and _isn't_ " -"cancellation-safe. See its documentation for details and alternatives." +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "**ABI stability**" msgstr "" -#: src/exercises/concurrency/afternoon.md -msgid "" -"To practice your Async Rust skills, we have again two exercises for you:" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Explicitly unstable" +msgstr "" + +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Vendor-specific" msgstr "" -#: src/exercises/concurrency/afternoon.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md msgid "" -"Dining philosophers: we already saw this problem in the morning. This time " -"you are going to implement it with Async Rust." +"Even if it were possible to avoid interop via C, there are still some areas " +"of the languages that impact FFI:" +msgstr "" + +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "_Trivial relocatability_" msgstr "" -#: src/exercises/concurrency/afternoon.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md msgid "" -"A Broadcast Chat Application: this is a larger project that allows you " -"experiment with more advanced Async Rust features." +"Cannot safely move C++ objects on the Rust side; must pin or keep in C++ " +"heap." msgstr "" -#: src/exercises/concurrency/dining-philosophers-async.md -#: src/exercises/concurrency/solutions-afternoon.md -#, fuzzy -msgid "Dining Philosophers --- Async" -msgstr "Dining āĻĻāĻžāĻ°ā§āĻļāύāĻŋāĻ•" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "" +"In Rust, object movement, which occurs during assignment or by being passed " +"by value, always copies values bit by bit." +msgstr "" -#: src/exercises/concurrency/dining-philosophers-async.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md msgid "" -"See [dining philosophers](dining-philosophers.md) for a description of the " -"problem." +"C++ allows users to define their own semantics by allowing them to overload " +"the assignment operator and create move and copy constructors." msgstr "" -#: src/exercises/concurrency/dining-philosophers-async.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md msgid "" -"As before, you will need a local [Cargo installation](../../cargo/running-" -"locally.md) for this exercise. Copy the code below to a file called `src/" -"main.rs`, fill out the blanks, and test that `cargo run` does not deadlock:" +"This impacts interop because self-referential types become natural in high-" +"performance C++. Custom constructors can uphold safety invariants even when " +"the object moves its position in memory." msgstr "" -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "// Keep trying until we have both forks" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "Objects with the same semantics are impossible to define in Rust." msgstr "" -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "// Make them think and eat" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "_Destruction safety_" msgstr "" -#: src/exercises/concurrency/dining-philosophers-async.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md msgid "" -"Since this time you are using Async Rust, you'll need a `tokio` dependency. " -"You can use the following `Cargo.toml`:" +"Moved-from C++ object semantics don't map; must prevent Rust from \"moving\" " +"C++ types." msgstr "" -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "" -"```toml\n" -"[package]\n" -"name = \"dining-philosophers-async-dine\"\n" -"version = \"0.1.0\"\n" -"edition = \"2021\"\n" -"\n" -"[dependencies]\n" -"tokio = { version = \"1.26.0\", features = [\"sync\", \"time\", \"macros\", " -"\"rt-multi-thread\"] }\n" -"```" +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md +msgid "_Exception safety_" msgstr "" -#: src/exercises/concurrency/dining-philosophers-async.md +#: src/unsafe-deep-dive/ffi/language-differences/rust-and-cpp.md msgid "" -"Also note that this time you have to use the `Mutex` and the `mpsc` module " -"from the `tokio` crate." +"Neither can cross into the other safely; both must catch at the boundary." msgstr "" -#: src/exercises/concurrency/dining-philosophers-async.md -msgid "Can you make your implementation single-threaded?" +#: src/unsafe-deep-dive/ffi/abs.md +msgid "Wrapping `abs(3)`" msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "" -"In this exercise, we want to use our new knowledge to implement a broadcast " -"chat application. We have a chat server that the clients connect to and " -"publish their messages. The client reads user messages from the standard " -"input, and sends them to the server. The chat server broadcasts each message " -"that it receives to all the clients." +#: src/unsafe-deep-dive/ffi/abs.md +msgid "In this slide, we’re establishing a pattern for writing wrappers." msgstr "" -#: src/exercises/concurrency/chat-app.md +#: src/unsafe-deep-dive/ffi/abs.md msgid "" -"For this, we use [a broadcast channel](https://docs.rs/tokio/latest/tokio/" -"sync/broadcast/fn.channel.html) on the server, and [`tokio_websockets`]" -"(https://docs.rs/tokio-websockets/) for the communication between the client " -"and the server." +"Find the external definition of a function’s signature Write a matching " +"function in Rust within an `extern` block Confirm which safety invariants " +"need to be upheld Decide whether it’s possible to mark the function as safe" +msgstr "" + +#: src/unsafe-deep-dive/ffi/abs.md +msgid "Note that this doesn’t work _yet_." +msgstr "" + +#: src/unsafe-deep-dive/ffi/abs.md +msgid "Add the extern block:" msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "Create a new Cargo project and add the following dependencies:" +#: src/unsafe-deep-dive/ffi/abs.md +msgid "" +"Explain that many POSIX functions are available in Rust because Cargo links " +"against the C standard library (libc) by default, which brings its symbols " +"into the program’s scope." msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "_Cargo.toml_:" +#: src/unsafe-deep-dive/ffi/abs.md +msgid "" +"Show `man 3 abs` in the terminal or [a webpage](https://www.man7.org/linux/" +"man-pages/man3/abs.3.html)." msgstr "" -#: src/exercises/concurrency/chat-app.md +#: src/unsafe-deep-dive/ffi/abs.md msgid "" -"```toml\n" -"[package]\n" -"name = \"chat-async\"\n" -"version = \"0.1.0\"\n" -"edition = \"2021\"\n" -"\n" -"[dependencies]\n" -"futures-util = { version = \"0.3.30\", features = [\"sink\"] }\n" -"http = \"1.0.0\"\n" -"tokio = { version = \"1.36.0\", features = [\"full\"] }\n" -"tokio-websockets = { version = \"0.5.1\", features = [\"client\", " -"\"fastrand\", \"server\", \"sha1_smol\"] }\n" -"```" +"Explain that our function signature must match its definition: `int abs(int " +"j);`." msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "The required APIs" +#: src/unsafe-deep-dive/ffi/abs.md +msgid "Update the code block to use the C types." msgstr "" -#: src/exercises/concurrency/chat-app.md +#: src/unsafe-deep-dive/ffi/abs.md msgid "" -"You are going to need the following functions from `tokio` and " -"[`tokio_websockets`](https://docs.rs/tokio-websockets/). Spend a few minutes " -"to familiarize yourself with the API." +"Discuss rationale: using `ffi::c_int` increases the portability of our code. " +"When the standard library is compiled for the target platform, the platform " +"can determine the widths. According to the C standard, a `c_int` may be " +"defined as an `i16` rather than the much more common `i32`." msgstr "" -#: src/exercises/concurrency/chat-app.md +#: src/unsafe-deep-dive/ffi/abs.md msgid "" -"[StreamExt::next()](https://docs.rs/futures-util/0.3.28/futures_util/stream/" -"trait.StreamExt.html#method.next) implemented by `WebSocketStream`: for " -"asynchronously reading messages from a Websocket Stream." +"(Optional) Show the [documentation for c_int](https://doc.rust-lang.org/std/" +"ffi/type.c_int.html) to reveal that it is a type alias for `i32`." msgstr "" -#: src/exercises/concurrency/chat-app.md +#: src/unsafe-deep-dive/ffi/abs.md msgid "" -"[SinkExt::send()](https://docs.rs/futures-util/0.3.28/futures_util/sink/" -"trait.SinkExt.html#method.send) implemented by `WebSocketStream`: for " -"asynchronously sending messages on a Websocket Stream." +"Attempt to compile to trigger “error: extern blocks must be unsafe” error " +"message." msgstr "" -#: src/exercises/concurrency/chat-app.md +#: src/unsafe-deep-dive/ffi/abs.md +msgid "Add the unsafe keyword to the block:" +msgstr "" + +#: src/unsafe-deep-dive/ffi/abs.md msgid "" -"[Lines::next_line()](https://docs.rs/tokio/latest/tokio/io/struct.Lines." -"html#method.next_line): for asynchronously reading user messages from the " -"standard input." +"Check that learners understand the significance of this change. We are " +"required to uphold type safety and other safety preconditions." +msgstr "" + +#: src/unsafe-deep-dive/ffi/abs.md +msgid "Recompile." +msgstr "" + +#: src/unsafe-deep-dive/ffi/abs.md +msgid "Add safe keyword to the abs function:" msgstr "" -#: src/exercises/concurrency/chat-app.md +#: src/unsafe-deep-dive/ffi/abs.md msgid "" -"[Sender::subscribe()](https://docs.rs/tokio/latest/tokio/sync/broadcast/" -"struct.Sender.html#method.subscribe): for subscribing to a broadcast channel." +"Explain that the `safe fn` marks `abs` as safe to call without an `unsafe` " +"block." msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "Two binaries" +#: src/unsafe-deep-dive/ffi/abs.md +msgid "Completed program for reference:" +msgstr "" + +#: src/unsafe-deep-dive/ffi/rand.md +msgid "Wrapping `srand(3)` and `rand(3)`" msgstr "" -#: src/exercises/concurrency/chat-app.md +#: src/unsafe-deep-dive/ffi/rand.md msgid "" -"Normally in a Cargo project, you can have only one binary, and one `src/main." -"rs` file. In this project, we need two binaries. One for the client, and one " -"for the server. You could potentially make them two separate Cargo projects, " -"but we are going to put them in a single Cargo project with two binaries. " -"For this to work, the client and the server code should go under `src/bin` " -"(see the [documentation](https://doc.rust-lang.org/cargo/reference/cargo-" -"targets.html#binaries))." +"// unsafe extern \"C\" {\n" +"// /// Seed the rng\n" +"// fn srand(seed: std::ffi::c_uint);\n" msgstr "" -#: src/exercises/concurrency/chat-app.md +#: src/unsafe-deep-dive/ffi/rand.md msgid "" -"Copy the following server and client code into `src/bin/server.rs` and `src/" -"bin/client.rs`, respectively. Your task is to complete these files as " -"described below." +"// fn rand() -> std::ffi::c_int;\n" +"// }\n" msgstr "" -#: src/exercises/concurrency/chat-app.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "_src/bin/server.rs_:" +#: src/unsafe-deep-dive/ffi/rand.md +msgid "\"{a:?}\"" msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "// TODO: For a hint, see the description of the task below." +#: src/unsafe-deep-dive/ffi/rand.md +msgid "" +"This slide attempts to demonstrate that it is very easy for wrappers to " +"trigger undefined behavior if they are written incorrectly. We’ll see how " +"easy it is to trigger type safety problems." msgstr "" -#: src/exercises/concurrency/chat-app.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"127.0.0.1:2000\"" +#: src/unsafe-deep-dive/ffi/rand.md +msgid "" +"Explain that `rand` and `srand` functions are provided by the C standard " +"library (libc)." msgstr "" -#: src/exercises/concurrency/chat-app.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"listening on port 2000\"" +#: src/unsafe-deep-dive/ffi/rand.md +msgid "" +"Explain that the functions are exported by the libc crate, but we can also " +"write an FFI wrapper for them manually." msgstr "" -#: src/exercises/concurrency/chat-app.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"New connection from {addr:?}\"" +#: src/unsafe-deep-dive/ffi/rand.md +msgid "Show calling the functions from the exported." msgstr "" -#: src/exercises/concurrency/chat-app.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// Wrap the raw TCP stream into a websocket.\n" +#: src/unsafe-deep-dive/ffi/rand.md +msgid "Code compiles because libc is linked to Rust programs by default." msgstr "" -#: src/exercises/concurrency/chat-app.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "_src/bin/client.rs_:" +#: src/unsafe-deep-dive/ffi/rand.md +msgid "Explain that Rust will trust you if you use the wrong type(s)." msgstr "" -#: src/exercises/concurrency/chat-app.md -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"ws://127.0.0.1:2000\"" +#: src/unsafe-deep-dive/ffi/rand.md +msgid "Modify `fn rand() -> std::ffi::c_int;` to return `char`." msgstr "" -#: src/exercises/concurrency/chat-app.md -#, fuzzy -msgid "Running the binaries" -msgstr "āϕ⧋āĻ°ā§āϏ āϚāĻžāϞāĻžāύ⧋" +#: src/unsafe-deep-dive/ffi/rand.md +msgid "" +"Avoiding type safety issues is a reason for using tools for generating " +"wrappers, rather than doing it by hand." +msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "Run the server with:" +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "C Library Example" msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "and the client with:" +#: src/unsafe-deep-dive/ffi/c-library-example.md +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "" msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "Implement the `handle_connection` function in `src/bin/server.rs`." +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "" msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "" -"Hint: Use `tokio::select!` for concurrently performing two tasks in a " -"continuous loop. One task receives messages from the client and broadcasts " -"them. The other sends messages received by the server to the client." +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "/* Return `false` to indicate that no token was found. */" msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "Complete the main function in `src/bin/client.rs`." +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "/* TextAnalyst constructor */" msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "" -"Hint: As before, use `tokio::select!` in a continuous loop for concurrently " -"performing two tasks: (1) reading user messages from standard input and " -"sending them to the server, and (2) receiving messages from the server, and " -"displaying them for the user." +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "/* TextAnalyst destructor */" msgstr "" -#: src/exercises/concurrency/chat-app.md -msgid "" -"Optional: Once you are done, change the code to broadcast messages to all " -"clients, but the sender of the message." +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "/* Resets state to clear the current document */" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "Concurrency Afternoon Exercise" +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "/* Use custom tokenizer (defaults to whitespace) */" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "([back to exercise](dining-philosophers-async.md))" +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "/* Apply `callback` to each token */" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// Keep trying until we have both forks\n" +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "/* Get human-readable error message */" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// Pick up forks...\n" +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "/* TEXT_ANALYSIS_H */" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md +#: src/unsafe-deep-dive/ffi/c-library-example.md msgid "" -"// If we didn't get the left fork, drop the right fork if we\n" -" // have it and let other tasks make progress.\n" +"C libraries will hide their implementation details with a `void*` argument." msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md +#: src/unsafe-deep-dive/ffi/c-library-example.md msgid "" -"// If we didn't get the right fork, drop the left fork and let\n" -" // other tasks make progress.\n" +"Consider this header file of a natural language processing library that " +"hides the `TextAnalyst` and `Analysis` types." msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// The locks are dropped here\n" +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "This can be emulated in Rust with a type similar to this:" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// Create forks\n" +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "Exercise: Ask learners to wrap this library." msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// Create philosophers\n" +#: src/unsafe-deep-dive/ffi/c-library-example.md +msgid "// ffi.rs\n" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// tx is dropped here, so we don't need to explicitly drop it later\n" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "Example: String interning library" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// Make them think and eat\n" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "C++ Header: interner.hpp" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// Output their thoughts\n" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"Here is a thought: {thought}\"" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "([back to exercise](chat-app.md))" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "" +"// Returns a pointer to the interned string (valid for lifetime of " +"interner)\n" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"Welcome to chat! Type a message\"" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "C header file: interner.h" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "" -"// A continuous loop for concurrently performing two tasks: (1) receiving\n" -" // messages from `ws_stream` and broadcasting them, and (2) receiving\n" -" // messages on `bcast_rx` and sending them to the client.\n" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "// interner.h (C API for FFI)\n" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"From client {addr:?} {text:?}\"" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "C++ implementation (interner.cpp)" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "// Continuous loop for concurrently sending and receiving messages.\n" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "\"interner.hpp\"" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md -msgid "\"From server: {}\"" +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "\"interner.h\"" +msgstr "" + +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "" +"This is a larger example. Write a wrapper for the string interner. You will " +"need to guide learners on how to create an opaque pointer, either directly " +"by explaining the code below or asking learners to do further research." +msgstr "" + +#: src/unsafe-deep-dive/ffi/cpp-library-example.md +msgid "Once the raw wrapper is written, ask learners to create a safe wrapper." msgstr "" #: src/thanks.md @@ -19330,15 +33889,21 @@ msgid "" "_Thank you for taking Comprehensive Rust đŸĻ€!_ We hope you enjoyed it and " "that it was useful." msgstr "" -"Comprehensive Rust đŸĻ€ āϕ⧋āĻ°ā§āϏāϟāĻŋ āύ⧇āĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ āφāĻĒāύāĻžāϕ⧇ āϧāĻ¨ā§āϝāĻŦāĻžāĻĻ! āφāĻŽāϰāĻž āφāĻļāĻž āĻ•āϰāĻŋ āφāĻĒāύāĻŋ āĻāϟāĻŋ " -"āωāĻĒāĻ­ā§‹āĻ— āĻ•āϰ⧇āϛ⧇āύ āĻāĻŦāĻ‚ āĻāϟāĻŋ āωāĻĒāĻ•āĻžāϰ⧀ āĻ›āĻŋāϞ⧋āĨ¤" #: src/thanks.md msgid "" -"We've had a lot of fun putting the course together. The course is not " -"perfect, so if you spotted any mistakes or have ideas for improvements, " -"please get in [contact with us on GitHub](https://github.com/google/" -"comprehensive-rust/discussions). We would love to hear from you." +"We have enjoyed putting the course together. The course is not perfect, so " +"if you spotted any mistakes or have ideas for improvements, please get in " +"[contact with us on GitHub](https://github.com/google/comprehensive-rust/" +"discussions). We would love to hear from you." +msgstr "" + +#: src/thanks.md +msgid "" +"Thank you for reading the speaker notes! We hope they have been useful. If " +"you find pages without notes, please send us a PR and link it to [issue " +"#1083](https://github.com/google/comprehensive-rust/issues/1083). We are " +"also very grateful for fixes and improvements to the existing notes." msgstr "" #: src/glossary.md @@ -19348,16 +33913,25 @@ msgid "" "the English original." msgstr "" +#. Please add the English term in italic after your translated term. Also, please keep the hard line breaks to ensure a nice formatting. #: src/glossary.md msgid "" "allocate: \n" -"Dynamic memory allocation on [the heap](memory-management/stack-vs-heap.md)." +"Dynamic memory allocation on [the heap](memory-management/review.md)." +msgstr "" + +#: src/glossary.md +msgid "" +"array: \n" +"A fixed-size collection of elements of the same type, stored contiguously in " +"memory. See [Arrays](tuples-and-arrays/arrays.md)." msgstr "" #: src/glossary.md msgid "" -"argument: \n" -"Information that is passed into a function or method." +"associated type: \n" +"A type associated with a specific trait. Useful for defining the " +"relationship between types." msgstr "" #: src/glossary.md @@ -19370,38 +33944,27 @@ msgstr "" #: src/glossary.md msgid "" "block: \n" -"See [Blocks](control-flow/blocks.md) and _scope_." +"See [Blocks](control-flow-basics/blocks-and-scopes.md) and _scope_." msgstr "" #: src/glossary.md msgid "" "borrow: \n" -"See [Borrowing](ownership/borrowing.md)." +"See [Borrowing](borrowing/shared.md)." msgstr "" #: src/glossary.md msgid "" "borrow checker: \n" -"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." msgstr "" #: src/glossary.md msgid "" "brace: \n" -"`{` and `}`. Also called _curly brace_, they delimit _blocks_." -msgstr "" - -#: src/glossary.md -msgid "" -"build: \n" -"The process of converting source code into executable code or a usable " -"program." -msgstr "" - -#: src/glossary.md -msgid "" -"call: \n" -"To invoke or execute a function or method." +"`{` and `}`. Also called _curly brace_, they delimit [_blocks_](control-flow-" +"basics/blocks-and-scopes.md)." msgstr "" #: src/glossary.md @@ -19410,194 +33973,177 @@ msgid "" "Used to safely pass messages [between threads](concurrency/channels.md)." msgstr "" -#: src/glossary.md -msgid "" -"Comprehensive Rust đŸĻ€: \n" -"The courses here are jointly called Comprehensive Rust đŸĻ€." -msgstr "" - #: src/glossary.md msgid "" "concurrency: \n" -"The execution of multiple tasks or processes at the same time." -msgstr "" - -#: src/glossary.md -msgid "" -"Concurrency in Rust: \n" -"See [Concurrency in Rust](concurrency.md)." +"The execution of multiple tasks or processes at the same time. See [Welcome " +"to Concurrency in Rust](concurrency/welcome.md)." msgstr "" #: src/glossary.md msgid "" "constant: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "control flow: \n" "The order in which the individual statements or instructions are executed in " -"a program." +"a program. See [Control Flow Basics](control-flow-basics.md)." msgstr "" #: src/glossary.md msgid "" "crash: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "enumeration: \n" "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)." msgstr "" #: src/glossary.md msgid "" "error: \n" -"An unexpected condition or result that deviates from the expected behavior." +"An unexpected condition or result that deviates from the expected behavior. " +"See [Error Handling](error-handling.md)." msgstr "" #: src/glossary.md msgid "" "error handling: \n" -"The process of managing and responding to errors that occur during program " -"execution." -msgstr "" - -#: src/glossary.md -msgid "" -"exercise: \n" -"A task or problem designed to practice and test programming skills." +"The process of managing and responding to [errors](error-handling.md) that " +"occur during program execution." msgstr "" #: src/glossary.md msgid "" "function: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "garbage collector: \n" "A mechanism that automatically frees up memory occupied by objects that are " -"no longer in use." +"no longer in use. See [Approaches to Memory Management](memory-management/" +"approaches.md)." msgstr "" #: src/glossary.md msgid "" "generics: \n" "A feature that allows writing code with placeholders for types, enabling " -"code reuse with different data types." +"code reuse with different data types. See [Generics](generics.md)." msgstr "" #: src/glossary.md msgid "" "immutable: \n" -"Unable to be changed after creation." +"Unable to be changed after creation. See [Variables](types-and-values/" +"variables.md)." msgstr "" #: src/glossary.md msgid "" "integration test: \n" "A type of test that verifies the interactions between different parts or " -"components of a system." -msgstr "" - -#: src/glossary.md -msgid "" -"keyword: \n" -"A reserved word in a programming language that has a specific meaning and " -"cannot be used as an identifier." +"components of a system. See [Other Types of Tests](testing/other.md)." msgstr "" #: src/glossary.md msgid "" "library: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "macro: \n" -"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." msgstr "" #: src/glossary.md msgid "" "`main` function: \n" -"Rust programs start executing with the `main` function." +"Rust programs start executing with the [`main` function](types-and-values/" +"hello-world.md)." msgstr "" #: src/glossary.md msgid "" "match: \n" -"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." msgstr "" #: src/glossary.md msgid "" "memory leak: \n" "A situation where a program fails to release memory that is no longer " -"needed, leading to a gradual increase in memory usage." +"needed, leading to a gradual increase in memory usage. See [Approaches to " +"Memory Management](memory-management/approaches.md)." msgstr "" #: src/glossary.md msgid "" "method: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "module: \n" "A namespace that contains definitions, such as functions, types, or traits, " -"to organize code in Rust." +"to organize code in Rust. See [Modules](modules.md)." msgstr "" #: src/glossary.md msgid "" "move: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "mutable: \n" -"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." msgstr "" #: src/glossary.md msgid "" "ownership: \n" "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)." msgstr "" #: src/glossary.md msgid "" "panic: \n" "An unrecoverable error condition in Rust that results in the termination of " -"the program." -msgstr "" - -#: src/glossary.md -msgid "" -"parameter: \n" -"A value that is passed into a function or method when it is called." +"the program. See [Panics](error-handling/panics.md)." msgstr "" #: src/glossary.md msgid "" "pattern: \n" "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)." msgstr "" #: src/glossary.md @@ -19608,194 +34154,181 @@ msgstr "" #: src/glossary.md msgid "" -"program: \n" -"A set of instructions that a computer can execute to perform a specific task " -"or solve a particular problem." -msgstr "" - -#: src/glossary.md -msgid "" -"programming language: \n" -"A formal system used to communicate instructions to a computer, such as Rust." +"receiver: \n" +"The first parameter in a Rust [method](methods-and-traits/methods.md) that " +"represents the instance on which the method is called." msgstr "" #: src/glossary.md msgid "" -"receiver: \n" -"The first parameter in a Rust method that represents the instance on which " -"the method is called." +"reference: \n" +"A non-owning pointer to a value that borrows it without transferring " +"ownership. References can be [shared (immutable)](references/shared.md) or " +"[exclusive (mutable)](references/exclusive.md)." msgstr "" #: src/glossary.md msgid "" "reference counting: \n" "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." -msgstr "" - -#: src/glossary.md -msgid "" -"return: \n" -"A keyword in Rust used to indicate the value to be returned from a function." +"is tracked, and the object is deallocated when the count reaches zero. See " +"[Rc](smart-pointers/rc.md)." msgstr "" #: src/glossary.md msgid "" "Rust: \n" "A systems programming language that focuses on safety, performance, and " -"concurrency." -msgstr "" - -#: src/glossary.md -msgid "" -"Rust Fundamentals: \n" -"Days 1 to 4 of this course." -msgstr "" - -#: src/glossary.md -msgid "" -"Rust in Android: \n" -"See [Rust in Android](android.md)." +"concurrency. See [What is Rust?](hello-world/what-is-rust.md)." msgstr "" #: src/glossary.md msgid "" -"Rust in Chromium: \n" -"See [Rust in Chromium](chromium.md)." +"safe: \n" +"Refers to code that adheres to Rust's ownership and borrowing rules, " +"preventing memory-related errors. See [Unsafe Rust](unsafe-rust.md)." msgstr "" #: src/glossary.md msgid "" -"safe: \n" -"Refers to code that adheres to Rust's ownership and borrowing rules, " -"preventing memory-related errors." +"slice: \n" +"A dynamically-sized view into a contiguous sequence, such as an array or " +"vector. Unlike arrays, slices have a size determined at runtime. See [Slices]" +"(references/slices.md)." msgstr "" #: src/glossary.md msgid "" "scope: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "standard library: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "static: \n" "A keyword in Rust used to define static variables or items with a `'static` " -"lifetime." +"lifetime. See [static](user-defined-types/static.md)." msgstr "" #: src/glossary.md msgid "" "string: \n" -"A data type storing textual data. See [`String` vs `str`](basic-syntax/" -"string-slices.html) for more." +"A data type storing textual data. See [Strings](references/strings.md)." msgstr "" #: src/glossary.md msgid "" "struct: \n" "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)." msgstr "" #: src/glossary.md msgid "" "test: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "thread: \n" -"A separate sequence of execution in a program, allowing concurrent execution." +"A separate sequence of execution in a program, allowing concurrent " +"execution. See [Threads](concurrency/threads.md)." msgstr "" #: src/glossary.md msgid "" "thread safety: \n" "The property of a program that ensures correct behavior in a multithreaded " -"environment." +"environment. See [Send and Sync](concurrency/send-sync.md)." msgstr "" #: src/glossary.md msgid "" "trait: \n" "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)." msgstr "" #: src/glossary.md msgid "" "trait bound: \n" "An abstraction where you can require types to implement some traits of your " -"interest." +"interest. See [Trait Bounds](generics/trait-bounds.md)." msgstr "" #: src/glossary.md msgid "" "tuple: \n" "A composite data type that contains variables of different types. Tuple " -"fields have no names, and are accessed by their ordinal numbers." +"fields have no names, and are accessed by their ordinal numbers. See [Tuples]" +"(tuples-and-arrays/tuples.md)." msgstr "" #: src/glossary.md msgid "" "type: \n" "A classification that specifies which operations can be performed on values " -"of a particular kind in Rust." +"of a particular kind in Rust. See [Types and Values](types-and-values.md)." msgstr "" #: src/glossary.md msgid "" "type inference: \n" "The ability of the Rust compiler to deduce the type of a variable or " -"expression." +"expression. See [Type Inference](types-and-values/inference.md)." msgstr "" #: src/glossary.md msgid "" "undefined behavior: \n" "Actions or conditions in Rust that have no specified result, often leading " -"to unpredictable program behavior." +"to unpredictable program behavior. See [Unsafe Rust](unsafe-rust.md)." msgstr "" #: src/glossary.md msgid "" "union: \n" -"A data type that can hold values of different types but only one at a time." +"A data type that can hold values of different types but only one at a time. " +"See [Unions](unsafe-rust/unions.md)." msgstr "" #: src/glossary.md msgid "" "unit test: \n" "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)." msgstr "" #: src/glossary.md msgid "" "unit type: \n" -"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)." msgstr "" #: src/glossary.md msgid "" "unsafe: \n" "The subset of Rust which allows you to trigger _undefined behavior_. See " -"[Unsafe Rust](unsafe.html)." +"[Unsafe Rust](unsafe-rust/unsafe.md)." msgstr "" #: src/glossary.md msgid "" "variable: \n" -"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)." msgstr "" #: src/other-resources.md @@ -19810,7 +34343,7 @@ msgstr "" #: src/other-resources.md msgid "Official Documentation" -msgstr "āĻ…āĻĢāĻŋāϏāĻŋāϝāĻŧāĻžāϞ āĻĄāϕ⧁āĻŽā§‡āĻ¨ā§āĻŸā§‡āĻļāύ" +msgstr "" #: src/other-resources.md msgid "The Rust project hosts many resources. These cover Rust in general:" @@ -19843,6 +34376,12 @@ msgid "" "book which describes the Rust grammar and memory model." msgstr "" +#: src/other-resources.md +msgid "" +"[Rust API Guidelines](https://rust-lang.github.io/api-guidelines/): " +"recommendations on how to design APIs." +msgstr "" + #: src/other-resources.md msgid "More specialized guides hosted on the official Rust site:" msgstr "" @@ -19884,9 +34423,9 @@ msgstr "" #: src/other-resources.md msgid "" -"[Rust for Embedded C Programmers](https://docs.opentitan.org/doc/ug/" -"rust_for_c/): covers Rust from the perspective of developers who write " -"firmware in C." +"[Rust for Embedded C Programmers](https://opentitan.org/book/doc/" +"rust_for_c_devs.html): covers Rust from the perspective of developers who " +"write firmware in C." msgstr "" #: src/other-resources.md @@ -19910,6 +34449,14 @@ msgid "" "and async/await are also covered." msgstr "" +#: src/other-resources.md +msgid "" +"[Advanced testing for Rust applications](https://rust-exercises.com/advanced-" +"testing/): a self-paced workshop that goes beyond Rust's built-in testing " +"framework. It covers `googletest`, snapshot testing, mocking as well as how " +"to write your own custom test harness." +msgstr "" + #: src/other-resources.md msgid "" "[Beginner's Series to Rust](https://docs.microsoft.com/en-us/shows/beginners-" @@ -19926,6 +34473,12 @@ msgid "" "rules, through implementing a few different types of list structures." msgstr "" +#: src/other-resources.md +msgid "" +"[The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/): " +"covers many details on Rust macros with practical examples." +msgstr "" + #: src/other-resources.md msgid "" "Please see the [Little Book of Rust Books](https://lborb.github.io/book/) " @@ -19946,32 +34499,9 @@ msgid "" "rust/blob/main/LICENSE) for details." msgstr "" -#: src/credits.md -msgid "Rust by Example" -msgstr "āωāĻĻāĻžāĻšāϰāϪ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āϰāĻžāĻ¸ā§āϟ" - -#: src/credits.md -msgid "" -"Some examples and exercises have been copied and adapted from [Rust by " -"Example](https://doc.rust-lang.org/rust-by-example/). Please see the " -"`third_party/rust-by-example/` directory for details, including the license " -"terms." -msgstr "" - -#: src/credits.md -msgid "Rust on Exercism" -msgstr "āĻ…āύ⧁āĻļā§€āϞāύ⧇ āϰāĻžāĻ¸ā§āϟ" - -#: src/credits.md -msgid "" -"Some exercises have been copied and adapted from [Rust on Exercism](https://" -"exercism.org/tracks/rust). Please see the `third_party/rust-on-exercism/` " -"directory for details, including the license terms." -msgstr "" - #: src/credits.md msgid "CXX" -msgstr "CXX" +msgstr "" #: src/credits.md msgid "" @@ -19979,637 +34509,3 @@ msgid "" "uses an image from [CXX](https://cxx.rs/). Please see the `third_party/cxx/` " "directory for details, including the license terms." msgstr "" - -#~ msgid "Much of the Rust syntax will be familiar to you from C, C++ or Java:" -#~ msgstr "" -#~ "C, C++ or Java āĻĨ⧇āϕ⧇ āĻŦ⧇āĻļāĻŋāϰāĻ­āĻžāĻ— āϰāĻžāĻ¸ā§āϟ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āφāĻĒāύāĻžāϰ āĻ•āĻžāϛ⧇ āĻĒāϰāĻŋāϚāĻŋāϤ āĻŽāύ⧇ āĻšāĻŦ⧇āσ" - -#, fuzzy -#~ msgid "\"aarch64-linux-gnu\"" -#~ msgstr "aarch64-paging" - -#, fuzzy -#~ msgid "\"exceptions.S\"" -#~ msgstr "āĻŦā§āϝāϤāĻŋāĻ•ā§āϰāĻŽ" - -#, fuzzy -#~ msgid "aarch64-linux-gnu" -#~ msgstr "aarch64-paging" - -#~ msgid "Small Example" -#~ msgstr "āϛ⧋āĻŸā§āϟ āωāĻĻāĻžāĻšāϰāĻŖ" - -#~ msgid "Why Rust?" -#~ msgstr "Rust āϕ⧇āύ⧋?" - -#~ msgid "Compile Time Guarantees" -#~ msgstr "āĻ•āĻŽā§āĻĒāĻžāχāϞ āϏāĻŽāϝāĻŧ⧇āϰ āĻ—ā§āϝāĻžāϰāĻžāĻ¨ā§āϟāĻŋ" - -#~ msgid "Runtime Guarantees" -#~ msgstr "āϰāĻžāύāϟāĻžāχāĻŽ āĻ—ā§āϝāϰāĻžāĻ¨ā§āϟāĻŋ" - -#~ msgid "Modern Features" -#~ msgstr "āφāϧ⧁āύāĻŋāĻ• āϏ⧁āĻŦāĻŋāϧāĻžāϏāĻŽā§‚āĻš" - -#~ msgid "Basic Syntax" -#~ msgstr "āĻŽā§ŒāϞāĻŋāĻ• āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ" - -#~ msgid "String vs str" -#~ msgstr "String āĻŦāύāĻžāĻŽ str" - -#~ msgid "Overloading" -#~ msgstr "āĻ…āĻ­āĻžāϰāϞ⧋āĻĄāĻŋāĻ‚" - -#~ msgid "Arrays and for Loops" -#~ msgstr "Arrays āĻāĻŦāĻ‚ for-Loops" - -#~ msgid "for expressions" -#~ msgstr "for āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ" - -#~ msgid "while expressions" -#~ msgstr "while āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ" - -#~ msgid "break & continue" -#~ msgstr "break & continue" - -#~ msgid "loop expressions" -#~ msgstr "loop āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ" - -#~ msgid "Variant Payloads" -#~ msgstr "āĻ­āĻŋāĻ¨ā§āύ Payloads" - -#~ msgid "Enum Sizes" -#~ msgstr "Enum āĻāϰ āĻŽāĻžāĻĒ" - -#~ msgid "Novel Control Flow" -#~ msgstr "āύāϭ⧇āϞ āĻ•āĻ¨ā§āĻŸā§āϰ⧋āϞ āĻĢā§āϞ⧋" - -#~ msgid "if let expressions" -#~ msgstr "if let āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ" - -#~ msgid "while let expressions" -#~ msgstr "while let āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ" - -#~ msgid "match expressions" -#~ msgstr "match āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ" - -#~ msgid "Destructuring Structs" -#~ msgstr "Structs āĻĄāĻŋāĻ¸ā§āĻŸā§āϰāĻžāĻ•āϚāĻžāϰ " - -#~ msgid "Destructuring Arrays" -#~ msgstr "Arrays āĻĄāĻŋāĻ¸ā§āĻŸā§āϰāĻžāĻ•āϚāĻžāϰ " - -#~ msgid "Match Guards" -#~ msgstr "Match Guards" - -#~ msgid "Pattern Matching (TBD)" -#~ msgstr "āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āĻŽā§āϝāĻžāϚāĻŋāĻ‚ (TBD)" - -#~ msgid "Stack vs Heap" -#~ msgstr "Stack āĻŦāύāĻžāĻŽ Heap" - -#~ msgid "Stack Memory" -#~ msgstr "Stack āĻŽā§‡āĻŽā§‹āϰāĻŋ" - -#~ msgid "Manual Memory Management" -#~ msgstr "āĻŽā§āϝāĻžāύ⧁āϝāĻŧāĻžāϞ āĻŽā§‡āĻŽā§‹āϰāĻŋ āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻž" - -#~ msgid "Scope-Based Memory Management" -#~ msgstr "āĻ¸ā§āϕ⧋āĻĒ āĻ­āĻŋāĻ¤ā§āϤāĻŋāĻ• āĻŽā§‡āĻŽā§‹āϰāĻŋ āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻž" - -#~ msgid "Comparison" -#~ msgstr "āϤ⧁āϞāύāĻž" - -#~ msgid "Copying and Cloning" -#~ msgstr "āĻ…āύ⧁āϞāĻŋāĻĒāĻŋ āĻāĻŦāĻ‚ āĻ•ā§āϞ⧋āύāĻŋāĻ‚" - -#~ msgid "Shared and Unique Borrows" -#~ msgstr "āĻ­āĻžāĻ— āĻ•āϰāĻž āϧāĻžāϰ āĻāĻŦāĻ‚ āĻ…āύāĻ¨ā§āϝ āϧāĻžāϰ" - -#~ msgid "Storing Books" -#~ msgstr "āĻŦāχ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰāĻž" - -#~ msgid "Field Shorthand Syntax" -#~ msgstr "Field Shorthand Syntax" - -#~ msgid "Method Receiver" -#~ msgstr "Method Receiver" - -#~ msgid "Option and Result" -#~ msgstr "Option āĻāĻŦāĻ‚ Result" - -#~ msgid "Vec" -#~ msgstr "Vec" - -#~ msgid "HashMap" -#~ msgstr "HashMap" - -#~ msgid "Box" -#~ msgstr "Box" - -#~ msgid "Recursive Data Types" -#~ msgstr "āϰāĻŋāĻ•āĻžāĻ°ā§āϏāĻŋāĻ­ āĻĄā§‡āϟāĻž āϟāĻžāχāĻĒ" - -#~ msgid "Rc" -#~ msgstr "Rc" - -#~ msgid "Strings and Iterators" -#~ msgstr "Strings āĻāĻŦāĻ‚ Iterators" - -#~ msgid "Generic Methods" -#~ msgstr "āĻœā§‡āύ⧇āϰāĻŋāĻ• āĻŽā§‡āĻĨāĻĄ-āϏāĻŽā§‚āĻš" - -#~ msgid "Monomorphization" -#~ msgstr "Monomorphization" - -#~ msgid "Default Methods" -#~ msgstr "āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻŽā§‡āĻĨāĻĄ-āϏāĻŽā§‚āĻš" - -#~ msgid "impl Trait" -#~ msgstr "impl Trait" - -#~ msgid "Important Traits" -#~ msgstr "āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ Traits" - -#~ msgid "From and Into" -#~ msgstr "From āĻāĻŦāĻ‚ Into" - -#~ msgid "Default" -#~ msgstr "Default" - -#~ msgid "Operators: Add, Mul, ..." -#~ msgstr "āĻ…āĻĒāĻžāϰ⧇āϟāϰāσ Add, Mul, ..." - -#~ msgid "Closures: Fn, FnMut, FnOnce" -#~ msgstr "Closures: Fn, FnMut, FnOnce" - -#~ msgid "A Simple GUI Library" -#~ msgstr "āĻāĻ•āϟāĻŋ āϏāĻžāϧāĻžāϰāĻŖ GUI āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ" - -#~ msgid "Points and Polygons" -#~ msgstr "Points and Polygons" - -#~ msgid "Catching Stack Unwinding" -#~ msgstr "Catching Stack Unwinding" - -#~ msgid "Structured Error Handling" -#~ msgstr "āĻ¸ā§āĻŸā§āϰāĻžāĻ•āϚāĻžāĻ°ā§āĻĄ āĻāϰāϰ āĻšā§āϝāĻžāĻ¨ā§āĻĄāϞāĻŋāĻ‚" - -#~ msgid "Propagating Errors with ?" -#~ msgstr "āĻāϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ⧇ āĻāϰāϰ/āĻ¤ā§āϰ⧁āϟāĻŋ āĻšāĻ¸ā§āϤāĻžāĻ¨ā§āϤāϰ āĻ•āϰāĻž ?" - -#~ msgid "Converting Error Types" -#~ msgstr "āĻāϰāϰ⧇āϰ āϟāĻžāχāĻĒ āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ" - -#~ msgid "Deriving Error Enums" -#~ msgstr "āĻāϰāϰ⧇āϰ āχāύāĻžāĻŽāϗ⧁āϞ⧋ āĻŦ⧇āϰ āĻ•āϰāĻž" - -#~ msgid "Adding Context to Errors" -#~ msgstr "āĻ¤ā§āϰ⧁āϟāĻŋāϤ⧇ āĻ•āĻ¨ā§āĻŸā§‡āĻ•ā§āϏāϟ āϝ⧋āĻ— āĻ•āϰāĻž" - -#~ msgid "no_std" -#~ msgstr "no_std" - -#~ msgid "alloc" -#~ msgstr "alloc" - -#~ msgid "zerocopy" -#~ msgstr "zerocopy" - -#~ msgid "buddy_system_allocator" -#~ msgstr "buddy_system_allocator" - -#~ msgid "tinyvec" -#~ msgstr "tinyvec" - -#~ msgid "spin" -#~ msgstr "spin" - -#~ msgid "Send and Sync" -#~ msgstr "Send āĻāĻŦāĻ‚ Sync" - -#~ msgid "Send" -#~ msgstr "Send" - -#~ msgid "Sync" -#~ msgstr "Sync" - -#~ msgid "Arc" -#~ msgstr "Arc" - -#~ msgid "Mutex" -#~ msgstr "Mutex" - -#~ msgid "async/await" -#~ msgstr "async/await" - -#~ msgid "Pin" -#~ msgstr "Pin" - -#~ msgid "Day 1 Morning" -#~ msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ" - -#~ msgid "Day 1 Afternoon" -#~ msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύāσ āĻŦāĻŋāĻ•āĻžāϞ" - -#~ msgid "Day 2 Morning" -#~ msgstr "āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ" - -#~ msgid "Day 2 Afternoon" -#~ msgstr "āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āĻŦāĻŋāĻ•āĻžāϞ" - -#~ msgid "Day 3 Morning" -#~ msgstr "āϤ⧃āϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ" - -#~ msgid "Day 3 Afternoon" -#~ msgstr "āϤ⧃āϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āĻŦāĻŋāĻ•āĻžāϞ" - -#~ msgid "Bare Metal Rust Morning" -#~ msgstr "Bare Metal Rust: āϏāĻ•āĻžāϞ" - -#~ msgid "Concurrency Morning" -#~ msgstr "Concurrency: āĻŦāĻŋāĻ•āĻžāϞ" - -#~ msgid "Concurrency Afternoon" -#~ msgstr "Concurrency: āĻŦāĻŋāĻ•āĻžāϞ" - -#~ msgid "The course is fast paced and covers a lot of ground:" -#~ msgstr "āϕ⧋āĻ°ā§āϏāϟāĻŋ āĻĻā§āϰ⧁āϤ āĻ—āϤāĻŋāϰ āĻāĻŦāĻ‚ āĻ…āύ⧇āĻ• āĻ•āĻŋāϛ⧁ āĻ•āĻ­āĻžāϰ āĻ•āϰ⧇āσ" - -#~ msgid "" -#~ "Day 2: Memory management, ownership, compound data types, and the " -#~ "standard library." -#~ msgstr "" -#~ "āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āĻŽā§‡āĻŽā§‹āϰāĻŋ āĻŽā§āϝāĻžāύ⧇āϜāĻŽā§‡āĻ¨ā§āϟ, āĻŽāĻžāϞāĻŋāĻ•āĻžāύāĻž, āĻ•āĻŽā§āĻĒāĻžāωāĻ¨ā§āĻĄ āĻĄā§‡āϟāĻž āϟāĻžāχāĻĒāϏ, āĻāĻŦāĻ‚ āĻĻāĻŋ " -#~ "āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋāĨ¤" - -#~ msgid "Day 3: Generics, traits, error handling, testing, and unsafe Rust." -#~ msgstr "" -#~ "āϤ⧃āϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ Traits āĻāĻŦāĻ‚ Generics, āĻāϰāϰ āĻšā§āϝāĻžāĻ¨ā§āĻĄāϞāĻŋāĻ‚, āĻŸā§‡āĻ¸ā§āϟāĻŋāĻ‚, āĻāĻŦāĻ‚ āĻ…āύāĻŋāϰāĻžāĻĒāĻĻ āϰāĻžāĻ¸ā§āϟāĨ¤" - -#~ msgid "" -#~ "```shell\n" -#~ "cargo init concurrency\n" -#~ "cd concurrency\n" -#~ "cargo add tokio --features full\n" -#~ "cargo run\n" -#~ "```" -#~ msgstr "" -#~ "```shell\n" -#~ "cargo init concurrency\n" -#~ "cd concurrency\n" -#~ "cargo add tokio --features full\n" -#~ "cargo run\n" -#~ "```" - -#~ msgid "" -#~ "```shell\n" -#~ "sudo apt install cargo rust-src rustfmt\n" -#~ "```" -#~ msgstr "" -#~ "```shell\n" -#~ "sudo apt install cargo rust-src rustfmt\n" -#~ "```" - -#, fuzzy -#~ msgid "" -#~ "We suggest using [VS Code](https://code.visualstudio.com/) to edit the " -#~ "code (but any LSP compatible editor works with rust-analyzer[3](https://" -#~ "rust-analyzer.github.io/))." -#~ msgstr "" -#~ "āĻāϟāĻŋ \\[rust-analyzer\\] \\[1\\] āϕ⧇ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧ āϝ⧇āϤ⧇ āĻ…āύ⧁āĻŽāϤāĻŋ āĻĻ⧇āĻŦ⧇āĨ¤ āφāĻŽāϰāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ " -#~ "āĻ•āϰāĻžāϰ āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻĻāĻŋāχ [VS Code](https://code.visualstudio.com/) āϕ⧋āĻĄ āĻāĻĄāĻŋāϟ āĻ•āϰāϤ⧇ " -#~ "(āĻ•āĻŋāĻ¨ā§āϤ⧁ āϝ⧇āϕ⧋āύ⧋ LSP āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝāĻĒā§‚āĻ°ā§āĻŖ āĻāĻĄāĻŋāϟāϰ āĻ•āĻžāϜ āĻ•āϰ⧇)āĨ¤" - -#~ msgid "" -#~ "Some folks also like to use the [JetBrains](https://www.jetbrains.com/" -#~ "clion/) family of IDEs, which do their own analysis but have their own " -#~ "tradeoffs. If you prefer them, you can install the [Rust Plugin](https://" -#~ "www.jetbrains.com/rust/). Please take note that as of January 2023 " -#~ "debugging only works on the CLion version of the JetBrains IDEA suite." -#~ msgstr "" -#~ "āĻ•āĻŋāϛ⧁ āϞ⧋āĻ• IDE-āĻāϰ āϜāĻ¨ā§āϝ [JetBrains](https://www.jetbrains.com/clion/) āĻŦā§āϝāĻŦāĻšāĻžāϰ " -#~ "āĻ•āϰāϤ⧇ āĻĒāĻ›āĻ¨ā§āĻĻ āĻ•āϰ⧇, āϝāĻžāϰāĻž āϤāĻžāĻĻ⧇āϰ āύāĻŋāϜāĻ¸ā§āĻŦ āĻŦāĻŋāĻļā§āϞ⧇āώāϪ⧇ āĻ•āϰ⧇ āĻ•āĻŋāĻ¨ā§āϤ⧁ āϤāĻžāĻĻ⧇āϰ āύāĻŋāϜāĻ¸ā§āĻŦ āĻŸā§āϰ⧇āĻĄāĻ…āĻĢ " -#~ "āϰāϝāĻŧ⧇āϛ⧇āĨ¤ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āϤāĻžāĻĻ⧇āϰ āĻĒāĻ›āĻ¨ā§āĻĻ āĻ•āϰ⧇āύ āϤāĻŦ⧇ āφāĻĒāύāĻŋ [Rust Plugin](https://www." -#~ "jetbrains.com/rust/) āχāύāĻ¸ā§āϟāϞ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ āĻ…āύ⧁āĻ—ā§āϰāĻš āĻ•āϰ⧇ āĻŽāύ⧇ āϰāĻžāĻ–āĻŦ⧇āύ āϝ⧇ āϜāĻžāύ⧁āϝāĻŧāĻžāϰ⧀ " -#~ "2023 āĻ…āύ⧁āϝāĻžāϝāĻŧā§€ āĻĄāĻŋāĻŦāĻžāĻ—āĻŋāĻ‚ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ JetBrains IDEA āĻ¸ā§āϝ⧁āĻŸā§‡āϰ CLion āϏāĻ‚āĻ¸ā§āĻ•āϰāϪ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤" - -#~ msgid "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " println!(\"Edit me!\");\n" -#~ "}\n" -#~ "```" -#~ msgstr "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " println!(\"Edit me!\");\n" -#~ "}\n" -#~ "```" - -#, fuzzy -#~ msgid "" -#~ "```shell\n" -#~ "% rustc --version\n" -#~ "rustc 1.69.0 (84c898d65 2023-04-16)\n" -#~ "% cargo --version\n" -#~ "cargo 1.69.0 (6e9a83356 2023-04-12)\n" -#~ "```" -#~ msgstr "" -#~ "```shell\n" -#~ "% rustc --version\n" -#~ "rustc 1.61.0 (fe5b13d68 2022-05-18)\n" -#~ "% cargo --version\n" -#~ "cargo 1.61.0 (a028ae4 2022-04-29)\n" -#~ "```" - -#~ msgid "" -#~ "If you're teaching this in a classroom, this is a good place to go over " -#~ "the schedule. We suggest splitting the day into two parts (following the " -#~ "slides):" -#~ msgstr "" -#~ "āϝāĻĻāĻŋ āφāĻĒāύāĻŋ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻļā§āϰ⧇āύ⧀āĻ•āĻ•ā§āώ⧇ āĻĒāĻĄāĻŧāĻžāĻšā§āϛ⧇āύ, āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻ­āĻžāϞ⧋ āϝāĻžāϝāĻŧāĻ—āĻž āύāĻŋāϝāĻŧāĻŽāĻŽāĻžāĻĢāĻŋāĻ• āϚāϞāĻžāϰ " -#~ "āϜāĻ¨ā§āϝāĨ¤ āφāĻŽāϰāĻž āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻĻāĻŋāχ āϝ⧇ āĻĻāĻŋāύāϟāĻžāϕ⧇ āĻĻ⧁āχāϟāĻž āĻ­āĻžāϗ⧇ āĻ­āĻžāĻ— āĻ•āϰ⧁āύ(āĻ¸ā§āϞāĻžāχāĻĄāϗ⧁āϞ⧋āϕ⧇ āĻ…āύ⧁āϏāϰāύ āĻ•āϰ⧇):" - -#~ msgid "Morning: 9:00 to 12:00," -#~ msgstr "āϏāĻ•āĻžāϞāσ ⧝:ā§Ļā§Ļ āĻĨ⧇āϕ⧇ ⧧⧍:ā§Ļā§Ļ," - -#~ msgid "Afternoon: 13:00 to 16:00." -#~ msgstr "āĻŦāĻŋāĻ•āĻžāϞ ā§§:ā§Ļā§Ļ āĻĨ⧇āϕ⧇ ā§Ē:ā§Ļā§Ļ." - -#~ msgid "" -#~ "You can of course adjust this as necessary. Please make sure to include " -#~ "breaks, we recommend a break every hour!" -#~ msgstr "" -#~ "āφāĻĒāύāĻŋ āĻ…āĻŦāĻļā§āϝāχ āĻāϟāĻŋ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āĻ…āύ⧁āϏāĻžāϰ⧇ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ āĻ…āύ⧁āĻ—ā§āϰāĻš āĻ•āϰ⧇ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ " -#~ "āĻŦāĻŋāϰāϤāĻŋ āύāĻŋāϤ⧇, āφāĻŽāϰāĻž āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻĻāĻŋāχ āĻĒā§āϰāϤāĻŋ āϘāĻ¨ā§āϟāĻžāϝāĻŧ āĻāĻ•āĻŦāĻžāϰ āĻŦāĻŋāϰāϤāĻŋ āύāĻŋāϤ⧇!" - -#~ msgid "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " println!(\"Hello 🌍!\");\n" -#~ "}\n" -#~ "```" -#~ msgstr "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " println!(\"Hello 🌍!\");\n" -#~ "}\n" -#~ "```" - -#~ msgid "Here is a small example program in Rust:" -#~ msgstr "āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āϛ⧋āϟ āωāĻĻāĻžāĻšāϰāĻŖ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ Rust āĻ:" - -#~ msgid "" -#~ "```rust,editable\n" -#~ "fn main() { // Program entry point\n" -#~ " let mut x: i32 = 6; // Mutable variable binding\n" -#~ " print!(\"{x}\"); // Macro for printing, like printf\n" -#~ " while x != 1 { // No parenthesis around expression\n" -#~ " if x % 2 == 0 { // Math like in other languages\n" -#~ " x = x / 2;\n" -#~ " } else {\n" -#~ " x = 3 * x + 1;\n" -#~ " }\n" -#~ " print!(\" -> {x}\");\n" -#~ " }\n" -#~ " println!();\n" -#~ "}\n" -#~ "```" -#~ msgstr "" -#~ "```rust,editable\n" -#~ "fn main() { // Program entry point\n" -#~ " let mut x: i32 = 6; // Mutable variable binding\n" -#~ " print!(\"{x}\"); // Macro for printing, like printf\n" -#~ " while x != 1 { // No parenthesis around expression\n" -#~ " if x % 2 == 0 { // Math like in other languages\n" -#~ " x = x / 2;\n" -#~ " } else {\n" -#~ " x = 3 * x + 1;\n" -#~ " }\n" -#~ " print!(\" -> {x}\");\n" -#~ " }\n" -#~ " println!();\n" -#~ "}\n" -#~ "```" - -#, fuzzy -#~ msgid "Rust is built with all the experience gained in the last decades." -#~ msgstr "āĻ—āϤ 40 āĻŦāĻ›āϰ⧇ āĻ…āĻ°ā§āϜāĻŋāϤ āϏāĻŽāĻ¸ā§āϤ āĻ…āĻ­āĻŋāĻœā§āĻžāϤāĻž āĻĻāĻŋāϝāĻŧ⧇ Rust āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤" - -#~ msgid "Language Features" -#~ msgstr "āĻ­āĻžāώāĻžāϰ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāϏāĻŽā§‚āĻš" - -#~ msgid "Tooling" -#~ msgstr "Tooling" - -#~ msgid "`\"foo\"`, `\"two\\nlines\"`" -#~ msgstr "`\"foo\"`, `\"two\\nlines\"`" - -#~ msgid "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " println!(r#\"link\"#);\n" -#~ " println!(\"link\");\n" -#~ "}\n" -#~ "```" -#~ msgstr "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " println!(r#\"link\"#);\n" -#~ " println!(\"link\");\n" -#~ "}\n" -#~ "```" - -#~ msgid "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " println!(\"{:?}\", b\"abc\");\n" -#~ " println!(\"{:?}\", &[97, 98, 99]);\n" -#~ "}\n" -#~ "```" -#~ msgstr "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " println!(\"{:?}\", b\"abc\");\n" -#~ " println!(\"{:?}\", &[97, 98, 99]);\n" -#~ "}\n" -#~ "```" - -#~ msgid "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " let mut a: [i8; 10] = [42; 10];\n" -#~ " a[5] = 0;\n" -#~ " println!(\"a: {:?}\", a);\n" -#~ "}\n" -#~ "```" -#~ msgstr "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " let mut a: [i8; 10] = [42; 10];\n" -#~ " a[5] = 0;\n" -#~ " println!(\"a: {:?}\", a);\n" -#~ "}\n" -#~ "```" - -#~ msgid "Like C++, Rust has references:" -#~ msgstr "C++ āĻāϰ āĻŽāϤ⧋, Rust āĻāϰ āĻ“ references āφāϛ⧇" - -#, fuzzy -#~ msgid "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" -#~ " println!(\"a: {a:?}\");\n" -#~ "\n" -#~ " let s: &[i32] = &a[2..4];\n" -#~ "\n" -#~ " println!(\"s: {s:?}\");\n" -#~ "}\n" -#~ "```" -#~ msgstr "" -#~ "```rust,editable\n" -#~ "fn main() {\n" -#~ " let mut a: [i8; 10] = [42; 10];\n" -#~ " a[5] = 0;\n" -#~ " println!(\"a: {:?}\", a);\n" -#~ "}\n" -#~ "```" - -#~ msgid "Day 1: Morning Exercises" -#~ msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ⧇āϰ āĻ…āύ⧁āĻļā§€āϞāύ" - -#, fuzzy -#~ msgid "The Luhn algorithm," -#~ msgstr "āϞ⧁āύ āĻ…ā§āϝāĻžāϞāĻ—āϰāĻŋāĻĻāĻŽ" - -#, fuzzy -#~ msgid "An exercise on pattern matching." -#~ msgstr "Enums and pattern matching." - -#, fuzzy -#~ msgid "Structs and methods." -#~ msgstr "Strings āĻāĻŦāĻ‚ Iterators" - -#, fuzzy -#~ msgid "Stack and Heap Example" -#~ msgstr "Stack āĻŦāύāĻžāĻŽ Heap" - -#~ msgid "You allocate and deallocate heap memory yourself." -#~ msgstr "āφāĻĒāύāĻŋ āύāĻŋāĻœā§‡āχ heap-memory āĻāϞ⧋āϕ⧇āϟ āĻāĻŦāĻ‚ āĻĄāĻŋ-āĻāϞ⧋āϕ⧇āϟ āĻ•āϰ⧁āύāĨ¤" - -#~ msgid "C Example" -#~ msgstr "C āωāĻĻāĻžāĻšāϰāĻŖ" - -#, fuzzy -#~ msgid "Extra Work in Modern C++" -#~ msgstr "āφāϧ⧁āύāĻŋāĻ• C++ āĻ āĻĄāĻŦāϞ āĻŽā§āĻ•ā§āϤ" - -#~ msgid "Day 2: Morning Exercises" -#~ msgstr "āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ⧇āϰ āĻ…āύ⧁āĻļāĻŋāϞāύ" - -#~ msgid "Day 3: Morning Exercises" -#~ msgstr "āϤ⧃āϤ⧀āϝāĻŧ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ⧇āϰ āĻ…āύ⧁āĻļā§€āϞāύ" - -#, fuzzy -#~ msgid "" -#~ "```shell\n" -#~ "adb logcat -s rust\n" -#~ "```" -#~ msgstr "" -#~ "```shell\n" -#~ "$ sudo apt install cargo rust-src rustfmt\n" -#~ "```" - -#, fuzzy -#~ msgid "" -#~ "```shell\n" -#~ "cargo new link-checker\n" -#~ "cd link-checker\n" -#~ "cargo add --features blocking,rustls-tls reqwest\n" -#~ "```" -#~ msgstr "" -#~ "```shell\n" -#~ "cargo init concurrency\n" -#~ "cd concurrency\n" -#~ "cargo add tokio --features full\n" -#~ "cargo run\n" -#~ "```" - -#~ msgid "You will find solutions to the exercises on the following pages." -#~ msgstr "āφāĻĒāύāĻŋ āĻ…āύ⧁āĻļā§€āϞāύ⧀āϰ āϏāĻŽāĻžāϧāĻžāύ āĻāχ āĻĒ⧃āĻˇā§āĻ āĻžāϗ⧁āϞ⧋āϤ⧇ āϖ⧁āĻœā§‡ āĻĒāĻžāĻŦ⧇āύāĨ¤" - -#~ msgid "Day 1 Morning Exercises" -#~ msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύāσ āϏāĻ•āĻžāϞ⧇āϰ āĻ…āύ⧁āĻļā§€āϞāύ" - -#, fuzzy -#~ msgid "Pattern matching" -#~ msgstr "āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āĻŽāĻŋāϞāĻžāύ⧋" - -#~ msgid "Elevator Operations" -#~ msgstr "āϞāĻŋāĻĢāϟ āĻ…āĻĒāĻžāϰ⧇āĻļāύ" - -#~ msgid "" -#~ "[![Build workflow](https://img.shields.io/github/actions/workflow/status/" -#~ "google/comprehensive-rust/build.yml?style=flat-square)](https://github." -#~ "com/google/comprehensive-rust/actions/workflows/build.yml)" -#~ msgstr "" -#~ "[![Build workflow](https://img.shields.io/github/actions/workflow/status/" -#~ "google/comprehensive-rust/build.yml?style=flat-square)](https://github." -#~ "com/google/comprehensive-rust/actions/workflows/build.yml)" - -#~ msgid "Build workflow" -#~ msgstr "āĻ•āĻ°ā§āĻŽāĻĒā§āϰāĻŦāĻžāĻš āϤ⧈āϰāĻŋ" - -#~ msgid "GitHub contributors" -#~ msgstr "GitHub āĻ…āĻŦāĻĻāĻžāύāĻ•āĻžāϰ⧀" - -#~ msgid "" -#~ "[![GitHub contributors](https://img.shields.io/github/contributors/google/" -#~ "comprehensive-rust?style=flat-square)](https://github.com/google/" -#~ "comprehensive-rust/graphs/contributors) [![GitHub stars](https://img." -#~ "shields.io/github/stars/google/comprehensive-rust?style=flat-square)]" -#~ "(https://github.com/google/comprehensive-rust/stargazers)" -#~ msgstr "" -#~ "[![GitHub contributors](https://img.shields.io/github/contributors/google/" -#~ "comprehensive-rust?style=flat-square)](https://github.com/google/" -#~ "comprehensive-rust/graphs/contributors) [![GitHub stars](https://img." -#~ "shields.io/github/stars/google/comprehensive-rust?style=flat-square)]" -#~ "(https://github.com/google/comprehensive-rust/stargazers)" - -#~ msgid "GitHub stars" -#~ msgstr "GitHub stars" - -#~ msgid "" -#~ "[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" -#~ "rust?style=flat-square)](https://github.com/google/comprehensive-rust/" -#~ "stargazers)" -#~ msgstr "" -#~ "[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" -#~ "rust?style=flat-square)](https://github.com/google/comprehensive-rust/" -#~ "stargazers)" - -#~ msgid "Day 1: Basic Rust, ownership and the borrow checker." -#~ msgstr "āĻĒā§āϰāĻĨāĻŽ āĻĻāĻŋāύāσ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āϰāĻžāĻ¸ā§āϟ, āĻŽāĻžāϞāĻŋāĻ•āĻžāύāĻž āĻāĻŦāĻ‚ āϧāĻžāϰ āĻĒāϰ⧀āĻ•ā§āώāĻ•āĨ¤" - -#~ msgid "Concurrency" -#~ msgstr "Concurrency" - -#~ msgid "Rustup (Recommended)" -#~ msgstr "Rustup (āĻĒā§āϰāĻ¸ā§āϤāĻžāĻŦāĻŋāϤ)" - -#~ msgid "" -#~ "You can follow the instructions to install cargo and rust compiler, among " -#~ "other standard ecosystem tools with the [rustup](https://rust-analyzer." -#~ "github.io/) tool, which is maintained by the Rust Foundation." -#~ msgstr "" -#~ "āϰāĻžāĻ¸ā§āϟ āĻĢāĻžāωāĻ¨ā§āĻĄā§‡āĻļāύ āĻĻā§āĻŦāĻžāϰāĻž āϰāĻ•ā§āώāĻŖāĻžāĻŦ⧇āĻ•ā§āώāĻŖ āĻ•āϰāĻž [rustup](https://rust-analyzer.github." -#~ "io/) āϟ⧁āϞ āϏāĻš āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āχāϕ⧋āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ āϟ⧁āϞ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āφāĻĒāύāĻŋ Cargo āĻāĻŦāĻ‚ āϰāĻžāĻ¸ā§āϟ " -#~ "āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻžāϰ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻžāĻŦāϞ⧀ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤" - -#~ msgid "Package Managers" -#~ msgstr "āĻĒā§āϝāĻžāϕ⧇āϜ āĻŽā§āϝāĻžāύ⧇āϜāĻžāϰ" - -#~ msgid "Debian" -#~ msgstr "Debian" From a3d0c7eb235bf3e59ee238d04bbc8e0a8e8cb973 Mon Sep 17 00:00:00 2001 From: Al Rifat Sabbir Date: Thu, 19 Mar 2026 14:47:24 +0600 Subject: [PATCH 2/3] fix: remove duplicate translation key in labeler.yml --- .github/labeler.yml | 3 --- messages.mo | Bin 0 -> 360 bytes 2 files changed, 3 deletions(-) create mode 100644 messages.mo diff --git a/.github/labeler.yml b/.github/labeler.yml index f7fe7161237c..4e9e725797e7 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -85,6 +85,3 @@ translation: "translation/zh-TW": - changed-files: - any-glob-to-any-file: po/zh-TW.po -"translation/bn": - - changed-files: - - any-glob-to-any-file: po/bn.po \ No newline at end of file diff --git a/messages.mo b/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..50bc6cd17c0f5a9639997fc8f48030916b49cb24 GIT binary patch literal 360 zcmYL@&q~8U5XLKd%F(ljIe1WXTJ7UufgkQkR#*Xf~aV58;xS zM>G0#N4k0}4{7tP;>K+tpw2u7Xc`;$>!PjJ2k!53Dm}R&sAkC%UKNpbeC{r7Y XicO5IoB&<_jc$ Date: Sun, 12 Apr 2026 11:13:59 +0200 Subject: [PATCH 3/3] Delete unnecessary messages.mo --- messages.mo | Bin 360 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 messages.mo diff --git a/messages.mo b/messages.mo deleted file mode 100644 index 50bc6cd17c0f5a9639997fc8f48030916b49cb24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 360 zcmYL@&q~8U5XLKd%F(ljIe1WXTJ7UufgkQkR#*Xf~aV58;xS zM>G0#N4k0}4{7tP;>K+tpw2u7Xc`;$>!PjJ2k!53Dm}R&sAkC%UKNpbeC{r7Y XicO5IoB&<_jc$