diff --git a/po/fa.po b/po/fa.po index 1d21c6e6..a7a3bd78 100644 --- a/po/fa.po +++ b/po/fa.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Comprehensive Rust 🦀\n" -"POT-Creation-Date: 2023-08-23\n" +"POT-Creation-Date: 2023-10-25T14:05:24+03:30\n" "PO-Revision-Date: 2023-08-08 21:41+0330\n" "Last-Translator: danny \n" "Language-Team: Persian\n" @@ -14,7 +14,7 @@ msgstr "" #: src/SUMMARY.md:4 src/index.md:1 msgid "Welcome to Comprehensive Rust 🦀" -msgstr "Welcome to Comprehensive Rust 🦀" +msgstr "به Comprehensive Rust خوش آمدید 🦀" #: src/SUMMARY.md:5 src/running-the-course.md:1 msgid "Running the Course" @@ -52,8 +52,8 @@ msgstr "اجرای cargo روی ماشین local" msgid "Day 1: Morning" msgstr "روز اول: صبح" -#: src/SUMMARY.md:19 src/SUMMARY.md:76 src/SUMMARY.md:129 src/SUMMARY.md:186 -#: src/SUMMARY.md:212 src/SUMMARY.md:262 +#: src/SUMMARY.md:19 src/SUMMARY.md:80 src/SUMMARY.md:135 src/SUMMARY.md:193 +#: src/SUMMARY.md:219 src/SUMMARY.md:269 msgid "Welcome" msgstr "خوش آمدید" @@ -63,7 +63,7 @@ msgstr "زبان Rust چیست؟" #: src/SUMMARY.md:21 src/hello-world.md:1 msgid "Hello World!" -msgstr "Hello World!" +msgstr "سلام دنیا" #: src/SUMMARY.md:22 src/hello-world/small-example.md:1 msgid "Small Example" @@ -73,66 +73,71 @@ msgstr "یک مثال ساده" msgid "Why Rust?" msgstr "چرا Rust؟" -#: src/SUMMARY.md:24 src/why-rust/compile-time.md:1 +#: src/SUMMARY.md:24 src/why-rust/an-example-in-c.md:1 src/credits.md:32 +#, fuzzy +msgid "An Example in C" +msgstr "یک مثال در زبان C" + +#: src/SUMMARY.md:25 src/why-rust/compile-time.md:1 msgid "Compile Time Guarantees" -msgstr "Compile Time Guarantees" +msgstr "ضمانت‌های زمان کامپایل" -#: src/SUMMARY.md:25 src/why-rust/runtime.md:1 +#: src/SUMMARY.md:26 src/why-rust/runtime.md:1 msgid "Runtime Guarantees" -msgstr "Runtime Guarantees" +msgstr "ضمانت‌های زمان اجرا" -#: src/SUMMARY.md:26 src/why-rust/modern.md:1 +#: src/SUMMARY.md:27 src/why-rust/modern.md:1 msgid "Modern Features" msgstr "ویژگی‌های جدید" -#: src/SUMMARY.md:27 src/basic-syntax.md:1 +#: src/SUMMARY.md:28 src/basic-syntax.md:1 msgid "Basic Syntax" msgstr "سینتکس‌های مقدماتی" -#: src/SUMMARY.md:28 src/basic-syntax/scalar-types.md:1 +#: src/SUMMARY.md:29 src/basic-syntax/scalar-types.md:1 msgid "Scalar Types" -msgstr "Scalar Types" +msgstr "تایپ‌های عددی" -#: src/SUMMARY.md:29 src/basic-syntax/compound-types.md:1 +#: src/SUMMARY.md:30 src/basic-syntax/compound-types.md:1 msgid "Compound Types" -msgstr "Compound Types" +msgstr "تایپ‌های مرکب" -#: src/SUMMARY.md:30 src/basic-syntax/references.md:1 +#: src/SUMMARY.md:31 src/basic-syntax/references.md:1 msgid "References" msgstr "مراجع" -#: src/SUMMARY.md:31 src/basic-syntax/references-dangling.md:1 +#: src/SUMMARY.md:32 src/basic-syntax/references-dangling.md:1 msgid "Dangling References" msgstr "ارجاعات تعلیق شده" -#: src/SUMMARY.md:32 src/basic-syntax/slices.md:1 +#: src/SUMMARY.md:33 src/basic-syntax/slices.md:1 msgid "Slices" -msgstr "Slices" +msgstr "برش ها" -#: src/SUMMARY.md:33 +#: src/SUMMARY.md:34 msgid "String vs str" msgstr "String در مقابل str" -#: src/SUMMARY.md:34 src/basic-syntax/functions.md:1 +#: src/SUMMARY.md:35 src/basic-syntax/functions.md:1 msgid "Functions" msgstr "توابع" -#: src/SUMMARY.md:35 src/basic-syntax/rustdoc.md:1 +#: src/SUMMARY.md:36 src/basic-syntax/rustdoc.md:1 msgid "Rustdoc" -msgstr "Rustdoc" +msgstr "داکیومنت نویسی" -#: src/SUMMARY.md:36 src/SUMMARY.md:83 src/basic-syntax/methods.md:1 +#: src/SUMMARY.md:37 src/SUMMARY.md:103 src/basic-syntax/methods.md:1 #: src/methods.md:1 msgid "Methods" msgstr "متدها" -#: src/SUMMARY.md:37 +#: src/SUMMARY.md:38 msgid "Overloading" msgstr "سربارگذاری" -#: src/SUMMARY.md:38 src/SUMMARY.md:67 src/SUMMARY.md:91 src/SUMMARY.md:120 -#: src/SUMMARY.md:149 src/SUMMARY.md:178 src/SUMMARY.md:205 src/SUMMARY.md:226 -#: src/SUMMARY.md:254 src/SUMMARY.md:276 src/SUMMARY.md:297 +#: src/SUMMARY.md:39 src/SUMMARY.md:72 src/SUMMARY.md:106 src/SUMMARY.md:126 +#: src/SUMMARY.md:155 src/SUMMARY.md:185 src/SUMMARY.md:212 src/SUMMARY.md:233 +#: src/SUMMARY.md:261 src/SUMMARY.md:283 src/SUMMARY.md:304 #: src/exercises/android/morning.md:1 src/exercises/bare-metal/morning.md:1 #: src/exercises/bare-metal/afternoon.md:1 #: src/exercises/concurrency/morning.md:1 @@ -140,921 +145,905 @@ msgstr "سربارگذاری" msgid "Exercises" msgstr "تمرین‌ها" -#: src/SUMMARY.md:39 src/exercises/day-1/implicit-conversions.md:1 +#: src/SUMMARY.md:40 src/exercises/day-1/implicit-conversions.md:1 msgid "Implicit Conversions" -msgstr "تبدیل های غیر صریح" +msgstr "تبدیل‌های غیر صریح" -#: src/SUMMARY.md:40 +#: src/SUMMARY.md:41 msgid "Arrays and for Loops" msgstr "آرایه ها و حلقه های for" -#: src/SUMMARY.md:42 +#: src/SUMMARY.md:43 msgid "Day 1: Afternoon" msgstr "روز ۱: بعد از ظهر" -#: src/SUMMARY.md:44 src/basic-syntax/variables.md:1 +#: src/SUMMARY.md:45 src/SUMMARY.md:296 src/control-flow.md:1 +msgid "Control Flow" +msgstr "کنترل جریان" + +#: src/SUMMARY.md:46 src/control-flow/blocks.md:1 +msgid "Blocks" +msgstr "بلوک‌ها" + +#: src/SUMMARY.md:47 +msgid "if expressions" +msgstr "عبارت if" + +#: src/SUMMARY.md:48 +msgid "for expressions" +msgstr "عبارت for" + +#: src/SUMMARY.md:49 +msgid "while expressions" +msgstr "عبارت حلقه while" + +#: src/SUMMARY.md:50 +msgid "break & continue" +msgstr "توقف و ادامه دادن (break & continue)" + +#: src/SUMMARY.md:51 +msgid "loop expressions" +msgstr "عبارت loop" + +#: src/SUMMARY.md:53 src/basic-syntax/variables.md:1 msgid "Variables" msgstr "متغیرها" -#: src/SUMMARY.md:45 src/basic-syntax/type-inference.md:1 +#: src/SUMMARY.md:54 src/basic-syntax/type-inference.md:1 msgid "Type Inference" -msgstr "Type Inference" +msgstr "تعیین تایپ ضمنی" -#: src/SUMMARY.md:46 +#: src/SUMMARY.md:55 msgid "static & const" msgstr "نمادهای ایستا و ثابت" -#: src/SUMMARY.md:47 src/basic-syntax/scopes-shadowing.md:1 +#: src/SUMMARY.md:56 src/basic-syntax/scopes-shadowing.md:1 msgid "Scopes and Shadowing" msgstr "محدوده‌ها و سایه‌گذاری" -#: src/SUMMARY.md:48 src/memory-management.md:1 -msgid "Memory Management" -msgstr "مدیریت حافظه" - -#: src/SUMMARY.md:49 -msgid "Stack vs Heap" -msgstr "Stack vs Heap" - -#: src/SUMMARY.md:50 -msgid "Stack Memory" -msgstr "حافظه Stack" - -#: src/SUMMARY.md:51 src/memory-management/manual.md:1 -msgid "Manual Memory Management" -msgstr "مدیریت دستی حافظه" - -#: src/SUMMARY.md:52 src/memory-management/scope-based.md:1 -msgid "Scope-Based Memory Management" -msgstr "مدیریت حافظه مبتنی بر دامنه" - -#: src/SUMMARY.md:53 -msgid "Garbage Collection" -msgstr "Garbage Collection" - -#: src/SUMMARY.md:54 -msgid "Rust Memory Management" -msgstr "مدیریت منابع Rust" - -#: src/SUMMARY.md:55 src/memory-management/comparison.md:1 -msgid "Comparison" -msgstr "مقایسه" - -#: src/SUMMARY.md:56 src/ownership.md:1 -msgid "Ownership" -msgstr "مالکیت" - -#: src/SUMMARY.md:57 src/ownership/move-semantics.md:1 -msgid "Move Semantics" -msgstr "مفاهیم جابجایی" - -#: src/SUMMARY.md:58 src/ownership/moved-strings-rust.md:1 -msgid "Moved Strings in Rust" -msgstr "های جابجا شده در Rust String" - -#: src/SUMMARY.md:59 -msgid "Double Frees in Modern C++" -msgstr "آزاد سازی مضاعف در مدرن سی++" - -#: src/SUMMARY.md:60 src/ownership/moves-function-calls.md:1 -msgid "Moves in Function Calls" -msgstr "حرکت‌ها در فراخوانی توابع" - -#: src/SUMMARY.md:61 src/ownership/copy-clone.md:1 -msgid "Copying and Cloning" -msgstr "کپی برداری و شبیه سازی" - -#: src/SUMMARY.md:62 src/ownership/borrowing.md:1 -msgid "Borrowing" -msgstr "قرض گرفتن" - -#: src/SUMMARY.md:63 src/ownership/shared-unique-borrows.md:1 -msgid "Shared and Unique Borrows" -msgstr "قرض گرفتن های مشترک و منحصر به فرد" - -#: src/SUMMARY.md:64 src/ownership/lifetimes.md:1 -msgid "Lifetimes" -msgstr "چرخه حیات" - -#: src/SUMMARY.md:65 src/ownership/lifetimes-function-calls.md:1 -msgid "Lifetimes in Function Calls" -msgstr "طول عمر فراخوانی های تابع" - -#: src/SUMMARY.md:66 src/ownership/lifetimes-data-structures.md:1 -msgid "Lifetimes in Data Structures" -msgstr "طول عمر در ساختمان داده" - -#: src/SUMMARY.md:68 src/exercises/day-1/book-library.md:1 -msgid "Storing Books" -msgstr "ذخیره سازی کتاب" - -#: src/SUMMARY.md:69 src/exercises/day-1/iterators-and-ownership.md:1 -msgid "Iterators and Ownership" -msgstr "تکرار کننده ها و مالکیت" - -#: src/SUMMARY.md:72 -msgid "Day 2: Morning" -msgstr "روز دوم: صبح" - -#: src/SUMMARY.md:77 src/structs.md:1 -msgid "Structs" -msgstr "ساختارها" - -#: src/SUMMARY.md:78 src/structs/tuple-structs.md:1 -msgid "Tuple Structs" -msgstr "Tuple Structs" - -#: src/SUMMARY.md:79 src/structs/field-shorthand.md:1 -msgid "Field Shorthand Syntax" -msgstr "نحو اختصاری فیلد" - -#: src/SUMMARY.md:80 src/enums.md:1 +#: src/SUMMARY.md:57 src/enums.md:1 msgid "Enums" msgstr "Enums" -#: src/SUMMARY.md:81 src/enums/variant-payloads.md:1 +#: src/SUMMARY.md:58 src/enums/variant-payloads.md:1 msgid "Variant Payloads" msgstr "Variant Payloads" -#: src/SUMMARY.md:82 src/enums/sizes.md:1 +#: src/SUMMARY.md:59 src/enums/sizes.md:1 msgid "Enum Sizes" msgstr "اندازه ی Enum ها" -#: src/SUMMARY.md:84 src/methods/receiver.md:1 +#: src/SUMMARY.md:61 src/control-flow/novel.md:1 +#, fuzzy +msgid "Novel Control Flow" +msgstr "کنترل جریان پیشرفته" + +#: src/SUMMARY.md:62 +msgid "if let expressions" +msgstr "عبارت if let" + +#: src/SUMMARY.md:63 +msgid "while let expressions" +msgstr "عبارت while let" + +#: src/SUMMARY.md:64 +msgid "match expressions" +msgstr "عبارت تطبیق" + +#: src/SUMMARY.md:66 src/SUMMARY.md:74 src/pattern-matching.md:1 +msgid "Pattern Matching" +msgstr "تطبیق الگو" + +#: src/SUMMARY.md:67 src/pattern-matching/destructuring-enums.md:1 +msgid "Destructuring Enums" +msgstr "تخریب Enumها" + +#: src/SUMMARY.md:68 src/pattern-matching/destructuring-structs.md:1 +msgid "Destructuring Structs" +msgstr "تخریب ساختارها" + +#: src/SUMMARY.md:69 src/pattern-matching/destructuring-arrays.md:1 +msgid "Destructuring Arrays" +msgstr "تخریب آرایه‌ها" + +#: src/SUMMARY.md:70 src/pattern-matching/match-guards.md:1 +msgid "Match Guards" +msgstr "گاردهای تطبیق" + +#: src/SUMMARY.md:73 src/exercises/day-1/luhn.md:1 +#: src/exercises/day-1/solutions-afternoon.md:3 +msgid "Luhn Algorithm" +msgstr "الگوریتم Luhn" + +#: src/SUMMARY.md:76 +msgid "Day 2: Morning" +msgstr "روز دوم: صبح" + +#: src/SUMMARY.md:82 src/memory-management.md:1 +msgid "Memory Management" +msgstr "مدیریت حافظه" + +#: src/SUMMARY.md:83 +msgid "Stack vs Heap" +msgstr "مقایسه پشته و انباشت" + +#: src/SUMMARY.md:84 +msgid "Stack Memory" +msgstr "حافظه پشته" + +#: src/SUMMARY.md:85 src/memory-management/manual.md:1 +msgid "Manual Memory Management" +msgstr "مدیریت دستی حافظه" + +#: src/SUMMARY.md:86 src/memory-management/scope-based.md:1 +msgid "Scope-Based Memory Management" +msgstr "مدیریت حافظه مبتنی بر دامنه" + +#: src/SUMMARY.md:87 +msgid "Garbage Collection" +msgstr "جمع آوری زباله (GC)" + +#: src/SUMMARY.md:88 +msgid "Rust Memory Management" +msgstr "مدیریت حافظه Rust" + +#: src/SUMMARY.md:89 src/ownership.md:1 +msgid "Ownership" +msgstr "مالکیت" + +#: src/SUMMARY.md:90 src/ownership/move-semantics.md:1 +msgid "Move Semantics" +msgstr "مفاهیم جابه‌جایی" + +#: src/SUMMARY.md:91 src/ownership/moved-strings-rust.md:1 +msgid "Moved Strings in Rust" +msgstr "های جابجا شده در Rust String" + +#: src/SUMMARY.md:92 +msgid "Double Frees in Modern C++" +msgstr "آزاد سازی مضاعف در مدرن سی++" + +#: src/SUMMARY.md:93 src/ownership/moves-function-calls.md:1 +msgid "Moves in Function Calls" +msgstr "جابه‌جایی در صدا زدن توابع" + +#: src/SUMMARY.md:94 src/ownership/copy-clone.md:1 +msgid "Copying and Cloning" +msgstr "کپی برداری و شبیه سازی" + +#: src/SUMMARY.md:95 src/ownership/borrowing.md:1 +msgid "Borrowing" +msgstr "قرض گرفتن" + +#: src/SUMMARY.md:96 src/ownership/shared-unique-borrows.md:1 +msgid "Shared and Unique Borrows" +msgstr "قرض گرفتن‌های مشترک و منحصر به فرد" + +#: src/SUMMARY.md:97 src/ownership/lifetimes.md:1 +msgid "Lifetimes" +msgstr "چرخه حیات" + +#: src/SUMMARY.md:98 src/ownership/lifetimes-function-calls.md:1 +msgid "Lifetimes in Function Calls" +msgstr "طول عمر در فراخوانی‌ توابع" + +#: src/SUMMARY.md:99 src/ownership/lifetimes-data-structures.md:1 +msgid "Lifetimes in Data Structures" +msgstr "طول عمر در ساختمان داده" + +#: src/SUMMARY.md:100 src/structs.md:1 +msgid "Structs" +msgstr "ساختارها" + +#: src/SUMMARY.md:101 src/structs/tuple-structs.md:1 +msgid "Tuple Structs" +msgstr "ساختار‌های چند‌گانه (Tuple Structs)" + +#: src/SUMMARY.md:102 src/structs/field-shorthand.md:1 +msgid "Field Shorthand Syntax" +msgstr "نحو اختصاری فیلد" + +#: src/SUMMARY.md:104 src/methods/receiver.md:1 msgid "Method Receiver" msgstr "متد دریافتی" -#: src/SUMMARY.md:85 src/SUMMARY.md:160 src/SUMMARY.md:275 +#: src/SUMMARY.md:105 src/SUMMARY.md:167 src/SUMMARY.md:282 #: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 msgid "Example" msgstr "مثال" -#: src/SUMMARY.md:86 src/pattern-matching.md:1 -msgid "Pattern Matching" -msgstr "تطبیق الگو" +#: src/SUMMARY.md:107 src/exercises/day-2/book-library.md:1 +msgid "Storing Books" +msgstr "ذخیره سازی کتاب" -#: src/SUMMARY.md:87 src/pattern-matching/destructuring-enums.md:1 -msgid "Destructuring Enums" -msgstr "تخریب Enumها" - -#: src/SUMMARY.md:88 src/pattern-matching/destructuring-structs.md:1 -msgid "Destructuring Structs" -msgstr "تخریب ساختارها" - -#: src/SUMMARY.md:89 src/pattern-matching/destructuring-arrays.md:1 -msgid "Destructuring Arrays" -msgstr "تخریب آرایه‌ها" - -#: src/SUMMARY.md:90 src/pattern-matching/match-guards.md:1 -msgid "Match Guards" -msgstr "گاردهای تطبیق" - -#: src/SUMMARY.md:92 src/exercises/day-2/health-statistics.md:1 +#: src/SUMMARY.md:108 src/exercises/day-2/health-statistics.md:1 +#: src/exercises/day-2/solutions-morning.md:151 msgid "Health Statistics" msgstr "آمارهای سلامتی" -#: src/SUMMARY.md:93 src/exercises/day-2/solutions-morning.md:3 -msgid "Points and Polygons" -msgstr "نقطه‌ها و چند ضلعی‌ها" - -#: src/SUMMARY.md:95 +#: src/SUMMARY.md:110 msgid "Day 2: Afternoon" msgstr "روز دوم: عصر" -#: src/SUMMARY.md:97 src/SUMMARY.md:289 src/control-flow.md:1 -msgid "Control Flow" -msgstr "کنترل مسیر" - -#: src/SUMMARY.md:98 src/control-flow/blocks.md:1 -msgid "Blocks" -msgstr "بلوک‌ها" - -#: src/SUMMARY.md:99 -msgid "if expressions" -msgstr "عبارت if" - -#: src/SUMMARY.md:100 -msgid "if let expressions" -msgstr "عبارت if let" - -#: src/SUMMARY.md:101 -msgid "while expressions" -msgstr "عبارت حلقه while" - -#: src/SUMMARY.md:102 -msgid "while let expressions" -msgstr "عبارت while let" - -#: src/SUMMARY.md:103 -msgid "for expressions" -msgstr "عبارت for" - -#: src/SUMMARY.md:104 -msgid "loop expressions" -msgstr "عبارت loop" - -#: src/SUMMARY.md:105 -msgid "match expressions" -msgstr "عبارت تطبیق" - -#: src/SUMMARY.md:106 -msgid "break & continue" -msgstr "توقف و ادامه دادن (break & continue)" - -#: src/SUMMARY.md:107 src/std.md:1 +#: src/SUMMARY.md:112 src/std.md:1 msgid "Standard Library" msgstr "کتابخانه‌های استاندارد" -#: src/SUMMARY.md:108 +#: src/SUMMARY.md:113 msgid "Option and Result" msgstr "Option و Result" -#: src/SUMMARY.md:109 src/std/string.md:1 +#: src/SUMMARY.md:114 src/std/string.md:1 msgid "String" msgstr "String" -#: src/SUMMARY.md:110 +#: src/SUMMARY.md:115 msgid "Vec" msgstr "Vec" -#: src/SUMMARY.md:111 +#: src/SUMMARY.md:116 msgid "HashMap" msgstr "HashMap" -#: src/SUMMARY.md:112 +#: src/SUMMARY.md:117 msgid "Box" msgstr "Box" -#: src/SUMMARY.md:113 +#: src/SUMMARY.md:118 msgid "Recursive Data Types" -msgstr "انواع داده های بازگشتی" +msgstr "انواع داده‌های بازگشتی" -#: src/SUMMARY.md:114 src/std/box-niche.md:1 +#: src/SUMMARY.md:119 src/std/box-niche.md:1 msgid "Niche Optimization" msgstr "بهینه سازی Niche" -#: src/SUMMARY.md:115 +#: src/SUMMARY.md:120 msgid "Rc" msgstr "Rc" -#: src/SUMMARY.md:116 src/modules.md:1 +#: src/SUMMARY.md:121 +msgid "Cell/RefCell" +msgstr "" + +#: src/SUMMARY.md:122 src/modules.md:1 msgid "Modules" msgstr "ماژول‌ها" -#: src/SUMMARY.md:117 src/modules/visibility.md:1 +#: src/SUMMARY.md:123 src/modules/visibility.md:1 msgid "Visibility" msgstr "قابلیت دید" -#: src/SUMMARY.md:118 src/modules/paths.md:1 +#: src/SUMMARY.md:124 src/modules/paths.md:1 msgid "Paths" msgstr "مسیر" -#: src/SUMMARY.md:119 src/modules/filesystem.md:1 +#: src/SUMMARY.md:125 src/modules/filesystem.md:1 msgid "Filesystem Hierarchy" -msgstr "توالی فایل سیستم‌ها" +msgstr "سلسله‌ مراتب فایل‌سیستم" -#: src/SUMMARY.md:121 src/exercises/day-2/luhn.md:1 +#: src/SUMMARY.md:127 src/exercises/day-2/iterators-and-ownership.md:1 +msgid "Iterators and Ownership" +msgstr "تکرار کننده ها و مالکیت" + +#: src/SUMMARY.md:128 src/exercises/day-2/strings-iterators.md:1 #: src/exercises/day-2/solutions-afternoon.md:3 -msgid "Luhn Algorithm" -msgstr "الگوریتم Luhn" - -#: src/SUMMARY.md:122 src/exercises/day-2/strings-iterators.md:1 -#: src/exercises/day-2/solutions-afternoon.md:97 msgid "Strings and Iterators" msgstr "رشته ها و تکرار کننده‌ها (Strings and Iterators)" -#: src/SUMMARY.md:125 +#: src/SUMMARY.md:131 msgid "Day 3: Morning" msgstr "روز سوم: صبح" -#: src/SUMMARY.md:130 src/generics.md:1 +#: src/SUMMARY.md:136 src/generics.md:1 msgid "Generics" -msgstr "Generics" +msgstr "جنریک‌ها" -#: src/SUMMARY.md:131 src/generics/data-types.md:1 +#: src/SUMMARY.md:137 src/generics/data-types.md:1 msgid "Generic Data Types" msgstr "انواع داده‌ها جنریک (Generic Data Types)" -#: src/SUMMARY.md:132 src/generics/methods.md:1 +#: src/SUMMARY.md:138 src/generics/methods.md:1 msgid "Generic Methods" msgstr "متدهای جنریک" -#: src/SUMMARY.md:133 src/generics/monomorphization.md:1 +#: src/SUMMARY.md:139 src/generics/monomorphization.md:1 msgid "Monomorphization" msgstr "تک شکلی" -#: src/SUMMARY.md:134 src/traits.md:1 +#: src/SUMMARY.md:140 src/traits.md:1 msgid "Traits" msgstr "صفت‌ها" -#: src/SUMMARY.md:135 src/traits/trait-objects.md:1 +#: src/SUMMARY.md:141 src/traits/trait-objects.md:1 msgid "Trait Objects" msgstr "آبجکت‌های موصوفی (Trait Objects)" -#: src/SUMMARY.md:136 src/traits/deriving-traits.md:1 +#: src/SUMMARY.md:142 src/traits/deriving-traits.md:1 msgid "Deriving Traits" msgstr "صفات استنتاجی (Deriving Traits)" -#: src/SUMMARY.md:137 src/traits/default-methods.md:1 +#: src/SUMMARY.md:143 src/traits/default-methods.md:1 msgid "Default Methods" msgstr "متدهای پیشفرض" -#: src/SUMMARY.md:138 src/traits/trait-bounds.md:1 +#: src/SUMMARY.md:144 src/traits/trait-bounds.md:1 msgid "Trait Bounds" msgstr "صفات مرزی (Trait Bounds)" -#: src/SUMMARY.md:139 +#: src/SUMMARY.md:145 msgid "impl Trait" msgstr "صفات impl (impl Trait)" -#: src/SUMMARY.md:140 src/traits/important-traits.md:1 +#: src/SUMMARY.md:146 src/traits/important-traits.md:1 msgid "Important Traits" msgstr "صفات مهم" -#: src/SUMMARY.md:141 +#: src/SUMMARY.md:147 msgid "Iterator" msgstr "تکرار کننده" -#: src/SUMMARY.md:142 src/traits/from-iterator.md:1 +#: src/SUMMARY.md:148 src/traits/from-iterator.md:1 msgid "FromIterator" msgstr "FromIterator" -#: src/SUMMARY.md:143 +#: src/SUMMARY.md:149 msgid "From and Into" msgstr "From و Into" -#: src/SUMMARY.md:144 +#: src/SUMMARY.md:150 msgid "Read and Write" msgstr "Read and Write" -#: src/SUMMARY.md:145 +#: src/SUMMARY.md:151 msgid "Drop" msgstr "رها کردن" -#: src/SUMMARY.md:146 +#: src/SUMMARY.md:152 msgid "Default" msgstr "پیش‌فرض" -#: src/SUMMARY.md:147 +#: src/SUMMARY.md:153 msgid "Operators: Add, Mul, ..." msgstr "عملگر‌های: جمع و ضرب, ..." -#: src/SUMMARY.md:148 +#: src/SUMMARY.md:154 msgid "Closures: Fn, FnMut, FnOnce" msgstr "بسته شدن‌ها: Fn, FnMut, FnOnce" -#: src/SUMMARY.md:150 src/exercises/day-3/simple-gui.md:1 -#: src/exercises/day-3/solutions-morning.md:3 +#: src/SUMMARY.md:156 msgid "A Simple GUI Library" msgstr "یک کتابخانه GUI ساده" -#: src/SUMMARY.md:152 +#: src/SUMMARY.md:157 src/exercises/day-3/solutions-morning.md:142 +msgid "Points and Polygons" +msgstr "نقطه‌ها و چند ضلعی‌ها" + +#: src/SUMMARY.md:159 msgid "Day 3: Afternoon" msgstr "روز سوم: عصر" -#: src/SUMMARY.md:154 src/error-handling.md:1 +#: src/SUMMARY.md:161 src/error-handling.md:1 msgid "Error Handling" msgstr "مدیریت خطا (Error Handling)" -#: src/SUMMARY.md:155 src/error-handling/panics.md:1 +#: src/SUMMARY.md:162 src/error-handling/panics.md:1 msgid "Panics" -msgstr "Panics" +msgstr "پانیک‌ها" -#: src/SUMMARY.md:156 +#: src/SUMMARY.md:163 msgid "Catching Stack Unwinding" msgstr "گرفتن Stack در حال بازگشایی" -#: src/SUMMARY.md:157 +#: src/SUMMARY.md:164 msgid "Structured Error Handling" msgstr "مدیریت خطای ساختاری" -#: src/SUMMARY.md:158 +#: src/SUMMARY.md:165 msgid "Propagating Errors with ?" msgstr "انتشار خطاها با استفاده از عملگر ؟" -#: src/SUMMARY.md:159 src/error-handling/converting-error-types.md:1 +#: src/SUMMARY.md:166 src/error-handling/converting-error-types.md:1 #: src/error-handling/converting-error-types-example.md:1 msgid "Converting Error Types" msgstr "تبدیل انواع خطا" -#: src/SUMMARY.md:161 src/error-handling/deriving-error-enums.md:1 +#: src/SUMMARY.md:168 src/error-handling/deriving-error-enums.md:1 msgid "Deriving Error Enums" -msgstr "استخراج شماره های خطا" +msgstr "استخراج شماره‌های خطا" -#: src/SUMMARY.md:162 src/error-handling/dynamic-errors.md:1 +#: src/SUMMARY.md:169 src/error-handling/dynamic-errors.md:1 msgid "Dynamic Error Types" msgstr "انواع خطاهای Dynamic" -#: src/SUMMARY.md:163 src/error-handling/error-contexts.md:1 +#: src/SUMMARY.md:170 src/error-handling/error-contexts.md:1 msgid "Adding Context to Errors" msgstr "اضافه کردن زمینه (Context) به خطاها" -#: src/SUMMARY.md:164 src/testing.md:1 +#: src/SUMMARY.md:171 src/testing.md:1 msgid "Testing" msgstr "تست‌کردن" -#: src/SUMMARY.md:165 src/testing/unit-tests.md:1 +#: src/SUMMARY.md:172 src/testing/unit-tests.md:1 msgid "Unit Tests" msgstr "تست‌های واحد (Unit Tests)" -#: src/SUMMARY.md:166 src/testing/test-modules.md:1 +#: src/SUMMARY.md:173 src/testing/test-modules.md:1 msgid "Test Modules" msgstr "تست‌ ماژول‌ها" -#: src/SUMMARY.md:167 src/testing/doc-tests.md:1 +#: src/SUMMARY.md:174 src/testing/doc-tests.md:1 msgid "Documentation Tests" msgstr "تست‌ سندها" -#: src/SUMMARY.md:168 src/testing/integration-tests.md:1 +#: src/SUMMARY.md:175 src/testing/integration-tests.md:1 msgid "Integration Tests" msgstr "Integration Tests" -#: src/SUMMARY.md:169 src/bare-metal/useful-crates.md:1 +#: src/SUMMARY.md:176 src/bare-metal/useful-crates.md:1 #, fuzzy msgid "Useful crates" -msgstr "جعبه های (crates) کاربردی" +msgstr "جعبه‌های (crates) کاربردی" -#: src/SUMMARY.md:170 src/unsafe.md:1 +#: src/SUMMARY.md:177 src/unsafe.md:1 msgid "Unsafe Rust" -msgstr "Unsafe Rust" +msgstr "Rust ناایمن" -#: src/SUMMARY.md:171 src/unsafe/raw-pointers.md:1 +#: src/SUMMARY.md:178 src/unsafe/raw-pointers.md:1 msgid "Dereferencing Raw Pointers" msgstr "عدم ارجاع به اشاره گرهای خام" -#: src/SUMMARY.md:172 src/unsafe/mutable-static-variables.md:1 +#: src/SUMMARY.md:179 src/unsafe/mutable-static-variables.md:1 msgid "Mutable Static Variables" msgstr "متغیرهای ثابت قابل تغییر" -#: src/SUMMARY.md:173 src/unsafe/unions.md:1 +#: src/SUMMARY.md:180 src/unsafe/unions.md:1 msgid "Unions" -msgstr "Unions" +msgstr "نوع داده چندگانه" -#: src/SUMMARY.md:174 src/unsafe/calling-unsafe-functions.md:1 +#: src/SUMMARY.md:181 src/unsafe/calling-unsafe-functions.md:1 msgid "Calling Unsafe Functions" msgstr "فراخوانی متدهای ناامن" -#: src/SUMMARY.md:175 src/unsafe/writing-unsafe-functions.md:1 +#: src/SUMMARY.md:182 src/unsafe/writing-unsafe-functions.md:1 msgid "Writing Unsafe Functions" msgstr "نوشتن متدهای ناامن" -#: src/SUMMARY.md:176 +#: src/SUMMARY.md:183 msgid "Extern Functions" msgstr "توابع خارجی (Extern Functions)" -#: src/SUMMARY.md:177 src/unsafe/unsafe-traits.md:1 +#: src/SUMMARY.md:184 src/unsafe/unsafe-traits.md:1 msgid "Implementing Unsafe Traits" msgstr "پیاده سازی صفات (Traits) ناامن" -#: src/SUMMARY.md:179 src/exercises/day-3/safe-ffi-wrapper.md:1 +#: src/SUMMARY.md:186 src/exercises/day-3/safe-ffi-wrapper.md:1 #: src/exercises/day-3/solutions-afternoon.md:3 msgid "Safe FFI Wrapper" msgstr "امن بودن FFI Wrapper" -#: src/SUMMARY.md:182 src/SUMMARY.md:252 -#: src/running-the-course/course-structure.md:16 src/bare-metal/android.md:1 +#: src/SUMMARY.md:189 src/SUMMARY.md:259 src/bare-metal/android.md:1 msgid "Android" -msgstr "Android" +msgstr "اندروید" -#: src/SUMMARY.md:187 src/android/setup.md:1 +#: src/SUMMARY.md:194 src/android/setup.md:1 msgid "Setup" msgstr "تنظیم" -#: src/SUMMARY.md:188 src/android/build-rules.md:1 +#: src/SUMMARY.md:195 src/android/build-rules.md:1 msgid "Build Rules" msgstr "قوانین ساخت" -#: src/SUMMARY.md:189 +#: src/SUMMARY.md:196 msgid "Binary" msgstr "باینری" -#: src/SUMMARY.md:190 +#: src/SUMMARY.md:197 msgid "Library" msgstr "کتابخانه" -#: src/SUMMARY.md:191 src/android/aidl.md:1 +#: src/SUMMARY.md:198 src/android/aidl.md:1 msgid "AIDL" msgstr "AIDL" -#: src/SUMMARY.md:192 +#: src/SUMMARY.md:199 msgid "Interface" msgstr "رابط (Interface)" -#: src/SUMMARY.md:193 +#: src/SUMMARY.md:200 msgid "Implementation" msgstr "پیاده سازی" -#: src/SUMMARY.md:194 +#: src/SUMMARY.md:201 msgid "Server" msgstr "سرور" -#: src/SUMMARY.md:195 src/android/aidl/deploy.md:1 +#: src/SUMMARY.md:202 src/android/aidl/deploy.md:1 msgid "Deploy" msgstr "دیپلوی" -#: src/SUMMARY.md:196 +#: src/SUMMARY.md:203 msgid "Client" msgstr "کاربر" -#: src/SUMMARY.md:197 src/android/aidl/changing.md:1 +#: src/SUMMARY.md:204 src/android/aidl/changing.md:1 msgid "Changing API" msgstr "تغییر دادن API" -#: src/SUMMARY.md:198 src/SUMMARY.md:242 src/android/logging.md:1 +#: src/SUMMARY.md:205 src/SUMMARY.md:249 src/android/logging.md:1 #: src/bare-metal/aps/logging.md:1 msgid "Logging" msgstr "لاگ" -#: src/SUMMARY.md:199 src/android/interoperability.md:1 +#: src/SUMMARY.md:206 src/android/interoperability.md:1 msgid "Interoperability" msgstr "قابلیت همکاری" -#: src/SUMMARY.md:200 +#: src/SUMMARY.md:207 msgid "With C" msgstr "با C" -#: src/SUMMARY.md:201 +#: src/SUMMARY.md:208 msgid "Calling C with Bindgen" msgstr "فراخوانی C با Bindgen" -#: src/SUMMARY.md:202 +#: src/SUMMARY.md:209 msgid "Calling Rust from C" msgstr "فراخوانی Rust از C" -#: src/SUMMARY.md:203 src/android/interoperability/cpp.md:1 +#: src/SUMMARY.md:210 src/android/interoperability/cpp.md:1 msgid "With C++" msgstr "با ++C" -#: src/SUMMARY.md:204 +#: src/SUMMARY.md:211 msgid "With Java" msgstr "با جاوا" -#: src/SUMMARY.md:208 +#: src/SUMMARY.md:215 msgid "Bare Metal: Morning" msgstr "با Bare Metal: صبح" -#: src/SUMMARY.md:213 +#: src/SUMMARY.md:220 msgid "no_std" msgstr "no_std" -#: src/SUMMARY.md:214 +#: src/SUMMARY.md:221 msgid "A Minimal Example" msgstr "یک مثال ساده" -#: src/SUMMARY.md:215 +#: src/SUMMARY.md:222 msgid "alloc" msgstr "alloc" -#: src/SUMMARY.md:216 src/bare-metal/microcontrollers.md:1 +#: src/SUMMARY.md:223 src/bare-metal/microcontrollers.md:1 msgid "Microcontrollers" msgstr "میکروکنترلرها" -#: src/SUMMARY.md:217 src/bare-metal/microcontrollers/mmio.md:1 +#: src/SUMMARY.md:224 src/bare-metal/microcontrollers/mmio.md:1 msgid "Raw MMIO" msgstr "Raw MMIO" -#: src/SUMMARY.md:218 +#: src/SUMMARY.md:225 msgid "PACs" msgstr "PACs" -#: src/SUMMARY.md:219 +#: src/SUMMARY.md:226 msgid "HAL Crates" msgstr "HAL Crates" -#: src/SUMMARY.md:220 +#: src/SUMMARY.md:227 msgid "Board Support Crates" msgstr "Board Support Crates" -#: src/SUMMARY.md:221 +#: src/SUMMARY.md:228 msgid "The Type State Pattern" msgstr "انواع State Pattern" -#: src/SUMMARY.md:222 +#: src/SUMMARY.md:229 msgid "embedded-hal" msgstr "embedded-hal" -#: src/SUMMARY.md:223 +#: src/SUMMARY.md:230 msgid "probe-rs, cargo-embed" msgstr "probe-rs, cargo-embed" -#: src/SUMMARY.md:224 src/bare-metal/microcontrollers/debugging.md:1 +#: src/SUMMARY.md:231 src/bare-metal/microcontrollers/debugging.md:1 msgid "Debugging" msgstr "اشکال یابی (Debugging)" -#: src/SUMMARY.md:225 src/SUMMARY.md:245 +#: src/SUMMARY.md:232 src/SUMMARY.md:252 msgid "Other Projects" msgstr "باقی پروژه‌ها" -#: src/SUMMARY.md:227 src/exercises/bare-metal/compass.md:1 +#: src/SUMMARY.md:234 src/exercises/bare-metal/compass.md:1 #: src/exercises/bare-metal/solutions-morning.md:3 msgid "Compass" msgstr "قطب‌نما" -#: src/SUMMARY.md:229 +#: src/SUMMARY.md:236 msgid "Bare Metal: Afternoon" msgstr "با Bare Metal: عصر" -#: src/SUMMARY.md:231 +#: src/SUMMARY.md:238 msgid "Application Processors" -msgstr "پردازنده های برنامه" +msgstr "پردازنده‌های برنامه" -#: src/SUMMARY.md:232 src/bare-metal/aps/entry-point.md:1 +#: src/SUMMARY.md:239 src/bare-metal/aps/entry-point.md:1 msgid "Getting Ready to Rust" msgstr "آماده شدن برای Rust" -#: src/SUMMARY.md:233 +#: src/SUMMARY.md:240 msgid "Inline Assembly" msgstr "اسمبلی درونی" -#: src/SUMMARY.md:234 +#: src/SUMMARY.md:241 msgid "MMIO" msgstr "MMIO" -#: src/SUMMARY.md:235 +#: src/SUMMARY.md:242 msgid "Let's Write a UART Driver" msgstr "بریم یک درایور UART بنویسیم" -#: src/SUMMARY.md:236 +#: src/SUMMARY.md:243 msgid "More Traits" msgstr "صفت‌های بیشتر" -#: src/SUMMARY.md:237 +#: src/SUMMARY.md:244 msgid "A Better UART Driver" msgstr "یک درایور بهتر UART" -#: src/SUMMARY.md:238 src/bare-metal/aps/better-uart/bitflags.md:1 +#: src/SUMMARY.md:245 src/bare-metal/aps/better-uart/bitflags.md:1 msgid "Bitflags" -msgstr "پرچم های بیتی (Bitflags)" +msgstr "پرچم‌های بیتی (Bitflags)" -#: src/SUMMARY.md:239 +#: src/SUMMARY.md:246 msgid "Multiple Registers" msgstr "رجیستر‌های چندگانه" -#: src/SUMMARY.md:240 src/bare-metal/aps/better-uart/driver.md:1 +#: src/SUMMARY.md:247 src/bare-metal/aps/better-uart/driver.md:1 msgid "Driver" msgstr "درایور" -#: src/SUMMARY.md:241 src/SUMMARY.md:243 +#: src/SUMMARY.md:248 src/SUMMARY.md:250 msgid "Using It" msgstr "استفاده از آن" -#: src/SUMMARY.md:244 src/bare-metal/aps/exceptions.md:1 +#: src/SUMMARY.md:251 src/bare-metal/aps/exceptions.md:1 msgid "Exceptions" msgstr "استثناها" -#: src/SUMMARY.md:246 +#: src/SUMMARY.md:253 #, fuzzy msgid "Useful Crates" -msgstr "جعبه های (Crates) کاربردی" +msgstr "جعبه‌های (Crates) کاربردی" -#: src/SUMMARY.md:247 +#: src/SUMMARY.md:254 msgid "zerocopy" msgstr "صفر کپی (zerocopy)" -#: src/SUMMARY.md:248 +#: src/SUMMARY.md:255 msgid "aarch64-paging" msgstr "aarch64-paging" -#: src/SUMMARY.md:249 +#: src/SUMMARY.md:256 msgid "buddy_system_allocator" msgstr "buddy_system_allocator" -#: src/SUMMARY.md:250 +#: src/SUMMARY.md:257 msgid "tinyvec" msgstr "tinyvec" -#: src/SUMMARY.md:251 +#: src/SUMMARY.md:258 msgid "spin" msgstr "چرخش" -#: src/SUMMARY.md:253 src/bare-metal/android/vmbase.md:1 +#: src/SUMMARY.md:260 src/bare-metal/android/vmbase.md:1 msgid "vmbase" msgstr "vmbase" -#: src/SUMMARY.md:255 +#: src/SUMMARY.md:262 msgid "RTC Driver" msgstr "درایور RTC" -#: src/SUMMARY.md:258 +#: src/SUMMARY.md:265 msgid "Concurrency: Morning" msgstr "همزمانی: صبح" -#: src/SUMMARY.md:263 src/concurrency/threads.md:1 +#: src/SUMMARY.md:270 src/concurrency/threads.md:1 msgid "Threads" msgstr "تردها" -#: src/SUMMARY.md:264 src/concurrency/scoped-threads.md:1 +#: src/SUMMARY.md:271 src/concurrency/scoped-threads.md:1 msgid "Scoped Threads" msgstr "محدوده تردها" -#: src/SUMMARY.md:265 src/concurrency/channels.md:1 +#: src/SUMMARY.md:272 src/concurrency/channels.md:1 msgid "Channels" msgstr "کانال‌ها" -#: src/SUMMARY.md:266 src/concurrency/channels/unbounded.md:1 +#: src/SUMMARY.md:273 src/concurrency/channels/unbounded.md:1 msgid "Unbounded Channels" msgstr "کانال‌های نامحدود" -#: src/SUMMARY.md:267 src/concurrency/channels/bounded.md:1 +#: src/SUMMARY.md:274 src/concurrency/channels/bounded.md:1 msgid "Bounded Channels" -msgstr "کانال های محدود" +msgstr "کانال‌های محدود" -#: src/SUMMARY.md:268 +#: src/SUMMARY.md:275 msgid "Send and Sync" msgstr "ارسال و همگام سازی" -#: src/SUMMARY.md:268 +#: src/SUMMARY.md:275 msgid "Send" msgstr "ارسال" -#: src/SUMMARY.md:268 +#: src/SUMMARY.md:275 msgid "Sync" msgstr "همگام سازی" -#: src/SUMMARY.md:271 src/concurrency/send-sync/examples.md:1 +#: src/SUMMARY.md:278 src/concurrency/send-sync/examples.md:1 msgid "Examples" msgstr "مثال‌ها" -#: src/SUMMARY.md:272 src/concurrency/shared_state.md:1 +#: src/SUMMARY.md:279 src/concurrency/shared_state.md:1 msgid "Shared State" msgstr "ناحیه‌های مشترک" -#: src/SUMMARY.md:273 +#: src/SUMMARY.md:280 msgid "Arc" msgstr "Shared State" -#: src/SUMMARY.md:274 +#: src/SUMMARY.md:281 msgid "Mutex" msgstr "Mutex" -#: src/SUMMARY.md:277 src/SUMMARY.md:298 +#: src/SUMMARY.md:284 src/SUMMARY.md:305 #: src/exercises/concurrency/dining-philosophers.md:1 #: src/exercises/concurrency/solutions-morning.md:3 msgid "Dining Philosophers" msgstr "فلسفه Dining" -#: src/SUMMARY.md:278 src/exercises/concurrency/link-checker.md:1 +#: src/SUMMARY.md:285 src/exercises/concurrency/link-checker.md:1 msgid "Multi-threaded Link Checker" msgstr "جستجوگر پیوند چند تِردی" -#: src/SUMMARY.md:280 +#: src/SUMMARY.md:287 msgid "Concurrency: Afternoon" msgstr "همزمانی: عصر" -#: src/SUMMARY.md:282 +#: src/SUMMARY.md:289 msgid "Async Basics" msgstr "مبانی Async" -#: src/SUMMARY.md:283 +#: src/SUMMARY.md:290 msgid "async/await" msgstr "async/await" -#: src/SUMMARY.md:284 src/async/futures.md:1 +#: src/SUMMARY.md:291 src/async/futures.md:1 msgid "Futures" msgstr "Futures" -#: src/SUMMARY.md:285 src/async/runtimes.md:1 +#: src/SUMMARY.md:292 src/async/runtimes.md:1 msgid "Runtimes" msgstr "Runtimes" -#: src/SUMMARY.md:286 src/async/runtimes/tokio.md:1 +#: src/SUMMARY.md:293 src/async/runtimes/tokio.md:1 msgid "Tokio" msgstr "Tokio" -#: src/SUMMARY.md:287 src/exercises/concurrency/link-checker.md:126 -#: src/exercises/concurrency/chat-app.md:140 src/async/tasks.md:1 +#: src/SUMMARY.md:294 src/exercises/concurrency/link-checker.md:126 +#: src/async/tasks.md:1 src/exercises/concurrency/chat-app.md:143 msgid "Tasks" msgstr "Task" -#: src/SUMMARY.md:288 src/async/channels.md:1 +#: src/SUMMARY.md:295 src/async/channels.md:1 msgid "Async Channels" msgstr "کانال‌های Async" -#: src/SUMMARY.md:290 src/async/control-flow/join.md:1 +#: src/SUMMARY.md:297 src/async/control-flow/join.md:1 msgid "Join" msgstr "Join" -#: src/SUMMARY.md:291 src/async/control-flow/select.md:1 +#: src/SUMMARY.md:298 src/async/control-flow/select.md:1 msgid "Select" msgstr "Select" -#: src/SUMMARY.md:292 +#: src/SUMMARY.md:299 msgid "Pitfalls" msgstr "مشکل‌ها" -#: src/SUMMARY.md:293 +#: src/SUMMARY.md:300 msgid "Blocking the Executor" msgstr "مسدود کردن Executor" -#: src/SUMMARY.md:294 src/async/pitfalls/pin.md:1 +#: src/SUMMARY.md:301 src/async/pitfalls/pin.md:1 msgid "Pin" msgstr "Pin" -#: src/SUMMARY.md:295 src/async/pitfalls/async-traits.md:1 +#: src/SUMMARY.md:302 src/async/pitfalls/async-traits.md:1 msgid "Async Traits" msgstr "صفات Async" -#: src/SUMMARY.md:296 src/async/pitfalls/cancellation.md:1 +#: src/SUMMARY.md:303 src/async/pitfalls/cancellation.md:1 msgid "Cancellation" msgstr "لغو" -#: src/SUMMARY.md:299 src/exercises/concurrency/chat-app.md:1 -#: src/exercises/concurrency/solutions-afternoon.md:119 +#: src/SUMMARY.md:306 src/exercises/concurrency/chat-app.md:1 +#: src/exercises/concurrency/solutions-afternoon.md:95 msgid "Broadcast Chat Application" msgstr "پخش برنامه چت" -#: src/SUMMARY.md:302 +#: src/SUMMARY.md:309 msgid "Final Words" msgstr "کلمات آخر" -#: src/SUMMARY.md:306 src/thanks.md:1 +#: src/SUMMARY.md:313 src/thanks.md:1 msgid "Thanks!" msgstr "سپاس!" -#: src/SUMMARY.md:307 +#: src/SUMMARY.md:314 src/glossary.md:1 +msgid "Glossary" +msgstr "واژه نامه" + +#: src/SUMMARY.md:315 msgid "Other Resources" msgstr "منابع دیگر" -#: src/SUMMARY.md:308 src/credits.md:1 +#: src/SUMMARY.md:316 src/credits.md:1 msgid "Credits" msgstr "اعتبارها" -#: src/SUMMARY.md:311 src/exercises/solutions.md:1 +#: src/SUMMARY.md:319 src/exercises/solutions.md:1 msgid "Solutions" msgstr "راه حل‌ها" -#: src/SUMMARY.md:316 +#: src/SUMMARY.md:324 msgid "Day 1 Morning" msgstr "روز ۱ صبح" -#: src/SUMMARY.md:317 +#: src/SUMMARY.md:325 msgid "Day 1 Afternoon" msgstr "روز ۱ عصر" -#: src/SUMMARY.md:318 +#: src/SUMMARY.md:326 msgid "Day 2 Morning" msgstr "روز ۲ صبح" -#: src/SUMMARY.md:319 +#: src/SUMMARY.md:327 msgid "Day 2 Afternoon" msgstr "روز ۲ عصر" -#: src/SUMMARY.md:320 +#: src/SUMMARY.md:328 msgid "Day 3 Morning" msgstr "روز ۳ صبح" -#: src/SUMMARY.md:321 +#: src/SUMMARY.md:329 msgid "Day 3 Afternoon" msgstr "روز ۳ عصر" -#: src/SUMMARY.md:322 +#: src/SUMMARY.md:330 msgid "Bare Metal Rust Morning" msgstr "صبح‌گاه با Bare Metal Rust" -#: src/SUMMARY.md:323 src/exercises/bare-metal/solutions-afternoon.md:1 +#: src/SUMMARY.md:331 src/exercises/bare-metal/solutions-afternoon.md:1 msgid "Bare Metal Rust Afternoon" msgstr "عصرانه با Bare Metal Rust" -#: src/SUMMARY.md:324 +#: src/SUMMARY.md:332 msgid "Concurrency Morning" msgstr "صبح‌گاه با همزمانی (Concurrency)" -#: src/SUMMARY.md:325 +#: src/SUMMARY.md:333 msgid "Concurrency Afternoon" msgstr "همزمانی: عصر" #: src/index.md:3 -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)" -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)" - -#: src/index.md:3 -msgid "Build workflow" -msgstr "ساخت workflow" - -#: src/index.md:3 +#, fuzzy 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)" -msgstr "" - -#: src/index.md:4 -msgid "GitHub contributors" -msgstr "مشارکت کنندگان GitHub" - -#: src/index.md:4 -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)" @@ -1065,20 +1054,6 @@ msgstr "" "io/github/stars/google/comprehensive-rust?style=flat-square)](https://github." "com/google/comprehensive-rust/stargazers)" -#: src/index.md:5 -msgid "GitHub stars" -msgstr "ستاره های GitHub" - -#: src/index.md:5 -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)" - #: src/index.md:7 msgid "" "This is a free Rust course developed by the Android team at Google. The " @@ -1091,37 +1066,44 @@ msgstr "" #: src/index.md:11 msgid "" +"The latest version of the course can be found at . If you are reading somewhere else, please check there " +"for updates." +msgstr "" + +#: src/index.md:15 +msgid "" "The goal of the course is to teach you Rust. We assume you don't know " "anything about Rust and hope to:" msgstr "" "هدف از این دوره آموزش Rust به شماست. ما فرض می کنیم شما چیزی از درباره Rust " "نمی دانید امید به یادگیری:" -#: src/index.md:14 +#: src/index.md:18 msgid "Give you a comprehensive understanding of the Rust syntax and language." msgstr "درک جامعی از syntax و زبان Rust به شما می دهد." -#: src/index.md:15 +#: src/index.md:19 msgid "Enable you to modify existing programs and write new programs in Rust." msgstr "" "شما را قادر می سازد تا برنامه های موجود را تغییر دهید و برنامه های جدید را " "در Rust بنویسید." -#: src/index.md:16 +#: src/index.md:20 msgid "Show you common Rust idioms." msgstr "اصطلاحات رایج Rust را به شما نشان می دهد." -#: src/index.md:18 +#: src/index.md:22 msgid "We call the first three course days Rust Fundamentals." msgstr "ما سه روز اول دوره را Rust Fundamentals می نامیم." -#: src/index.md:20 +#: src/index.md:24 msgid "" "Building on this, you're invited to dive into one or more specialized topics:" msgstr "" "با تکیه بر این، از شما دعوت می شود تا به یک یا چند موضوع تخصصی بپردازید:" -#: src/index.md:22 +#: src/index.md:26 #, fuzzy msgid "" "[Android](android.md): a half-day course on using Rust for Android platform " @@ -1136,14 +1118,14 @@ msgstr "" "استفاده از نخ ها و موتکس) و همزمانی async/wait (همکاری چندوظیفه ای با " "استفاده از حالت futures)." -#: src/index.md:24 +#: src/index.md:28 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/index.md:27 +#: src/index.md:31 msgid "" "[Concurrency](concurrency.md): a whole-day class on concurrency in Rust. We " "cover both classical concurrency (preemptively scheduling using threads and " @@ -1151,11 +1133,11 @@ msgid "" "futures)." msgstr "" -#: src/index.md:33 +#: src/index.md:37 msgid "Non-Goals" msgstr "موارد غیر اهداف آموزشی" -#: src/index.md:35 +#: src/index.md:39 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:" @@ -1163,7 +1145,7 @@ msgstr "" "Rust زبان بزرگی است و تا چند روز دیگر نمی‌توانیم همه آن را پوشش دهیم. برخی از " "اهداف غیر از این دوره عبارتند از:" -#: src/index.md:38 +#: src/index.md:42 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]" @@ -1173,11 +1155,11 @@ msgstr "" "(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/index.md:42 +#: src/index.md:46 msgid "Assumptions" msgstr "فرضیه ها" -#: src/index.md:44 +#: src/index.md:48 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 " @@ -1188,7 +1170,7 @@ msgstr "" "و ما گاهی اوقات زبان Rust را با C و C++ مقایسه می کنیم تا رویکرد‌های Rust را " "بهتر توضیح دهیم یا در در حالت مقایسه با آن قرار دهیم." -#: src/index.md:48 +#: src/index.md:52 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." @@ -1196,7 +1178,7 @@ msgstr "" "اگر می‌دانید چگونه به زبانی با دینامیک تایپ مانند پایتون یا جاوا اسکریپت " "برنامه‌نویسی کنید می‌توانید به خوبی این روش را دنبال کنید." -#: src/index.md:53 +#: src/index.md:57 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 " @@ -1214,10 +1196,20 @@ msgid "" msgstr "" #: src/running-the-course.md:8 +msgid "" +"We typically run classes from 10:00 am to 4:00 pm, with a 1 hour lunch break " +"in the middle. This leaves 2.5 hours for the morning class and 2.5 hours for " +"the afternoon class. Note that this is just a recommendation: you can also " +"spend 3 hour on the morning session to give people more time for exercises. " +"The downside of longer session is that people can become very tired after 6 " +"full hours of class in the afternoon." +msgstr "" + +#: src/running-the-course.md:16 msgid "Before you run the course, you will want to:" msgstr "قبل از اجرای دوره، شما می خواهید:" -#: src/running-the-course.md:10 +#: src/running-the-course.md:18 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 " @@ -1226,7 +1218,7 @@ msgid "" "Notes\"). This way you have a clean screen to present to the class." msgstr "" -#: src/running-the-course.md:16 +#: src/running-the-course.md:24 msgid "" "Decide on the dates. Since the course takes at least three full days, we " "recommend that you schedule the days over two weeks. Course participants " @@ -1234,7 +1226,7 @@ msgid "" "helps them process all the information we give them." msgstr "" -#: src/running-the-course.md:21 +#: src/running-the-course.md:29 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 " @@ -1245,7 +1237,7 @@ msgid "" "instructor, so a lectern won't be very helpful for you." msgstr "" -#: src/running-the-course.md:29 +#: src/running-the-course.md:37 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 " @@ -1255,7 +1247,7 @@ msgid "" "you or the course participants spot them." msgstr "" -#: src/running-the-course.md:35 +#: src/running-the-course.md:43 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 " @@ -1266,13 +1258,13 @@ msgid "" "information in the standard library." msgstr "" -#: src/running-the-course.md:43 +#: src/running-the-course.md:51 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:46 +#: src/running-the-course.md:54 msgid "" "Please [provide feedback](https://github.com/google/comprehensive-rust/" "discussions/86) afterwards so that we can keep improving the course. We " @@ -1287,26 +1279,34 @@ msgstr "" "github.com/google/comprehensive-rust/discussions/100)!" #: src/running-the-course/course-structure.md:5 -msgid "The course is fast paced and covers a lot of ground:" -msgstr "یاد گیری این دوره کوتاه است و مبحث‌های زیادی را پوشش می دهد:" - -#: src/running-the-course/course-structure.md:7 -msgid "Day 1: Basic Rust, ownership and the borrow checker." -msgstr "روز 1: زنگ اولیه، مالکیت و چک کننده قرض." - -#: src/running-the-course/course-structure.md:8 -msgid "Day 2: Compound data types, pattern matching, the standard library." +msgid "Rust Fundamentals" msgstr "" -#: src/running-the-course/course-structure.md:9 -msgid "Day 3: Traits and generics, error handling, testing, unsafe Rust." +#: src/running-the-course/course-structure.md:7 +msgid "" +"The first three days make up [Rust Fundaments](../welcome-day-1.md). The " +"days are fast paced and we cover a lot of ground:" +msgstr "" + +#: src/running-the-course/course-structure.md:10 +msgid "Day 1: Basic Rust, syntax, control flow, creating and consuming values." msgstr "" #: src/running-the-course/course-structure.md:11 +msgid "" +"Day 2: Memory management, ownership, compound data types, and the standard " +"library." +msgstr "" + +#: src/running-the-course/course-structure.md:12 +msgid "Day 3: Generics, traits, error handling, testing, and unsafe Rust." +msgstr "" + +#: src/running-the-course/course-structure.md:14 msgid "Deep Dives" msgstr "شیرجه در اعماق" -#: src/running-the-course/course-structure.md:13 +#: src/running-the-course/course-structure.md:16 msgid "" "In addition to the 3-day class on Rust Fundamentals, we cover some more " "specialized topics:" @@ -1314,17 +1314,23 @@ msgstr "" "علاوه بر کلاس 3 روزه Rust Fundamentals، موضوعات تخصصی تری را نیز پوشش می " "دهیم:" -#: src/running-the-course/course-structure.md:18 +#: src/running-the-course/course-structure.md:19 +#, fuzzy +msgid "Rust in Android" +msgstr "Android" + +#: src/running-the-course/course-structure.md:21 +#, fuzzy msgid "" -"The [Android Deep Dive](../android.md) is a half-day course on using Rust " -"for Android platform development. This includes interoperability with C, C+" -"+, and Java." +"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 "" "در [Android Deep Dive](../android.md) یک دوره نیم روزه در مورد استفاده از " "Rust برای توسعه پلتفرم اندروید است. این شامل قابلیت تعامل با C، C++ و جاوا " "می شود." -#: src/running-the-course/course-structure.md:22 +#: src/running-the-course/course-structure.md:25 #, fuzzy msgid "" "You will need an [AOSP checkout](https://source.android.com/docs/setup/" @@ -1340,7 +1346,7 @@ msgstr "" "حاصل می کند که سیستم ساخت اندروید فایل های «Android.bp» را در «src/android/» " "می بیند." -#: src/running-the-course/course-structure.md:27 +#: src/running-the-course/course-structure.md:30 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 " @@ -1351,21 +1357,23 @@ msgstr "" "بسازید. اسکریپت را بخوانید تا دستوراتی را که اجرا می‌کند ببینید و مطمئن شوید " "که وقتی آنها را اجرا می‌کنید به درستی کار می‌کنند." -#: src/running-the-course/course-structure.md:34 -msgid "Bare-Metal" +#: src/running-the-course/course-structure.md:37 +#, fuzzy +msgid "Bare-Metal Rust" msgstr "Bare-Metal" -#: src/running-the-course/course-structure.md:36 +#: src/running-the-course/course-structure.md:39 +#, fuzzy msgid "" -"The [Bare-Metal Deep Dive](../bare-metal.md): a full day class on using Rust " -"for bare-metal (embedded) development. Both microcontrollers and application " -"processors are covered." +"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 "" "در [Bare-Metal Deep Dive](../bare-metal.md): یک کلاس یک روزه کامل در مورد " "استفاده از Rust برای توسعه bare-metal (embedded) هم میکروکنترلرها و هم " "پردازنده های برنامه پوشش داده شده اند." -#: src/running-the-course/course-structure.md:40 +#: src/running-the-course/course-structure.md:43 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 " @@ -1376,19 +1384,21 @@ msgstr "" "v2 را خریداری کنید. همه باید تعدادی بسته را همانطور که در \\[welcome " "page\\] (../bare-metal.md) توضیح داده شده نصب کنند." -#: src/running-the-course/course-structure.md:45 -msgid "Concurrency" -msgstr "همزمانی" +#: src/running-the-course/course-structure.md:48 +#, fuzzy +msgid "Concurrency in Rust" +msgstr "صبح‌گاه با همزمانی (Concurrency)" -#: src/running-the-course/course-structure.md:47 +#: src/running-the-course/course-structure.md:50 +#, fuzzy msgid "" -"The [Concurrency Deep Dive](../concurrency.md) is a full day class on " -"classical as well as `async`/`await` concurrency." +"The [Concurrency in Rust](../concurrency.md) deep dive is a full day class " +"on classical as well as `async`/`await` concurrency." msgstr "" "این \\[Concurrency Deep Dive\\] (../concurrency.md) به اصطلاح یک کلاس یک " "روزه است و همچنین همزمانی `async`/`await` اینگونه است." -#: src/running-the-course/course-structure.md:50 +#: src/running-the-course/course-structure.md:53 #, fuzzy msgid "" "You will need a fresh crate set up and the dependencies downloaded and ready " @@ -1399,27 +1409,11 @@ msgstr "" "هستند نیاز دارید. سپس می‌توانید مثال‌ها را در «src/main.rs» به راحتی copy/" "paste کنید و با آنها آزمایش کنید:" -#: src/running-the-course/course-structure.md:54 -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" -"```" - -#: src/running-the-course/course-structure.md:61 +#: src/running-the-course/course-structure.md:64 msgid "Format" msgstr "فرمت" -#: src/running-the-course/course-structure.md:63 +#: src/running-the-course/course-structure.md:66 msgid "" "The course is meant to be very interactive and we recommend letting the " "questions drive the exploration of Rust!" @@ -1472,10 +1466,11 @@ msgstr "" "است:" #: src/running-the-course/translations.md:6 +#, fuzzy 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 " +"com/hugojacob), [@joaovicmendes](https://github.com/joaovicmendes), and " "[@henrif75](https://github.com/henrif75)." msgstr "" "[Brazilian Portuguese](https://google.github.io/comprehensive-rust/pt-BR/) " @@ -1485,25 +1480,59 @@ msgstr "" #: src/running-the-course/translations.md:7 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)." +msgstr "" + +#: src/running-the-course/translations.md:8 +#, fuzzy +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 "" +"[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/running-the-course/translations.md:9 +#, fuzzy +msgid "" "[Korean](https://google.github.io/comprehensive-rust/ko/) by [@keispace]" -"(https://github.com/keispace), [@jiyongp](https://github.com/jiyongp) and " +"(https://github.com/keispace), [@jiyongp](https://github.com/jiyongp), and " "[@jooyunghan](https://github.com/jooyunghan)." msgstr "" "[Korean](https://google.github.io/comprehensive-rust/ko/) by [@keispace]" "(https://github.com/keispace), [@jiyongp](https://github.com/jiyongp) and " "[@jooyunghan](https://github.com/jooyunghan)." -#: src/running-the-course/translations.md:9 +#: src/running-the-course/translations.md:10 +#, fuzzy +msgid "" +"[Spanish](https://google.github.io/comprehensive-rust/es/) by [@deavid]" +"(https://github.com/deavid)." +msgstr "" +"[Bengali](https://google.github.io/comprehensive-rust/bn/) توسط " +"[@raselmandol](https://github.com/raselmandol)." + +#: src/running-the-course/translations.md:12 msgid "" "Use the language picker in the top-right corner to switch between languages." msgstr "" "از انتخابگر زبان در گوشه بالا سمت راست برای جابه‌جایی بین زبان‌ها استفاده کنید." -#: src/running-the-course/translations.md:11 +#: src/running-the-course/translations.md:14 msgid "Incomplete Translations" msgstr "ترجمه‌های کامل نشده" -#: src/running-the-course/translations.md:13 +#: src/running-the-course/translations.md:16 msgid "" "There is a large number of in-progress translations. We link to the most " "recently updated translations:" @@ -1511,7 +1540,7 @@ msgstr "" "تعداد زیادی ترجمه در حال انجام وجود دارد. ما به آخرین ترجمه های به روز شده " "پیوند می دهیم:" -#: src/running-the-course/translations.md:16 +#: src/running-the-course/translations.md:19 msgid "" "[Bengali](https://google.github.io/comprehensive-rust/bn/) by [@raselmandol]" "(https://github.com/raselmandol)." @@ -1519,7 +1548,7 @@ msgstr "" "[Bengali](https://google.github.io/comprehensive-rust/bn/) توسط " "[@raselmandol](https://github.com/raselmandol)." -#: src/running-the-course/translations.md:17 +#: src/running-the-course/translations.md:20 msgid "" "[French](https://google.github.io/comprehensive-rust/fr/) by [@KookaS]" "(https://github.com/KookaS) and [@vcaen](https://github.com/vcaen)." @@ -1527,7 +1556,7 @@ msgstr "" "[French](https://google.github.io/comprehensive-rust/fr/) توسط [@KookaS]" "(https://github.com/KookaS) و [@vcaen](https://github.com/vcaen)." -#: src/running-the-course/translations.md:18 +#: src/running-the-course/translations.md:21 msgid "" "[German](https://google.github.io/comprehensive-rust/de/) by [@Throvn]" "(https://github.com/Throvn) and [@ronaldfw](https://github.com/ronaldfw)." @@ -1535,7 +1564,7 @@ msgstr "" "[German](https://google.github.io/comprehensive-rust/de/) توسط [@Throvn]" "(https://github.com/Throvn) و [@ronaldfw](https://github.com/ronaldfw)." -#: src/running-the-course/translations.md:19 +#: src/running-the-course/translations.md:22 msgid "" "[Japanese](https://google.github.io/comprehensive-rust/ja/) by [@CoinEZ-JPN]" "(https://github.com/CoinEZ) and [@momotaro1105](https://github.com/" @@ -1545,7 +1574,7 @@ msgstr "" "JPN](https://github.com/CoinEZ) و [@momotaro1105](https://github.com/" "momotaro1105)." -#: src/running-the-course/translations.md:21 +#: src/running-the-course/translations.md:24 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 " @@ -1579,17 +1608,29 @@ msgid "**Please follow the instructions on .**" msgstr "**لطفا دستورالعمل را اجرا کنید .**" #: src/cargo.md:12 +#, fuzzy 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/switch toolchains, setup cross compilation, etc." +"use to install to different compiler versions." msgstr "" "این ابزار ساخت Cargo ('cargo') و کامپایلر Rust ('rustc') را در اختیار شما " "قرار می دهد. همچنین «rustup» را دریافت خواهید کرد، یک ابزار خط فرمان که " "می‌توانید از آن برای نصب/تغییر toolchains، راه‌اندازی cross کامپایل و ... " "استفاده کنید." -#: src/cargo.md:16 +#: src/cargo.md:14 +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:18 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 " @@ -1601,41 +1642,6 @@ msgstr "" "یک نسخه قدیمی Rust را جهت نصب می دهد و ممکن است منجر به رفتار غیرمنتظره " "برنامه شود. command مورد نظر این خواهد بود:" -#: src/cargo.md:18 -msgid "" -"```shell\n" -" sudo apt install cargo rust-src rustfmt\n" -"```" -msgstr "" -"```shell\n" -" sudo apt install cargo rust-src rustfmt\n" -"```" - -#: src/cargo.md:22 -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 "" -"پیشنهاد می کنیم از [VS Code](https://code.visualstudio.com/) برای ویرایش کد " -"استفاده کنید (اما هر ویرایشگر سازگار با LSP با ust-analyzer[3](https://rust-" -"analyzer.github.io/) کار می کند)." - -#: src/cargo.md:24 -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/) استفاده کنند، که آنالیزهای خود را انجام می دهند اما " -"یان مسئله tradeoffهای خاص خود را دارد. اگر آنها را ترجیح می دهید، می توانید " -"[Plugin Rust](https://www.jetbrains.com/rust/) را نصب کنید. لطفاً توجه داشته " -"باشید که از ژانویه 2023 اشکال زدایی (debugging) فقط در نسخه CLion مجموعه " -"JetBrains IDEA کار می کند." - #: src/cargo/rust-ecosystem.md:1 msgid "The Rust Ecosystem" msgstr "اکوسیستم رراست" @@ -1693,9 +1699,10 @@ msgstr "" #: src/cargo/rust-ecosystem.md:21 src/hello-world.md:25 #: src/hello-world/small-example.md:27 src/why-rust/runtime.md:10 -#: src/why-rust/modern.md:21 src/basic-syntax/compound-types.md:30 -#: src/basic-syntax/references.md:23 +#: src/why-rust/modern.md:21 src/basic-syntax/compound-types.md:32 +#: src/basic-syntax/references.md:24 #: src/pattern-matching/destructuring-enums.md:35 +#: src/ownership/double-free-modern-cpp.md:55 #: src/error-handling/try-operator.md:48 #: src/error-handling/converting-error-types-example.md:50 #: src/concurrency/threads.md:30 src/async/async-await.md:25 @@ -1920,82 +1927,40 @@ msgstr "" "«rustc» و «cargo» کاربردی بدهد. در زمان نگارش، آخرین نسخه پایدار Rust دارای " "این version numberها است:" -#: src/cargo/running-locally.md:8 -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.69.0 (84c898d65 2023-04-16)\n" -"% cargo --version\n" -"cargo 1.69.0 (6e9a83356 2023-04-12)\n" -"```" - #: src/cargo/running-locally.md:15 msgid "" +"You can use any later version too since Rust maintains backwards " +"compatibility." +msgstr "" + +#: src/cargo/running-locally.md:17 +msgid "" "With this in place, follow these steps to build a Rust binary from one of " "the examples in this training:" msgstr "" "با این کار، این مراحل را دنبال کنید تا از یکی از مثال‌های این آموزش، یک " "باینری Rust بسازید:" -#: src/cargo/running-locally.md:18 +#: src/cargo/running-locally.md:20 msgid "Click the \"Copy to clipboard\" button on the example you want to copy." msgstr "" "روی دکمه \"کپی در کلیپ بورد\" در نمونه ای که می خواهید کپی کنید؛ کلیک کنید." -#: src/cargo/running-locally.md:20 +#: src/cargo/running-locally.md:22 msgid "" "Use `cargo new exercise` to create a new `exercise/` directory for your code:" msgstr "" "از «cargo new exercise» برای ایجاد دایرکتوری «excerise/» جدید برای کد خود " "استفاده کنید:" -#: src/cargo/running-locally.md:22 -msgid "" -"```shell\n" -"$ cargo new exercise\n" -" Created binary (application) `exercise` package\n" -"```" -msgstr "" -"```shell\n" -"$ cargo new exercise\n" -" Created binary (application) `exercise` package\n" -"```" - -#: src/cargo/running-locally.md:27 +#: src/cargo/running-locally.md:29 msgid "" "Navigate into `exercise/` and use `cargo run` to build and run your binary:" msgstr "" "به «exercise/» بروید و از «cargo run» برای ساخت و اجرای باینری خود استفاده " "کنید:" -#: src/cargo/running-locally.md:29 -msgid "" -"```shell\n" -"$ cd exercise\n" -"$ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" -" Running `target/debug/exercise`\n" -"Hello, world!\n" -"```" -msgstr "" -"```shell\n" -"$ cd exercise\n" -"$ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" -" Running `target/debug/exercise`\n" -"Hello, world!\n" -"```" - -#: src/cargo/running-locally.md:38 +#: src/cargo/running-locally.md:40 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" @@ -2003,7 +1968,7 @@ msgstr "" "کد صفحه دیگر را در `src/main.rs` با کد خود جایگزین کنید. برای مثال، با " "استفاده از مثال در صفحه قبل، «src/main.rs» را شبیه به آن کنید." -#: src/cargo/running-locally.md:41 +#: src/cargo/running-locally.md:43 msgid "" "```rust\n" "fn main() {\n" @@ -2017,29 +1982,11 @@ msgstr "" "}\n" "```" -#: src/cargo/running-locally.md:47 +#: src/cargo/running-locally.md:49 msgid "Use `cargo run` to build and run your updated binary:" msgstr "برای ساختن و اجرای باینری به روز شده خود از «Cargo Run» استفاده کنید:" -#: src/cargo/running-locally.md:49 -msgid "" -"```shell\n" -"$ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" -" Running `target/debug/exercise`\n" -"Edit me!\n" -"```" -msgstr "" -"```shell\n" -"$ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" -" Running `target/debug/exercise`\n" -"Edit me!\n" -"```" - -#: src/cargo/running-locally.md:57 +#: src/cargo/running-locally.md:59 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/" @@ -2051,7 +1998,7 @@ msgstr "" "«target/debug/» برای ساخت اشکال زدایی معمولی خواهید یافت. برای تولید نسخه " "بهینه سازی شده در «target/release/» از «cargo build --release» استفاده کنید." -#: src/cargo/running-locally.md:62 +#: src/cargo/running-locally.md:64 msgid "" "You can add dependencies for your project by editing `Cargo.toml`. When you " "run `cargo` commands, it will automatically download and compile missing " @@ -2061,7 +2008,7 @@ msgstr "" "هنگامی که دستورات \"cargo\" را اجرا می کنید، به طور خودکار وابستگی های گم " "شده را برای شما دانلود و کامپایل می کند." -#: src/cargo/running-locally.md:70 +#: src/cargo/running-locally.md:72 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 " @@ -2093,16 +2040,13 @@ msgstr "" #: src/welcome-day-1.md:9 msgid "" -"Memory management: stack vs heap, manual memory management, scope-based " -"memory management, and garbage collection." +"Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and " +"`continue`." msgstr "" -"Memory management: stack vs heap, manual memory management, scope-based " -"memory management, و garbage collection." #: src/welcome-day-1.md:12 -msgid "" -"Ownership: move semantics, copying and cloning, borrowing, and lifetimes." -msgstr "Ownership: حرکت semantics،copying و cloning, borrowing و lifetimes." +msgid "Pattern matching: destructuring enums, structs, and arrays." +msgstr "" #: src/welcome-day-1.md:16 msgid "Please remind the students that:" @@ -2305,7 +2249,7 @@ msgstr "" #: src/hello-world.md:22 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 " +"see a ton of it over the next three days so we start small with something " "familiar." msgstr "" @@ -2445,6 +2389,196 @@ msgid "" "collector) as well as access to low-level hardware (should you need it)" msgstr "" +#: src/why-rust/an-example-in-c.md:4 +msgid "Let's consider the following \"minimum wrong example\" program in C:" +msgstr "" + +#: src/why-rust/an-example-in-c.md:6 +msgid "" +"```c,editable\n" +"#include \n" +"#include \n" +"#include \n" +"\n" +"int main(int argc, char* argv[]) {\n" +"\tchar *buf, *filename;\n" +"\tFILE *fp;\n" +"\tsize_t bytes, len;\n" +"\tstruct stat st;\n" +"\n" +"\tswitch (argc) {\n" +"\t\tcase 1:\n" +"\t\t\tprintf(\"Too few arguments!\\n\");\n" +"\t\t\treturn 1;\n" +"\n" +"\t\tcase 2:\n" +"\t\t\tfilename = argv[argc];\n" +"\t\t\tstat(filename, &st);\n" +"\t\t\tlen = st.st_size;\n" +"\t\t\t\n" +"\t\t\tbuf = (char*)malloc(len);\n" +"\t\t\tif (!buf)\n" +"\t\t\t\tprintf(\"malloc failed!\\n\", len);\n" +"\t\t\t\treturn 1;\n" +"\n" +"\t\t\tfp = fopen(filename, \"rb\");\n" +"\t\t\tbytes = fread(buf, 1, len, fp);\n" +"\t\t\tif (bytes = st.st_size)\n" +"\t\t\t\tprintf(\"%s\", buf);\n" +"\t\t\telse\n" +"\t\t\t\tprintf(\"fread failed!\\n\");\n" +"\n" +"\t\tcase 3:\n" +"\t\t\tprintf(\"Too many arguments!\\n\");\n" +"\t\t\treturn 1;\n" +"\t}\n" +"\n" +"\treturn 0;\n" +"}\n" +"```" +msgstr "" + +#: src/why-rust/an-example-in-c.md:48 +msgid "How many bugs do you spot?" +msgstr "" + +#: src/why-rust/an-example-in-c.md:52 +msgid "" +"Despite just 29 lines of code, this C example contains serious bugs in at " +"least 11:" +msgstr "" + +#: src/why-rust/an-example-in-c.md:54 +msgid "Assignment `=` instead of equality comparison `==` (line 28)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:55 +msgid "Excess argument to `printf` (line 23)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:56 +msgid "File descriptor leak (after line 26)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:57 +msgid "Forgotten braces in multi-line `if` (line 22)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:58 +msgid "Forgotten `break` in a `switch` statement (line 32)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:59 +msgid "" +"Forgotten NUL-termination of the `buf` string, leading to a buffer overflow " +"(line 29)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:60 +msgid "Memory leak by not freeing the `malloc`\\-allocated buffer (line 21)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:61 +msgid "Out-of-bounds access (line 17)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:62 +msgid "Unchecked cases in the `switch` statement (line 11)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:63 +msgid "Unchecked return values of `stat` and `fopen` (lines 18 and 26)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:65 +msgid "" +"_Shouldn't these bugs be obvious even for a C compiler?_ \n" +"No, surprisingly this code compiles warning-free at the default warning " +"level, even in the latest GCC version (13.2 as of writing)." +msgstr "" + +#: src/why-rust/an-example-in-c.md:68 +msgid "" +"_Isn't this a highly unrealistic example?_ \n" +"Absolutely not, these kind of bugs have lead to serious security " +"vulnerabilities in the past. Some examples:" +msgstr "" + +#: src/why-rust/an-example-in-c.md:71 +msgid "" +"Assignment `=` instead of equality comparison `==`: [The Linux Backdoor " +"Attempt of 2003](https://freedom-to-tinker.com/2013/10/09/the-linux-backdoor-" +"attempt-of-2003)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:72 +msgid "" +"Forgotten braces in multi-line `if`: [The Apple goto fail vulnerability]" +"(https://dwheeler.com/essays/apple-goto-fail.html)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:73 +msgid "" +"Forgotten `break` in a `switch` statement: [The break that broke sudo]" +"(https://nakedsecurity.sophos.com/2012/05/21/anatomy-of-a-security-hole-the-" +"break-that-broke-sudo)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:75 +msgid "" +"_How is Rust any better here?_ \n" +"Safe Rust makes all of these bugs impossible:" +msgstr "" + +#: src/why-rust/an-example-in-c.md:78 +msgid "Assignments inside an `if` clause are not supported." +msgstr "" + +#: src/why-rust/an-example-in-c.md:79 +msgid "Format strings are checked at compile-time." +msgstr "" + +#: src/why-rust/an-example-in-c.md:80 +msgid "Resources are freed at the end of scope via the `Drop` trait." +msgstr "" + +#: src/why-rust/an-example-in-c.md:81 +msgid "All `if` clauses require braces." +msgstr "" + +#: src/why-rust/an-example-in-c.md:82 +msgid "" +"`match` (as the Rust equivalent to `switch`) does not fall-through, hence " +"you can't accidentally forget a `break`." +msgstr "" + +#: src/why-rust/an-example-in-c.md:83 +msgid "Buffer slices carry their size and don't rely on a NUL terminator." +msgstr "" + +#: src/why-rust/an-example-in-c.md:84 +msgid "" +"Heap-allocated memory is freed via the `Drop` trait when the corresponding " +"`Box` leaves the scope." +msgstr "" + +#: src/why-rust/an-example-in-c.md:85 +msgid "" +"Out-of-bounds accesses cause a panic or can be checked via the `get` method " +"of a slice." +msgstr "" + +#: src/why-rust/an-example-in-c.md:86 +msgid "`match` mandates that all cases are handled." +msgstr "" + +#: src/why-rust/an-example-in-c.md:87 +msgid "" +"Fallible Rust functions return `Result` values that need to be unwrapped and " +"thereby checked for success. Additionally, the compiler emits a warning if " +"you miss to check the return value of a function marked with `#[must_use]`." +msgstr "" + #: src/why-rust/compile-time.md:3 msgid "Static memory management at compile time:" msgstr "" @@ -2796,31 +2930,11 @@ msgid "" "amount of `#` on either side of the quotes:" msgstr "" -#: src/basic-syntax/scalar-types.md:27 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(r#\"link\"#);\n" -" println!(\"link\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/scalar-types.md:34 +#: src/basic-syntax/scalar-types.md:35 msgid "Byte strings allow you to create a `&[u8]` value directly:" msgstr "" -#: src/basic-syntax/scalar-types.md:36 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"{:?}\", b\"abc\");\n" -" println!(\"{:?}\", &[97, 98, 99]);\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/scalar-types.md:43 +#: src/basic-syntax/scalar-types.md:45 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 " @@ -2855,37 +2969,15 @@ msgstr "" msgid "Array assignment and access:" msgstr "" -#: src/basic-syntax/compound-types.md:10 -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 "" - -#: src/basic-syntax/compound-types.md:18 +#: src/basic-syntax/compound-types.md:19 msgid "Tuple assignment and access:" msgstr "" -#: src/basic-syntax/compound-types.md:20 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let t: (i8, bool) = (7, true);\n" -" println!(\"1st index: {}\", t.0);\n" -" println!(\"2nd index: {}\", t.1);\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/compound-types.md:32 +#: src/basic-syntax/compound-types.md:34 msgid "Arrays:" msgstr "" -#: src/basic-syntax/compound-types.md:34 +#: src/basic-syntax/compound-types.md:36 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 " @@ -2893,43 +2985,44 @@ msgid "" "different types." msgstr "" -#: src/basic-syntax/compound-types.md:38 +#: src/basic-syntax/compound-types.md:40 msgid "We can use literals to assign values to arrays." msgstr "" -#: src/basic-syntax/compound-types.md:40 +#: src/basic-syntax/compound-types.md:42 msgid "" -"In the main function, the print statement asks for the debug implementation " -"with the `?` format parameter: `{}` gives the default output, `{:?}` gives " -"the debug output. We could also have used `{a}` and `{a:?}` without " -"specifying the value after the format string." +"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/basic-syntax/compound-types.md:45 +#: src/basic-syntax/compound-types.md:47 msgid "" "Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be " "easier to read." msgstr "" -#: src/basic-syntax/compound-types.md:47 +#: src/basic-syntax/compound-types.md:49 msgid "Tuples:" msgstr "" -#: src/basic-syntax/compound-types.md:49 +#: src/basic-syntax/compound-types.md:51 msgid "Like arrays, tuples have a fixed length." msgstr "" -#: src/basic-syntax/compound-types.md:51 +#: src/basic-syntax/compound-types.md:53 msgid "Tuples group together values of different types into a compound type." msgstr "" -#: src/basic-syntax/compound-types.md:53 +#: src/basic-syntax/compound-types.md:55 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/basic-syntax/compound-types.md:55 +#: src/basic-syntax/compound-types.md:57 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 " @@ -2937,7 +3030,7 @@ msgid "" "function or expression has no return value, as we'll see in a future slide. " msgstr "" -#: src/basic-syntax/compound-types.md:59 +#: src/basic-syntax/compound-types.md:61 msgid "" "You can think of it as `void` that can be familiar to you from other " "programming languages." @@ -2947,41 +3040,29 @@ msgstr "" msgid "Like C++, Rust has references:" msgstr "" -#: src/basic-syntax/references.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x: i32 = 10;\n" -" let ref_x: &mut i32 = &mut x;\n" -" *ref_x = 20;\n" -" println!(\"x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/references.md:14 +#: src/basic-syntax/references.md:15 msgid "Some notes:" msgstr "" -#: src/basic-syntax/references.md:16 +#: src/basic-syntax/references.md:17 msgid "" "We must dereference `ref_x` when assigning to it, similar to C and C++ " "pointers." msgstr "" -#: src/basic-syntax/references.md:17 +#: src/basic-syntax/references.md:18 msgid "" "Rust will auto-dereference in some cases, in particular when invoking " "methods (try `ref_x.count_ones()`)." msgstr "" -#: src/basic-syntax/references.md:19 +#: src/basic-syntax/references.md:20 msgid "" "References that are declared as `mut` can be bound to different values over " "their lifetime." msgstr "" -#: src/basic-syntax/references.md:25 +#: src/basic-syntax/references.md:26 msgid "" "Be sure to note the difference between `let mut ref_x: &i32` and `let ref_x: " "&mut i32`. The first one represents a mutable reference which can be bound " @@ -2993,31 +3074,17 @@ msgstr "" msgid "Rust will statically forbid dangling references:" msgstr "" -#: src/basic-syntax/references-dangling.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let ref_x: &i32;\n" -" {\n" -" let x: i32 = 10;\n" -" ref_x = &x;\n" -" }\n" -" println!(\"ref_x: {ref_x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/references-dangling.md:16 +#: src/basic-syntax/references-dangling.md:17 msgid "A reference is said to \"borrow\" the value it refers to." msgstr "" -#: src/basic-syntax/references-dangling.md:17 +#: src/basic-syntax/references-dangling.md:18 msgid "" "Rust is tracking the lifetimes of all references to ensure they live long " "enough." msgstr "" -#: src/basic-syntax/references-dangling.md:19 +#: src/basic-syntax/references-dangling.md:20 msgid "We will talk more about borrowing when we get to ownership." msgstr "" @@ -3025,66 +3092,52 @@ msgstr "" msgid "A slice gives you a view into a larger collection:" msgstr "" -#: src/basic-syntax/slices.md:5 -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 "" - -#: src/basic-syntax/slices.md:16 +#: src/basic-syntax/slices.md:17 msgid "Slices borrow data from the sliced type." msgstr "" -#: src/basic-syntax/slices.md:17 +#: src/basic-syntax/slices.md:18 msgid "Question: What happens if you modify `a[3]` right before printing `s`?" msgstr "" -#: src/basic-syntax/slices.md:21 +#: src/basic-syntax/slices.md:22 msgid "" "We create a slice by borrowing `a` and specifying the starting and ending " "indexes in brackets." msgstr "" -#: src/basic-syntax/slices.md:23 +#: src/basic-syntax/slices.md:24 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/basic-syntax/slices.md:25 +#: src/basic-syntax/slices.md:26 msgid "" "The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are " "identical." msgstr "" -#: src/basic-syntax/slices.md:27 +#: src/basic-syntax/slices.md:28 msgid "" "To easily create a slice of the full array, we can therefore use `&a[..]`." msgstr "" -#: src/basic-syntax/slices.md:29 +#: src/basic-syntax/slices.md:30 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/basic-syntax/slices.md:31 +#: src/basic-syntax/slices.md:32 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/basic-syntax/slices.md:33 +#: src/basic-syntax/slices.md:34 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 " @@ -3178,62 +3231,31 @@ msgid "" "Fizz_buzz) interview question:" msgstr "" -#: src/basic-syntax/functions.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" print_fizzbuzz_to(20);\n" -"}\n" -"\n" -"fn is_divisible(n: u32, divisor: u32) -> bool {\n" -" if divisor == 0 {\n" -" return false;\n" -" }\n" -" n % divisor == 0\n" -"}\n" -"\n" -"fn fizzbuzz(n: u32) -> String {\n" -" let fizz = if is_divisible(n, 3) { \"fizz\" } else { \"\" };\n" -" let buzz = if is_divisible(n, 5) { \"buzz\" } else { \"\" };\n" -" if fizz.is_empty() && buzz.is_empty() {\n" -" return format!(\"{n}\");\n" -" }\n" -" format!(\"{fizz}{buzz}\")\n" -"}\n" -"\n" -"fn print_fizzbuzz_to(n: u32) {\n" -" for i in 1..=n {\n" -" println!(\"{}\", fizzbuzz(i));\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/functions.md:35 +#: src/basic-syntax/functions.md:36 msgid "" "We refer in `main` to a function written below. Neither forward declarations " "nor headers are necessary. " msgstr "" -#: src/basic-syntax/functions.md:36 +#: src/basic-syntax/functions.md:37 msgid "" "Declaration parameters are followed by a type (the reverse of some " "programming languages), then a return type." msgstr "" -#: src/basic-syntax/functions.md:37 +#: src/basic-syntax/functions.md:38 msgid "" "The last expression in a function body (or any block) becomes the return " "value. Simply omit the `;` at the end of the expression." msgstr "" -#: src/basic-syntax/functions.md:38 +#: src/basic-syntax/functions.md:39 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/basic-syntax/functions.md:39 +#: src/basic-syntax/functions.md:40 msgid "" "The range expression in the `for` loop in `print_fizzbuzz_to()` contains " "`=n`, which causes it to include the upper bound." @@ -3251,6 +3273,11 @@ msgid "" "argument.\n" "///\n" "/// If the second argument is zero, the result is false.\n" +"///\n" +"/// # Example\n" +"/// ```\n" +"/// assert!(is_divisible_by(42, 2));\n" +"/// ```\n" "fn is_divisible_by(lhs: u32, rhs: u32) -> bool {\n" " if rhs == 0 {\n" " return false; // Corner case, early return\n" @@ -3261,33 +3288,34 @@ msgid "" "```" msgstr "" -#: src/basic-syntax/rustdoc.md:17 +#: src/basic-syntax/rustdoc.md:22 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." +"idiomatic to document all public items in an API using this pattern. Code " +"snippets can document usage and will be used as unit tests." msgstr "" -#: src/basic-syntax/rustdoc.md:24 +#: src/basic-syntax/rustdoc.md:30 msgid "" "Show students the generated docs for the `rand` crate at [`docs.rs/rand`]" "(https://docs.rs/rand)." msgstr "" -#: src/basic-syntax/rustdoc.md:27 +#: src/basic-syntax/rustdoc.md:33 msgid "" "This course does not include rustdoc on slides, just to save space, but in " "real code they should be present." msgstr "" -#: src/basic-syntax/rustdoc.md:30 +#: src/basic-syntax/rustdoc.md:36 msgid "" "Inner doc comments are discussed later (in the page on modules) and need not " "be addressed here." msgstr "" -#: src/basic-syntax/rustdoc.md:33 +#: src/basic-syntax/rustdoc.md:39 msgid "" "Rustdoc comments can contain code snippets that we can run and test using " "`cargo test`. We will discuss these tests in the [Testing section](../" @@ -3337,15 +3365,6 @@ msgstr "" msgid "Add a static method called `Rectangle::new` and call this from `main`:" msgstr "" -#: src/basic-syntax/methods.md:36 -msgid "" -"```rust,editable,compile_fail\n" -"fn new(width: u32, height: u32) -> Rectangle {\n" -" Rectangle { width, height }\n" -"}\n" -"```" -msgstr "" - #: src/basic-syntax/methods.md:42 msgid "" "While _technically_, Rust does not have custom constructors, static methods " @@ -3454,14 +3473,12 @@ msgid "" "their state if you navigate away from the page." msgstr "" -#: src/exercises/day-1/morning.md:22 src/exercises/day-1/afternoon.md:11 -#: src/exercises/day-2/morning.md:11 src/exercises/day-2/afternoon.md:7 -#: src/exercises/day-3/morning.md:7 src/exercises/bare-metal/morning.md:7 -#: src/exercises/bare-metal/afternoon.md:7 +#: src/exercises/day-1/morning.md:22 src/exercises/day-2/morning.md:11 +#: src/exercises/day-3/morning.md:9 src/exercises/bare-metal/morning.md:7 #: src/exercises/concurrency/morning.md:12 -#: src/exercises/concurrency/afternoon.md:13 msgid "" -"After looking at the exercises, you can look at the \\[solutions\\] provided." +"After looking at the exercises, you can look at the [solutions](solutions-" +"morning.md) provided." msgstr "" #: src/exercises/day-1/implicit-conversions.md:3 @@ -3471,23 +3488,7 @@ msgid "" "implicit_conversion)). You can see this in a program like this:" msgstr "" -#: src/exercises/day-1/implicit-conversions.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"fn multiply(x: i16, y: i16) -> i16 {\n" -" x * y\n" -"}\n" -"\n" -"fn main() {\n" -" let x: i8 = 15;\n" -" let y: i16 = 1000;\n" -"\n" -" println!(\"{x} * {y} = {}\", multiply(x, y));\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/implicit-conversions.md:19 +#: src/exercises/day-1/implicit-conversions.md:20 msgid "" "The Rust integer types all implement the [`From`](https://doc.rust-lang." "org/std/convert/trait.From.html) and [`Into`](https://doc.rust-lang.org/" @@ -3497,7 +3498,7 @@ msgid "" "expresses that it can be converted into another type." msgstr "" -#: src/exercises/day-1/implicit-conversions.md:25 +#: src/exercises/day-1/implicit-conversions.md:26 msgid "" "The standard library has an implementation of `From for i16`, which " "means that we can convert a variable `x` of type `i8` to an `i16` by " @@ -3506,22 +3507,22 @@ msgid "" "i8`." msgstr "" -#: src/exercises/day-1/implicit-conversions.md:30 +#: src/exercises/day-1/implicit-conversions.md:31 msgid "" "The same applies for your own `From` implementations for your own types, so " "it is sufficient to only implement `From` to get a respective `Into` " "implementation automatically." msgstr "" -#: src/exercises/day-1/implicit-conversions.md:33 +#: src/exercises/day-1/implicit-conversions.md:34 msgid "Execute the above program and look at the compiler error." msgstr "" -#: src/exercises/day-1/implicit-conversions.md:35 +#: src/exercises/day-1/implicit-conversions.md:36 msgid "Update the code above to use `into()` to do the conversion." msgstr "" -#: src/exercises/day-1/implicit-conversions.md:37 +#: src/exercises/day-1/implicit-conversions.md:38 msgid "" "Change the types of `x` and `y` to other things (such as `f32`, `bool`, " "`i128`) to see which types you can convert to which other types. Try " @@ -3539,42 +3540,25 @@ msgstr "" msgid "We saw that an array can be declared like this:" msgstr "" -#: src/exercises/day-1/for-loops.md:5 -msgid "" -"```rust\n" -"let array = [10, 20, 30];\n" -"```" -msgstr "" - #: src/exercises/day-1/for-loops.md:9 msgid "" "You can print such an array by asking for its debug representation with `{:?}" "`:" msgstr "" -#: src/exercises/day-1/for-loops.md:11 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let array = [10, 20, 30];\n" -" println!(\"array: {array:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/for-loops.md:18 +#: src/exercises/day-1/for-loops.md:19 msgid "" "Rust lets you iterate over things like arrays and ranges using the `for` " "keyword:" msgstr "" -#: src/exercises/day-1/for-loops.md:21 +#: src/exercises/day-1/for-loops.md:22 msgid "" "```rust,editable\n" "fn main() {\n" " let array = [10, 20, 30];\n" " print!(\"Iterating over array:\");\n" -" for n in array {\n" +" for n in &array {\n" " print!(\" {n}\");\n" " }\n" " println!();\n" @@ -3588,33 +3572,24 @@ msgid "" "```" msgstr "" -#: src/exercises/day-1/for-loops.md:38 +#: src/exercises/day-1/for-loops.md:39 msgid "" "Use the above to write a function `pretty_print` which pretty-print a matrix " "and a function `transpose` which will transpose a matrix (turn rows into " "columns):" msgstr "" -#: src/exercises/day-1/for-loops.md:41 -msgid "" -"```bob\n" -" ⎛⎡1 2 3⎤⎞ ⎡1 4 7⎤\n" -"\"transpose\"⎜⎢4 5 6⎥⎟ \"==\"⎢2 5 8⎥\n" -" ⎝⎣7 8 9⎦⎠ ⎣3 6 9⎦\n" -"```" -msgstr "" - -#: src/exercises/day-1/for-loops.md:47 +#: src/exercises/day-1/for-loops.md:49 msgid "Hard-code both functions to operate on 3 × 3 matrices." msgstr "" -#: src/exercises/day-1/for-loops.md:49 +#: src/exercises/day-1/for-loops.md:51 msgid "" "Copy the code below to and implement the " "functions:" msgstr "" -#: src/exercises/day-1/for-loops.md:52 +#: src/exercises/day-1/for-loops.md:54 msgid "" "```rust,should_panic\n" "// TODO: remove this when you're done with your implementation.\n" @@ -3645,92 +3620,239 @@ msgid "" "```" msgstr "" -#: src/exercises/day-1/for-loops.md:80 +#: src/exercises/day-1/for-loops.md:82 msgid "Bonus Question" msgstr "" -#: src/exercises/day-1/for-loops.md:82 +#: src/exercises/day-1/for-loops.md:84 msgid "" "Could you use `&[i32]` slices instead of hard-coded 3 × 3 matrices for your " "argument and return types? Something like `&[&[i32]]` for a two-dimensional " "slice-of-slices. Why or why not?" msgstr "" -#: src/exercises/day-1/for-loops.md:87 +#: src/exercises/day-1/for-loops.md:89 msgid "" "See the [`ndarray` crate](https://docs.rs/ndarray/) for a production quality " "implementation." msgstr "" -#: src/exercises/day-1/for-loops.md:92 +#: src/exercises/day-1/for-loops.md:94 msgid "" "The solution and the answer to the bonus section are available in the " "[Solution](solutions-morning.md#arrays-and-for-loops) section." msgstr "" +#: src/exercises/day-1/for-loops.md:97 +msgid "" +"The use of the reference `&array` within `for n in &array` is a subtle " +"preview of issues of ownership that will come later in the afternoon." +msgstr "" + +#: src/exercises/day-1/for-loops.md:100 +msgid "Without the `&`..." +msgstr "" + +#: src/exercises/day-1/for-loops.md:101 +msgid "" +"The loop would have been one that consumes the array. This is a change " +"[introduced in the 2021 Edition](https://doc.rust-lang.org/edition-guide/" +"rust-2021/IntoIterator-for-arrays.html)." +msgstr "" + +#: src/exercises/day-1/for-loops.md:104 +msgid "" +"An implicit array copy would have occurred. Since `i32` is a copy type, " +"then `[i32; 3]` is also a copy type." +msgstr "" + +#: src/control-flow.md:3 +msgid "" +"As we have seen, `if` is an expression in Rust. It is used to conditionally " +"evaluate one of two blocks, but the blocks can have a value which then " +"becomes the value of the `if` expression. Other control flow expressions " +"work similarly in Rust." +msgstr "" + +#: src/control-flow/blocks.md:3 +msgid "" +"A block in Rust contains a sequence of expressions. Each block has a value " +"and a type, which are those of the last expression of the block:" +msgstr "" + +#: src/control-flow/blocks.md:27 +msgid "" +"If the last expression ends with `;`, then the resulting value and type is " +"`()`." +msgstr "" + +#: src/control-flow/blocks.md:29 +msgid "" +"The same rule is used for functions: the value of the function body is the " +"return value:" +msgstr "" + +#: src/control-flow/blocks.md:45 src/enums.md:34 src/enums/sizes.md:28 +#: src/pattern-matching.md:25 src/pattern-matching/match-guards.md:22 +#: src/structs.md:31 src/methods.md:30 src/methods/example.md:46 +msgid "Key Points:" +msgstr "" + +#: src/control-flow/blocks.md:46 +msgid "" +"The point of this slide is to show that blocks have a type and value in " +"Rust. " +msgstr "" + +#: src/control-flow/blocks.md:47 +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/if-expressions.md:1 +msgid "`if` expressions" +msgstr "" + +#: src/control-flow/if-expressions.md:3 +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/if-expressions.md:18 +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/if-expressions.md:35 +msgid "" +"Because `if` is an expression and must have a particular type, both of its " +"branch blocks must have the same type. Consider showing what happens if you " +"add `;` after `x / 2` in the second example." +msgstr "" + +#: src/control-flow/for-expressions.md:1 +msgid "`for` loops" +msgstr "" + +#: src/control-flow/for-expressions.md:3 +msgid "" +"The [`for` loop](https://doc.rust-lang.org/std/keyword.for.html) is closely " +"related to the [`while let` loop](while-let-expressions.md). It will " +"automatically call `into_iter()` on the expression and then iterate over it:" +msgstr "" + +#: src/control-flow/for-expressions.md:22 +msgid "You can use `break` and `continue` here as usual." +msgstr "" + +#: src/control-flow/for-expressions.md:26 +msgid "Index iteration is not a special syntax in Rust for just that case." +msgstr "" + +#: src/control-flow/for-expressions.md:27 +msgid "`(0..10)` is a range that implements an `Iterator` trait. " +msgstr "" + +#: src/control-flow/for-expressions.md:28 +msgid "" +"`step_by` is a method that returns another `Iterator` that skips every other " +"element. " +msgstr "" + +#: src/control-flow/for-expressions.md:29 +msgid "" +"Modify the elements in the vector and explain the compiler errors. Change " +"vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." +msgstr "" + +#: src/control-flow/while-expressions.md:1 +msgid "`while` loops" +msgstr "" + +#: src/control-flow/while-expressions.md:3 +msgid "" +"The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-" +"expr.html#predicate-loops) works very similar to other languages:" +msgstr "" + +#: src/control-flow/break-continue.md:1 +msgid "`break` and `continue`" +msgstr "" + +#: src/control-flow/break-continue.md:3 +msgid "" +"If you want to exit a loop early, use [`break`](https://doc.rust-lang.org/" +"reference/expressions/loop-expr.html#break-expressions)," +msgstr "" + +#: src/control-flow/break-continue.md:4 +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/break-continue.md:7 +msgid "" +"Both `continue` and `break` can optionally take a label argument which is " +"used to break out of nested loops:" +msgstr "" + +#: src/control-flow/break-continue.md:29 +msgid "" +"In this case we break the outer loop after 3 iterations of the inner loop." +msgstr "" + +#: src/control-flow/loop-expressions.md:1 +msgid "`loop` expressions" +msgstr "" + +#: src/control-flow/loop-expressions.md:3 +msgid "" +"Finally, there is a [`loop` keyword](https://doc.rust-lang.org/reference/" +"expressions/loop-expr.html#infinite-loops) which creates an endless loop." +msgstr "" + +#: src/control-flow/loop-expressions.md:6 +msgid "Here you must either `break` or `return` to stop the loop:" +msgstr "" + +#: src/control-flow/loop-expressions.md:28 +msgid "Break the `loop` with a value (e.g. `break 8`) and print it out." +msgstr "" + +#: src/control-flow/loop-expressions.md:29 +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)." +msgstr "" + #: src/basic-syntax/variables.md:3 msgid "" "Rust provides type safety via static typing. Variable bindings are immutable " "by default:" msgstr "" -#: src/basic-syntax/variables.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let x: i32 = 10;\n" -" println!(\"x: {x}\");\n" -" // x = 20;\n" -" // println!(\"x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/variables.md:17 +#: src/basic-syntax/variables.md:18 msgid "" "Due to type inference the `i32` is optional. We will gradually show the " "types less and less as the course progresses." msgstr "" -#: src/basic-syntax/variables.md:18 -msgid "" -"Note that since `println!` is a macro, `x` is not moved, even using the " -"function like syntax of `println!(\"x: {}\", x)`" -msgstr "" - #: src/basic-syntax/type-inference.md:3 msgid "Rust will look at how the variable is _used_ to determine the type:" msgstr "" -#: src/basic-syntax/type-inference.md:5 -msgid "" -"```rust,editable\n" -"fn takes_u32(x: u32) {\n" -" println!(\"u32: {x}\");\n" -"}\n" -"\n" -"fn takes_i8(y: i8) {\n" -" println!(\"i8: {y}\");\n" -"}\n" -"\n" -"fn main() {\n" -" let x = 10;\n" -" let y = 20;\n" -"\n" -" takes_u32(x);\n" -" takes_i8(y);\n" -" // takes_u32(y);\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/type-inference.md:26 +#: src/basic-syntax/type-inference.md:27 msgid "" "This slide demonstrates how the Rust compiler infers types based on " "constraints given by variable declarations and usages." msgstr "" -#: src/basic-syntax/type-inference.md:28 +#: src/basic-syntax/type-inference.md:29 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 " @@ -3739,29 +3861,14 @@ msgid "" "code." msgstr "" -#: src/basic-syntax/type-inference.md:32 +#: src/basic-syntax/type-inference.md:33 msgid "" "The following code tells the compiler to copy into a certain generic " "container without the code ever explicitly specifying the contained type, " "using `_` as a placeholder:" msgstr "" -#: src/basic-syntax/type-inference.md:34 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut v = Vec::new();\n" -" v.push((10, false));\n" -" v.push((20, true));\n" -" println!(\"v: {v:?}\");\n" -"\n" -" let vv = v.iter().collect::>();\n" -" println!(\"vv: {vv:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/type-inference.md:46 +#: src/basic-syntax/type-inference.md:48 msgid "" "[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator." "html#method.collect) relies on [`FromIterator`](https://doc.rust-lang.org/" @@ -3791,51 +3898,29 @@ msgid "" "inlined wherever they are used:" msgstr "" -#: src/basic-syntax/static-and-const.md:11 -msgid "" -"```rust,editable\n" -"const DIGEST_SIZE: usize = 3;\n" -"const ZERO: Option = Some(42);\n" -"\n" -"fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {\n" -" let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];\n" -" for (idx, &b) in text.as_bytes().iter().enumerate() {\n" -" digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE]." -"wrapping_add(b);\n" -" }\n" -" digest\n" -"}\n" -"\n" -"fn main() {\n" -" let digest = compute_digest(\"Hello\");\n" -" println!(\"Digest: {digest:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/static-and-const.md:29 +#: src/basic-syntax/static-and-const.md:30 msgid "" "According to the [Rust RFC Book](https://rust-lang.github.io/rfcs/0246-const-" "vs-static.html) these are inlined upon use." msgstr "" -#: src/basic-syntax/static-and-const.md:31 +#: src/basic-syntax/static-and-const.md:32 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/basic-syntax/static-and-const.md:33 +#: src/basic-syntax/static-and-const.md:34 msgid "`static`" msgstr "" -#: src/basic-syntax/static-and-const.md:35 +#: src/basic-syntax/static-and-const.md:36 msgid "" "Static variables will live during the whole execution of the program, and " "therefore will not move:" msgstr "" -#: src/basic-syntax/static-and-const.md:37 +#: src/basic-syntax/static-and-const.md:38 msgid "" "```rust,editable\n" "static BANNER: &str = \"Welcome to RustOS 3.14\";\n" @@ -3846,7 +3931,7 @@ msgid "" "```" msgstr "" -#: src/basic-syntax/static-and-const.md:45 +#: src/basic-syntax/static-and-const.md:46 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 " @@ -3856,100 +3941,100 @@ msgid "" "`const` is generally preferred." msgstr "" -#: src/basic-syntax/static-and-const.md:49 +#: src/basic-syntax/static-and-const.md:50 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. It is also possible " "to have mutable statics, but they require manual synchronisation so any " -"access to them requires `unsafe` code. We will look at mutable statics\\](../" +"access to them requires `unsafe` code. We will look at [mutable statics](../" "unsafe/mutable-static-variables.md) in the chapter on Unsafe Rust." msgstr "" -#: src/basic-syntax/static-and-const.md:57 +#: src/basic-syntax/static-and-const.md:58 msgid "Mention that `const` behaves semantically similar to C++'s `constexpr`." msgstr "" -#: src/basic-syntax/static-and-const.md:58 +#: src/basic-syntax/static-and-const.md:59 msgid "" "`static`, on the other hand, is much more similar to a `const` or mutable " "global variable in C++." msgstr "" -#: src/basic-syntax/static-and-const.md:59 +#: src/basic-syntax/static-and-const.md:60 msgid "" "`static` provides object identity: an address in memory and state as " "required by types with interior mutability such as `Mutex`." msgstr "" -#: src/basic-syntax/static-and-const.md:60 +#: src/basic-syntax/static-and-const.md:61 msgid "" "It isn't super common that one would need a runtime evaluated constant, but " "it is helpful and safer than using a static." msgstr "" -#: src/basic-syntax/static-and-const.md:61 +#: src/basic-syntax/static-and-const.md:62 msgid "`thread_local` data can be created with the macro `std::thread_local`." msgstr "" -#: src/basic-syntax/static-and-const.md:63 +#: src/basic-syntax/static-and-const.md:64 msgid "Properties table:" msgstr "" -#: src/basic-syntax/static-and-const.md:65 +#: src/basic-syntax/static-and-const.md:66 msgid "Property" msgstr "" -#: src/basic-syntax/static-and-const.md:65 +#: src/basic-syntax/static-and-const.md:66 msgid "Static" msgstr "" -#: src/basic-syntax/static-and-const.md:65 +#: src/basic-syntax/static-and-const.md:66 msgid "Constant" msgstr "" -#: src/basic-syntax/static-and-const.md:67 +#: src/basic-syntax/static-and-const.md:68 msgid "Has an address in memory" msgstr "" -#: src/basic-syntax/static-and-const.md:67 #: src/basic-syntax/static-and-const.md:68 -#: src/basic-syntax/static-and-const.md:70 +#: src/basic-syntax/static-and-const.md:69 #: src/basic-syntax/static-and-const.md:71 +#: src/basic-syntax/static-and-const.md:72 msgid "Yes" msgstr "" -#: src/basic-syntax/static-and-const.md:67 +#: src/basic-syntax/static-and-const.md:68 msgid "No (inlined)" msgstr "" -#: src/basic-syntax/static-and-const.md:68 +#: src/basic-syntax/static-and-const.md:69 msgid "Lives for the entire duration of the program" msgstr "" -#: src/basic-syntax/static-and-const.md:68 #: src/basic-syntax/static-and-const.md:69 -#: src/basic-syntax/static-and-const.md:71 +#: src/basic-syntax/static-and-const.md:70 +#: src/basic-syntax/static-and-const.md:72 msgid "No" msgstr "" -#: src/basic-syntax/static-and-const.md:69 +#: src/basic-syntax/static-and-const.md:70 msgid "Can be mutable" msgstr "" -#: src/basic-syntax/static-and-const.md:69 +#: src/basic-syntax/static-and-const.md:70 msgid "Yes (unsafe)" msgstr "" -#: src/basic-syntax/static-and-const.md:70 +#: src/basic-syntax/static-and-const.md:71 msgid "Evaluated at compile time" msgstr "" -#: src/basic-syntax/static-and-const.md:70 +#: src/basic-syntax/static-and-const.md:71 msgid "Yes (initialised at compile time)" msgstr "" -#: src/basic-syntax/static-and-const.md:71 +#: src/basic-syntax/static-and-const.md:72 msgid "Inlined wherever it is used" msgstr "" @@ -4003,1748 +4088,6 @@ msgid "" "does not change." msgstr "" -#: src/basic-syntax/scopes-shadowing.md:30 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let a = 1;\n" -" let b = &a;\n" -" let a = a + 1;\n" -" println!(\"{a} {b}\");\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management.md:3 -msgid "Traditionally, languages have fallen into two broad categories:" -msgstr "" - -#: src/memory-management.md:5 -msgid "Full control via manual memory management: C, C++, Pascal, ..." -msgstr "" - -#: src/memory-management.md:6 -msgid "" -"Full safety via automatic memory management at runtime: Java, Python, Go, " -"Haskell, ..." -msgstr "" - -#: src/memory-management.md:8 -msgid "Rust offers a new mix:" -msgstr "" - -#: src/memory-management.md:10 -msgid "" -"Full control _and_ safety via compile time enforcement of correct memory " -"management." -msgstr "" - -#: src/memory-management.md:13 -msgid "It does this with an explicit ownership concept." -msgstr "" - -#: src/memory-management.md:15 -msgid "First, let's refresh how memory management works." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:1 -msgid "The Stack vs The Heap" -msgstr "" - -#: src/memory-management/stack-vs-heap.md:3 -msgid "Stack: Continuous area of memory for local variables." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:4 -msgid "Values have fixed sizes known at compile time." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:5 -msgid "Extremely fast: just move a stack pointer." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:6 -msgid "Easy to manage: follows function calls." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:7 -msgid "Great memory locality." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:9 -msgid "Heap: Storage of values outside of function calls." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:10 -msgid "Values have dynamic sizes determined at runtime." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:11 -msgid "Slightly slower than the stack: some book-keeping needed." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:12 -msgid "No guarantee of memory locality." -msgstr "" - -#: src/memory-management/stack.md:1 -msgid "Stack and Heap Example" -msgstr "" - -#: src/memory-management/stack.md:3 -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/stack.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1 = String::from(\"Hello\");\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/stack.md:12 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| H | e | l | l | o | :\n" -": | len | 5 | : : +----+----+----+----+----+ :\n" -": | capacity | 5 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/memory-management/stack.md:28 -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/stack.md:30 -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/stack.md:32 -msgid "" -"We can inspect the memory layout with `unsafe` code. However, you should " -"point out that this is rightfully unsafe!" -msgstr "" - -#: src/memory-management/stack.md:34 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut s1 = String::from(\"Hello\");\n" -" s1.push(' ');\n" -" s1.push_str(\"world\");\n" -" // 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" -" unsafe {\n" -" let (ptr, capacity, len): (usize, usize, usize) = std::mem::" -"transmute(s1);\n" -" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/manual.md:3 -msgid "You allocate and deallocate heap memory yourself." -msgstr "" - -#: src/memory-management/manual.md:5 -msgid "" -"If not done with care, this can lead to crashes, bugs, security " -"vulnerabilities, and memory leaks." -msgstr "" - -#: src/memory-management/manual.md:7 -msgid "C Example" -msgstr "" - -#: src/memory-management/manual.md:9 -msgid "You must call `free` on every pointer you allocate with `malloc`:" -msgstr "" - -#: src/memory-management/manual.md:11 -msgid "" -"```c\n" -"void foo(size_t n) {\n" -" int* int_array = malloc(n * sizeof(int));\n" -" //\n" -" // ... lots of code\n" -" //\n" -" free(int_array);\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/manual.md:21 -msgid "" -"Memory is leaked if the function returns early between `malloc` and `free`: " -"the pointer is lost and we cannot deallocate the memory. Worse, freeing the " -"pointer twice, or accessing a freed pointer can lead to exploitable security " -"vulnerabilities." -msgstr "" - -#: src/memory-management/scope-based.md:3 -msgid "" -"Constructors and destructors let you hook into the lifetime of an object." -msgstr "" - -#: src/memory-management/scope-based.md:5 -msgid "" -"By wrapping a pointer in an object, you can free memory when the object is " -"destroyed. The compiler guarantees that this happens, even if an exception " -"is raised." -msgstr "" - -#: src/memory-management/scope-based.md:9 -msgid "" -"This is often called _resource acquisition is initialization_ (RAII) and " -"gives you smart pointers." -msgstr "" - -#: src/memory-management/scope-based.md:12 -msgid "C++ Example" -msgstr "" - -#: src/memory-management/scope-based.md:14 -msgid "" -"```c++\n" -"void say_hello(std::unique_ptr person) {\n" -" std::cout << \"Hello \" << person->name << std::endl;\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/scope-based.md:20 -msgid "" -"The `std::unique_ptr` object is allocated on the stack, and points to memory " -"allocated on the heap." -msgstr "" - -#: src/memory-management/scope-based.md:22 -msgid "At the end of `say_hello`, the `std::unique_ptr` destructor will run." -msgstr "" - -#: src/memory-management/scope-based.md:23 -msgid "The destructor frees the `Person` object it points to." -msgstr "" - -#: src/memory-management/scope-based.md:25 -msgid "" -"Special move constructors are used when passing ownership to a function:" -msgstr "" - -#: src/memory-management/scope-based.md:27 -msgid "" -"```c++\n" -"std::unique_ptr person = find_person(\"Carla\");\n" -"say_hello(std::move(person));\n" -"```" -msgstr "" - -#: src/memory-management/garbage-collection.md:1 -msgid "Automatic Memory Management" -msgstr "" - -#: src/memory-management/garbage-collection.md:3 -msgid "" -"An alternative to manual and scope-based memory management is automatic " -"memory management:" -msgstr "" - -#: src/memory-management/garbage-collection.md:6 -msgid "The programmer never allocates or deallocates memory explicitly." -msgstr "" - -#: src/memory-management/garbage-collection.md:7 -msgid "" -"A garbage collector finds unused memory and deallocates it for the " -"programmer." -msgstr "" - -#: src/memory-management/garbage-collection.md:9 -msgid "Java Example" -msgstr "" - -#: src/memory-management/garbage-collection.md:11 -msgid "The `person` object is not deallocated after `sayHello` returns:" -msgstr "" - -#: src/memory-management/garbage-collection.md:13 -msgid "" -"```java\n" -"void sayHello(Person person) {\n" -" System.out.println(\"Hello \" + person.getName());\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/rust.md:1 -msgid "Memory Management in Rust" -msgstr "" - -#: src/memory-management/rust.md:3 -msgid "Memory management in Rust is a mix:" -msgstr "" - -#: src/memory-management/rust.md:5 -msgid "Safe and correct like Java, but without a garbage collector." -msgstr "" - -#: src/memory-management/rust.md:6 -msgid "" -"Depending on which abstraction (or combination of abstractions) you choose, " -"can be a single unique pointer, reference counted, or atomically reference " -"counted." -msgstr "" - -#: src/memory-management/rust.md:7 -msgid "Scope-based like C++, but the compiler enforces full adherence." -msgstr "" - -#: src/memory-management/rust.md:8 -msgid "" -"A Rust user can choose the right abstraction for the situation, some even " -"have no cost at runtime like C." -msgstr "" - -#: src/memory-management/rust.md:10 -msgid "Rust achieves this by modeling _ownership_ explicitly." -msgstr "" - -#: src/memory-management/rust.md:14 -msgid "" -"If asked how at this point, you can mention that in Rust this is usually " -"handled by RAII wrapper types such as [Box](https://doc.rust-lang.org/std/" -"boxed/struct.Box.html), [Vec](https://doc.rust-lang.org/std/vec/struct.Vec." -"html), [Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html), or [Arc]" -"(https://doc.rust-lang.org/std/sync/struct.Arc.html). These encapsulate " -"ownership and memory allocation via various means, and prevent the potential " -"errors in C." -msgstr "" - -#: src/memory-management/rust.md:16 -msgid "" -"You may be asked about destructors here, the [Drop](https://doc.rust-lang." -"org/std/ops/trait.Drop.html) trait is the Rust equivalent." -msgstr "" - -#: src/memory-management/comparison.md:3 -msgid "Here is a rough comparison of the memory management techniques." -msgstr "" - -#: src/memory-management/comparison.md:5 -msgid "Pros of Different Memory Management Techniques" -msgstr "" - -#: src/memory-management/comparison.md:7 src/memory-management/comparison.md:22 -msgid "Manual like C:" -msgstr "" - -#: src/memory-management/comparison.md:8 src/memory-management/comparison.md:14 -#: src/memory-management/comparison.md:17 -msgid "No runtime overhead." -msgstr "" - -#: src/memory-management/comparison.md:9 src/memory-management/comparison.md:26 -msgid "Automatic like Java:" -msgstr "" - -#: src/memory-management/comparison.md:10 -msgid "Fully automatic." -msgstr "" - -#: src/memory-management/comparison.md:11 -#: src/memory-management/comparison.md:18 -msgid "Safe and correct." -msgstr "" - -#: src/memory-management/comparison.md:12 -#: src/memory-management/comparison.md:29 -msgid "Scope-based like C++:" -msgstr "" - -#: src/memory-management/comparison.md:13 -msgid "Partially automatic." -msgstr "" - -#: src/memory-management/comparison.md:15 -msgid "Compiler-enforced scope-based like Rust:" -msgstr "" - -#: src/memory-management/comparison.md:16 -msgid "Enforced by compiler." -msgstr "" - -#: src/memory-management/comparison.md:20 -msgid "Cons of Different Memory Management Techniques" -msgstr "" - -#: src/memory-management/comparison.md:23 -msgid "Use-after-free." -msgstr "" - -#: src/memory-management/comparison.md:24 -msgid "Double-frees." -msgstr "" - -#: src/memory-management/comparison.md:25 -msgid "Memory leaks." -msgstr "" - -#: src/memory-management/comparison.md:27 -msgid "Garbage collection pauses." -msgstr "" - -#: src/memory-management/comparison.md:28 -msgid "Destructor delays." -msgstr "" - -#: src/memory-management/comparison.md:30 -msgid "Complex, opt-in by programmer (on C++)." -msgstr "" - -#: src/memory-management/comparison.md:31 -msgid "Circular references can lead to memory leaks" -msgstr "" - -#: src/memory-management/comparison.md:32 -msgid "Potential runtime overhead" -msgstr "" - -#: src/memory-management/comparison.md:33 -msgid "Compiler-enforced and scope-based like Rust:" -msgstr "" - -#: src/memory-management/comparison.md:34 -msgid "Some upfront complexity." -msgstr "" - -#: src/memory-management/comparison.md:35 -msgid "Can reject valid programs." -msgstr "" - -#: src/ownership.md:3 -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/ownership.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"struct Point(i32, i32);\n" -"\n" -"fn main() {\n" -" {\n" -" let p = Point(3, 4);\n" -" println!(\"x: {}\", p.0);\n" -" }\n" -" println!(\"y: {}\", p.1);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership.md:18 -msgid "" -"At the end of the scope, the variable is _dropped_ and the data is freed." -msgstr "" - -#: src/ownership.md:19 -msgid "A destructor can run here to free up resources." -msgstr "" - -#: src/ownership.md:20 -msgid "We say that the variable _owns_ the value." -msgstr "" - -#: src/ownership/move-semantics.md:3 -msgid "An assignment will transfer _ownership_ between variables:" -msgstr "" - -#: src/ownership/move-semantics.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1: String = String::from(\"Hello!\");\n" -" let s2: String = s1;\n" -" println!(\"s2: {s2}\");\n" -" // println!(\"s1: {s1}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/move-semantics.md:14 -msgid "The assignment of `s1` to `s2` transfers ownership." -msgstr "" - -#: src/ownership/move-semantics.md:15 -msgid "When `s1` goes out of scope, nothing happens: it does not own anything." -msgstr "" - -#: src/ownership/move-semantics.md:16 -msgid "When `s2` goes out of scope, the string data is freed." -msgstr "" - -#: src/ownership/move-semantics.md:17 -msgid "There is always _exactly_ one variable binding which owns a value." -msgstr "" - -#: src/ownership/move-semantics.md:21 -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/ownership/move-semantics.md:23 -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/ownership/move-semantics.md:25 -msgid "" -"Simple values (such as integers) can be marked `Copy` (see later slides)." -msgstr "" - -#: src/ownership/move-semantics.md:27 -msgid "In Rust, clones are explicit (by using `clone`)." -msgstr "" - -#: src/ownership/moved-strings-rust.md:3 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1: String = String::from(\"Rust\");\n" -" let s2: String = s1;\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/moved-strings-rust.md:10 -msgid "The heap data from `s1` is reused for `s2`." -msgstr "" - -#: src/ownership/moved-strings-rust.md:11 -msgid "When `s1` goes out of scope, nothing happens (it has been moved from)." -msgstr "" - -#: src/ownership/moved-strings-rust.md:13 -msgid "Before move to `s2`:" -msgstr "" - -#: src/ownership/moved-strings-rust.md:15 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| R | u | s | t | :\n" -": | len | 4 | : : +----+----+----+----+ :\n" -": | capacity | 4 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - -'\n" -": :\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/ownership/moved-strings-rust.md:30 -msgid "After move to `s2`:" -msgstr "" - -#: src/ownership/moved-strings-rust.md:32 -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" -"```" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:1 -msgid "Extra Work in Modern C++" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:3 -msgid "Modern C++ solves this differently:" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:5 -msgid "" -"```c++\n" -"std::string s1 = \"Cpp\";\n" -"std::string s2 = s1; // Duplicate the data in s1.\n" -"```" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:10 -msgid "" -"The heap data from `s1` is duplicated and `s2` gets its own independent copy." -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:11 -msgid "When `s1` and `s2` go out of scope, they each free their own memory." -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:13 -msgid "Before copy-assignment:" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:16 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:30 -msgid "After copy-assignment:" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:32 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : : :\n" -": s2 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+-----+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/ownership/moves-function-calls.md:3 -msgid "" -"When you pass a value to a function, the value is assigned to the function " -"parameter. This transfers ownership:" -msgstr "" - -#: src/ownership/moves-function-calls.md:6 -msgid "" -"```rust,editable\n" -"fn say_hello(name: String) {\n" -" println!(\"Hello {name}\")\n" -"}\n" -"\n" -"fn main() {\n" -" let name = String::from(\"Alice\");\n" -" say_hello(name);\n" -" // say_hello(name);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/moves-function-calls.md:20 -msgid "" -"With the first call to `say_hello`, `main` gives up ownership of `name`. " -"Afterwards, `name` cannot be used anymore within `main`." -msgstr "" - -#: src/ownership/moves-function-calls.md:21 -msgid "" -"The heap memory allocated for `name` will be freed at the end of the " -"`say_hello` function." -msgstr "" - -#: src/ownership/moves-function-calls.md:22 -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/ownership/moves-function-calls.md:23 -msgid "" -"Alternatively, `main` can pass a clone of `name` in the first call (`name." -"clone()`)." -msgstr "" - -#: src/ownership/moves-function-calls.md:24 -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/ownership/copy-clone.md:3 -msgid "" -"While move semantics are the default, certain types are copied by default:" -msgstr "" - -#: src/ownership/copy-clone.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let x = 42;\n" -" let y = x;\n" -" println!(\"x: {x}\");\n" -" println!(\"y: {y}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/copy-clone.md:14 -msgid "These types implement the `Copy` trait." -msgstr "" - -#: src/ownership/copy-clone.md:16 -msgid "You can opt-in your own types to use copy semantics:" -msgstr "" - -#: src/ownership/copy-clone.md:18 -msgid "" -"```rust,editable\n" -"#[derive(Copy, Clone, Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = p1;\n" -" println!(\"p1: {p1:?}\");\n" -" println!(\"p2: {p2:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/copy-clone.md:30 -msgid "After the assignment, both `p1` and `p2` own their own data." -msgstr "" - -#: src/ownership/copy-clone.md:31 -msgid "We can also use `p1.clone()` to explicitly copy the data." -msgstr "" - -#: src/ownership/copy-clone.md:35 -msgid "Copying and cloning are not the same thing:" -msgstr "" - -#: src/ownership/copy-clone.md:37 -msgid "" -"Copying refers to bitwise copies of memory regions and does not work on " -"arbitrary objects." -msgstr "" - -#: src/ownership/copy-clone.md:38 -msgid "" -"Copying does not allow for custom logic (unlike copy constructors in C++)." -msgstr "" - -#: src/ownership/copy-clone.md:39 -msgid "" -"Cloning is a more general operation and also allows for custom behavior by " -"implementing the `Clone` trait." -msgstr "" - -#: src/ownership/copy-clone.md:40 -msgid "Copying does not work on types that implement the `Drop` trait." -msgstr "" - -#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 -msgid "In the above example, try the following:" -msgstr "" - -#: src/ownership/copy-clone.md:44 -msgid "" -"Add a `String` field to `struct Point`. It will not compile because `String` " -"is not a `Copy` type." -msgstr "" - -#: src/ownership/copy-clone.md:45 -msgid "" -"Remove `Copy` from the `derive` attribute. The compiler error is now in the " -"`println!` for `p1`." -msgstr "" - -#: src/ownership/copy-clone.md:46 -msgid "Show that it works if you clone `p1` instead." -msgstr "" - -#: src/ownership/copy-clone.md:48 -msgid "" -"If students ask about `derive`, it is sufficient to say that this is a way " -"to generate code in Rust at compile time. In this case the default " -"implementations of `Copy` and `Clone` traits are generated." -msgstr "" - -#: src/ownership/borrowing.md:3 -msgid "" -"Instead of transferring ownership when calling a function, you can let a " -"function _borrow_ the value:" -msgstr "" - -#: src/ownership/borrowing.md:6 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn add(p1: &Point, p2: &Point) -> Point {\n" -" Point(p1.0 + p2.0, p1.1 + p2.1)\n" -"}\n" -"\n" -"fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" -" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/borrowing.md:22 -msgid "The `add` function _borrows_ two points and returns a new point." -msgstr "" - -#: src/ownership/borrowing.md:23 -msgid "The caller retains ownership of the inputs." -msgstr "" - -#: src/ownership/borrowing.md:27 -msgid "Notes on stack returns:" -msgstr "" - -#: src/ownership/borrowing.md:28 -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/) 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/ownership/borrowing.md:30 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn add(p1: &Point, p2: &Point) -> Point {\n" -" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" -" println!(\"&p.0: {:p}\", &p.0);\n" -" p\n" -"}\n" -"\n" -"pub fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" -" println!(\"&p3.0: {:p}\", &p3.0);\n" -" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/borrowing.md:48 -msgid "The Rust compiler can do return value optimization (RVO)." -msgstr "" - -#: src/ownership/borrowing.md:49 -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." -msgstr "" - -#: src/ownership/shared-unique-borrows.md:3 -msgid "Rust puts constraints on the ways you can borrow values:" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:5 -msgid "You can have one or more `&T` values at any given time, _or_" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:6 -msgid "You can have exactly one `&mut T` value." -msgstr "" - -#: src/ownership/shared-unique-borrows.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let mut a: i32 = 10;\n" -" let b: &i32 = &a;\n" -"\n" -" {\n" -" let c: &mut i32 = &mut a;\n" -" *c = 20;\n" -" }\n" -"\n" -" println!(\"a: {a}\");\n" -" println!(\"b: {b}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:25 -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/ownership/shared-unique-borrows.md:26 -msgid "" -"Move the `println!` statement for `b` before the scope that introduces `c` " -"to make the code compile." -msgstr "" - -#: src/ownership/shared-unique-borrows.md:27 -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/ownership/lifetimes.md:3 -msgid "A borrowed value has a _lifetime_:" -msgstr "" - -#: src/ownership/lifetimes.md:5 -msgid "The lifetime can be implicit: `add(p1: &Point, p2: &Point) -> Point`." -msgstr "" - -#: src/ownership/lifetimes.md:6 -msgid "Lifetimes can also be explicit: `&'a Point`, `&'document str`." -msgstr "" - -#: src/ownership/lifetimes.md:7 src/ownership/lifetimes-function-calls.md:23 -msgid "" -"Read `&'a Point` as \"a borrowed `Point` which is valid for at least the " -"lifetime `a`\"." -msgstr "" - -#: src/ownership/lifetimes.md:9 -msgid "" -"Lifetimes are always inferred by the compiler: you cannot assign a lifetime " -"yourself." -msgstr "" - -#: src/ownership/lifetimes.md:11 -msgid "" -"Lifetime annotations create constraints; the compiler verifies that there is " -"a valid solution." -msgstr "" - -#: src/ownership/lifetimes.md:13 -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)." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:3 -msgid "" -"In addition to borrowing its arguments, a function can return a borrowed " -"value:" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" -" if p1.0 < p2.0 { p1 } else { p2 }\n" -"}\n" -"\n" -"fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p2: Point = Point(20, 20);\n" -" let p3: &Point = left_most(&p1, &p2);\n" -" println!(\"left-most point: {:?}\", p3);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:21 -msgid "`'a` is a generic parameter, it is inferred by the compiler." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:22 -msgid "Lifetimes start with `'` and `'a` is a typical default name." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:25 -msgid "" -"The _at least_ part is important when parameters are in different scopes." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:31 -msgid "" -"Move the declaration of `p2` and `p3` into a new scope (`{ ... }`), " -"resulting in the following code:" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:32 -msgid "" -"```rust,ignore\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" -" if p1.0 < p2.0 { p1 } else { p2 }\n" -"}\n" -"\n" -"fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p3: &Point;\n" -" {\n" -" let p2: Point = Point(20, 20);\n" -" p3 = left_most(&p1, &p2);\n" -" }\n" -" println!(\"left-most point: {:?}\", p3);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:50 -msgid "Note how this does not compile since `p3` outlives `p2`." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:52 -msgid "" -"Reset the workspace and change the function signature to `fn left_most<'a, " -"'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " -"because the relationship between the lifetimes `'a` and `'b` is unclear." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:53 -msgid "Another way to explain it:" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:54 -msgid "" -"Two references to two values are borrowed by a function and the function " -"returns another reference." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:56 -msgid "" -"It must have come from one of those two inputs (or from a global variable)." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:57 -msgid "" -"Which one is it? The compiler needs to know, so at the call site the " -"returned reference is not used for longer than a variable from where the " -"reference came from." -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:3 -msgid "" -"If a data type stores borrowed data, it must be annotated with a lifetime:" -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Highlight<'doc>(&'doc str);\n" -"\n" -"fn erase(text: String) {\n" -" println!(\"Bye {text}!\");\n" -"}\n" -"\n" -"fn main() {\n" -" let text = String::from(\"The quick brown fox jumps over the lazy dog." -"\");\n" -" let fox = Highlight(&text[4..19]);\n" -" let dog = Highlight(&text[35..43]);\n" -" // erase(text);\n" -" println!(\"{fox:?}\");\n" -" println!(\"{dog:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:25 -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." -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:26 -msgid "" -"If `text` is consumed before the end of the lifetime of `fox` (or `dog`), " -"the borrow checker throws an error." -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:27 -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/ownership/lifetimes-data-structures.md:28 -msgid "When possible, make data structures own their data directly." -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:29 -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/exercises/day-1/afternoon.md:1 -msgid "Day 1: Afternoon Exercises" -msgstr "" - -#: src/exercises/day-1/afternoon.md:3 -msgid "We will look at two things:" -msgstr "" - -#: src/exercises/day-1/afternoon.md:5 -msgid "A small book library," -msgstr "" - -#: src/exercises/day-1/afternoon.md:7 -msgid "Iterators and ownership (hard)." -msgstr "" - -#: src/exercises/day-1/book-library.md:3 -msgid "" -"We will learn much more about structs and the `Vec` type tomorrow. For " -"now, you just need to know part of its API:" -msgstr "" - -#: src/exercises/day-1/book-library.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut vec = vec![10, 20];\n" -" vec.push(30);\n" -" let midpoint = vec.len() / 2;\n" -" println!(\"middle value: {}\", vec[midpoint]);\n" -" for item in &vec {\n" -" println!(\"item: {item}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/book-library.md:18 -msgid "" -"Use this to model a library's book collection. Copy the code below to " -" and update the types to make it compile:" -msgstr "" - -#: src/exercises/day-1/book-library.md:21 -msgid "" -"```rust,should_panic\n" -"struct Library {\n" -" books: Vec,\n" -"}\n" -"\n" -"struct Book {\n" -" title: String,\n" -" year: u16,\n" -"}\n" -"\n" -"impl Book {\n" -" // This is a constructor, used below.\n" -" fn new(title: &str, year: u16) -> Book {\n" -" Book {\n" -" title: String::from(title),\n" -" year,\n" -" }\n" -" }\n" -"}\n" -"\n" -"// Implement the methods below. Update the `self` parameter to\n" -"// indicate the method's required level of ownership over the object:\n" -"//\n" -"// - `&self` for shared read-only access,\n" -"// - `&mut self` for unique and mutable access,\n" -"// - `self` for unique access by value.\n" -"impl Library {\n" -" fn new() -> Library {\n" -" todo!(\"Initialize and return a `Library` value\")\n" -" }\n" -"\n" -" //fn len(self) -> usize {\n" -" // todo!(\"Return the length of `self.books`\")\n" -" //}\n" -"\n" -" //fn is_empty(self) -> bool {\n" -" // todo!(\"Return `true` if `self.books` is empty\")\n" -" //}\n" -"\n" -" //fn add_book(self, book: Book) {\n" -" // todo!(\"Add a new book to `self.books`\")\n" -" //}\n" -"\n" -" //fn print_books(self) {\n" -" // todo!(\"Iterate over `self.books` and each book's title and " -"year\")\n" -" //}\n" -"\n" -" //fn oldest_book(self) -> Option<&Book> {\n" -" // todo!(\"Return a reference to the oldest book (if any)\")\n" -" //}\n" -"}\n" -"\n" -"// This shows the desired behavior. Uncomment the code below and\n" -"// implement the missing methods. You will need to update the\n" -"// method signatures, including the \"self\" parameter! You may\n" -"// also need to update the variable bindings within main.\n" -"fn main() {\n" -" let library = Library::new();\n" -"\n" -" //println!(\"The library is empty: library.is_empty() -> {}\", library." -"is_empty());\n" -" //\n" -" //library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " -"1865));\n" -" //\n" -" //println!(\"The library is no longer empty: library.is_empty() -> {}\", " -"library.is_empty());\n" -" //\n" -" //\n" -" //library.print_books();\n" -" //\n" -" //match library.oldest_book() {\n" -" // Some(book) => println!(\"The oldest book is {}\", book.title),\n" -" // None => println!(\"The library is empty!\"),\n" -" //}\n" -" //\n" -" //println!(\"The library has {} books\", library.len());\n" -" //library.print_books();\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/book-library.md:102 -msgid "[Solution](solutions-afternoon.md#designing-a-library)" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:3 -msgid "" -"The ownership model of Rust affects many APIs. An example of this is the " -"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and " -"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html) " -"traits." -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:8 src/bare-metal/no_std.md:28 -msgid "`Iterator`" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:10 -msgid "" -"Traits are like interfaces: they describe behavior (methods) for a type. The " -"`Iterator` trait simply says that you can call `next` until you get `None` " -"back:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:13 -msgid "" -"```rust\n" -"pub trait Iterator {\n" -" type Item;\n" -" fn next(&mut self) -> Option;\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:20 -msgid "You use this trait like this:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:22 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();\n" -"\n" -" println!(\"v[0]: {:?}\", iter.next());\n" -" println!(\"v[1]: {:?}\", iter.next());\n" -" println!(\"v[2]: {:?}\", iter.next());\n" -" println!(\"No more items: {:?}\", iter.next());\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:34 -msgid "What is the type returned by the iterator? Test your answer here:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:36 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();\n" -"\n" -" let v0: Option<..> = iter.next();\n" -" println!(\"v0: {v0:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:46 -msgid "Why is this type used?" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:48 -msgid "`IntoIterator`" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:50 -msgid "" -"The `Iterator` trait tells you how to _iterate_ once you have created an " -"iterator. The related trait `IntoIterator` tells you how to create the " -"iterator:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:53 -msgid "" -"```rust\n" -"pub trait IntoIterator {\n" -" type Item;\n" -" type IntoIter: Iterator;\n" -"\n" -" fn into_iter(self) -> Self::IntoIter;\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:62 -msgid "" -"The syntax here means that every implementation of `IntoIterator` must " -"declare two types:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:65 -msgid "`Item`: the type we iterate over, such as `i8`," -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:66 -msgid "`IntoIter`: the `Iterator` type returned by the `into_iter` method." -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:68 -msgid "" -"Note that `IntoIter` and `Item` are linked: the iterator must have the same " -"`Item` type, which means that it returns `Option`" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:71 -msgid "Like before, what is the type returned by the iterator?" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:73 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::" -"from(\"bar\")];\n" -" let mut iter = v.into_iter();\n" -"\n" -" let v0: Option<..> = iter.next();\n" -" println!(\"v0: {v0:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:83 -msgid "`for` Loops" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:85 -msgid "" -"Now that we know both `Iterator` and `IntoIterator`, we can build `for` " -"loops. They call `into_iter()` on an expression and iterates over the " -"resulting iterator:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:89 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::" -"from(\"bar\")];\n" -"\n" -" for word in &v {\n" -" println!(\"word: {word}\");\n" -" }\n" -"\n" -" for word in v {\n" -" println!(\"word: {word}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:103 -msgid "What is the type of `word` in each loop?" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:105 -msgid "" -"Experiment with the code above and then consult the documentation for [`impl " -"IntoIterator for &Vec`](https://doc.rust-lang.org/std/vec/struct.Vec." -"html#impl-IntoIterator-for-%26'a+Vec%3CT,+A%3E) and [`impl IntoIterator for " -"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-" -"for-Vec%3CT,+A%3E) to check your answers." -msgstr "" - -#: src/welcome-day-2.md:1 -msgid "Welcome to Day 2" -msgstr "" - -#: src/welcome-day-2.md:3 -msgid "Now that we have seen a fair amount of Rust, we will continue with:" -msgstr "" - -#: src/welcome-day-2.md:5 -msgid "Structs, enums, methods." -msgstr "" - -#: src/welcome-day-2.md:7 -msgid "Pattern matching: destructuring enums, structs, and arrays." -msgstr "" - -#: src/welcome-day-2.md:9 -msgid "" -"Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and " -"`continue`." -msgstr "" - -#: src/welcome-day-2.md:12 -msgid "" -"The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, " -"`Rc` and `Arc`." -msgstr "" - -#: src/welcome-day-2.md:15 -msgid "Modules: visibility, paths, and filesystem hierarchy." -msgstr "" - -#: src/structs.md:3 -msgid "Like C and C++, Rust has support for custom structs:" -msgstr "" - -#: src/structs.md:5 -msgid "" -"```rust,editable\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"\n" -"fn main() {\n" -" let mut peter = Person {\n" -" name: String::from(\"Peter\"),\n" -" age: 27,\n" -" };\n" -" println!(\"{} is {} years old\", peter.name, peter.age);\n" -" \n" -" peter.age = 28;\n" -" println!(\"{} is {} years old\", peter.name, peter.age);\n" -" \n" -" let jackie = Person {\n" -" name: String::from(\"Jackie\"),\n" -" ..peter\n" -" };\n" -" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" -"}\n" -"```" -msgstr "" - -#: src/structs.md:31 src/enums.md:34 src/enums/sizes.md:28 src/methods.md:30 -#: src/methods/example.md:46 src/pattern-matching.md:25 -#: src/pattern-matching/match-guards.md:22 src/control-flow/blocks.md:43 -msgid "Key Points:" -msgstr "" - -#: src/structs.md:33 -msgid "Structs work like in C or C++." -msgstr "" - -#: src/structs.md:34 -msgid "Like in C++, and unlike in C, no typedef is needed to define a type." -msgstr "" - -#: src/structs.md:35 -msgid "Unlike in C++, there is no inheritance between structs." -msgstr "" - -#: src/structs.md:36 -msgid "" -"Methods are defined in an `impl` block, which we will see in following " -"slides." -msgstr "" - -#: src/structs.md:37 -msgid "" -"This may be a good time to let people know there are different types of " -"structs. " -msgstr "" - -#: src/structs.md:38 -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/structs.md:39 -msgid "" -"The next slide will introduce Tuple structs, used when the field names are " -"not important." -msgstr "" - -#: src/structs.md:40 -msgid "" -"The syntax `..peter` 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/structs/tuple-structs.md:3 -msgid "If the field names are unimportant, you can use a tuple struct:" -msgstr "" - -#: src/structs/tuple-structs.md:5 -msgid "" -"```rust,editable\n" -"struct Point(i32, i32);\n" -"\n" -"fn main() {\n" -" let p = Point(17, 23);\n" -" println!(\"({}, {})\", p.0, p.1);\n" -"}\n" -"```" -msgstr "" - -#: src/structs/tuple-structs.md:14 -msgid "This is often used for single-field wrappers (called newtypes):" -msgstr "" - -#: src/structs/tuple-structs.md:16 -msgid "" -"```rust,editable,compile_fail\n" -"struct PoundsOfForce(f64);\n" -"struct Newtons(f64);\n" -"\n" -"fn compute_thruster_force() -> PoundsOfForce {\n" -" todo!(\"Ask a rocket scientist at NASA\")\n" -"}\n" -"\n" -"fn set_thruster_force(force: Newtons) {\n" -" // ...\n" -"}\n" -"\n" -"fn main() {\n" -" let force = compute_thruster_force();\n" -" set_thruster_force(force);\n" -"}\n" -"\n" -"```" -msgstr "" - -#: src/structs/tuple-structs.md:37 -msgid "" -"Newtypes are a great way to encode additional information about the value in " -"a primitive type, for example:" -msgstr "" - -#: src/structs/tuple-structs.md:38 -msgid "The number is measured in some units: `Newtons` in the example above." -msgstr "" - -#: src/structs/tuple-structs.md:39 -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/structs/tuple-structs.md:40 -msgid "" -"Demonstrate how to add a `f64` value to a `Newtons` type by accessing the " -"single field in the newtype." -msgstr "" - -#: src/structs/tuple-structs.md:41 -msgid "" -"Rust generally doesn’t like inexplicit things, like automatic unwrapping or " -"for instance using booleans as integers." -msgstr "" - -#: src/structs/tuple-structs.md:42 -msgid "Operator overloading is discussed on Day 3 (generics)." -msgstr "" - -#: src/structs/tuple-structs.md:43 -msgid "" -"The example is a subtle reference to the [Mars Climate Orbiter](https://en." -"wikipedia.org/wiki/Mars_Climate_Orbiter) failure." -msgstr "" - -#: src/structs/field-shorthand.md:3 -msgid "" -"If you already have variables with the right names, then you can create the " -"struct using a shorthand:" -msgstr "" - -#: src/structs/field-shorthand.md:6 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"\n" -"impl Person {\n" -" fn new(name: String, age: u8) -> Person {\n" -" Person { name, age }\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let peter = Person::new(String::from(\"Peter\"), 27);\n" -" println!(\"{peter:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/structs/field-shorthand.md:27 -msgid "" -"The `new` function could be written using `Self` as a type, as it is " -"interchangeable with the struct type name" -msgstr "" - -#: src/structs/field-shorthand.md:29 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"impl Person {\n" -" fn new(name: String, age: u8) -> Self {\n" -" Self { name, age }\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/structs/field-shorthand.md:41 -msgid "" -"Implement the `Default` trait for the struct. Define some fields and use the " -"default values for the other fields." -msgstr "" - -#: src/structs/field-shorthand.md:43 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"impl Default for Person {\n" -" fn default() -> Person {\n" -" Person {\n" -" name: \"Bot\".to_string(),\n" -" age: 0,\n" -" }\n" -" }\n" -"}\n" -"fn create_default() {\n" -" let tmp = Person {\n" -" ..Person::default()\n" -" };\n" -" let tmp = Person {\n" -" name: \"Sam\".to_string(),\n" -" ..Person::default()\n" -" };\n" -"}\n" -"```" -msgstr "" - -#: src/structs/field-shorthand.md:68 -msgid "Methods are defined in the `impl` block." -msgstr "" - -#: src/structs/field-shorthand.md:69 -msgid "" -"Use struct update syntax to define a new structure using `peter`. Note that " -"the variable `peter` will no longer be accessible afterwards." -msgstr "" - -#: src/structs/field-shorthand.md:70 -msgid "" -"Use `{:#?}` when printing structs to request the `Debug` representation." -msgstr "" - #: src/enums.md:3 msgid "" "The `enum` keyword allows the creation of a type which has a few different " @@ -5946,381 +4289,232 @@ msgid "" "You can control the discriminant if needed (e.g., for compatibility with C):" msgstr "" -#: src/enums/sizes.md:34 -msgid "" -"```rust,editable\n" -"#[repr(u32)]\n" -"enum Bar {\n" -" A, // 0\n" -" B = 10000,\n" -" C, // 10001\n" -"}\n" -"\n" -"fn main() {\n" -" println!(\"A: {}\", Bar::A as u32);\n" -" println!(\"B: {}\", Bar::B as u32);\n" -" println!(\"C: {}\", Bar::C as u32);\n" -"}\n" -"```" -msgstr "" - -#: src/enums/sizes.md:49 +#: src/enums/sizes.md:50 msgid "" "Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2 " "bytes." msgstr "" -#: src/enums/sizes.md:53 +#: src/enums/sizes.md:54 msgid "Try out other types such as" msgstr "" -#: src/enums/sizes.md:55 +#: src/enums/sizes.md:56 msgid "`dbg_size!(bool)`: size 1 bytes, align: 1 bytes," msgstr "" -#: src/enums/sizes.md:56 +#: src/enums/sizes.md:57 msgid "" "`dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche optimization, " "see below)," msgstr "" -#: src/enums/sizes.md:57 +#: src/enums/sizes.md:58 msgid "`dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit machine)," msgstr "" -#: src/enums/sizes.md:58 +#: src/enums/sizes.md:59 msgid "" "`dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer " "optimization, see below)." msgstr "" -#: src/enums/sizes.md:60 +#: src/enums/sizes.md:61 src/memory-management/stack.md:32 +msgid "More to Explore" +msgstr "" + +#: src/enums/sizes.md:63 +msgid "" +"Rust has several optimizations it can employ to make enums take up less " +"space." +msgstr "" + +#: src/enums/sizes.md:65 msgid "" "Niche optimization: Rust will merge unused bit patterns for the enum " "discriminant." msgstr "" -#: src/enums/sizes.md:63 +#: src/enums/sizes.md:68 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/enums/sizes.md:67 +#: src/enums/sizes.md:72 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/enums/sizes.md:70 -msgid "" -"```rust,editable\n" -"use std::mem::transmute;\n" -"\n" -"macro_rules! dbg_bits {\n" -" ($e:expr, $bit_type:ty) => {\n" -" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, " -"$bit_type>($e));\n" -" };\n" -"}\n" -"\n" -"fn main() {\n" -" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" -" // representation of types.\n" -" unsafe {\n" -" println!(\"Bitwise representation of bool\");\n" -" dbg_bits!(false, u8);\n" -" dbg_bits!(true, u8);\n" -"\n" -" println!(\"Bitwise representation of Option\");\n" -" dbg_bits!(None::, u8);\n" -" dbg_bits!(Some(false), u8);\n" -" dbg_bits!(Some(true), u8);\n" -"\n" -" println!(\"Bitwise representation of Option>\");\n" -" dbg_bits!(Some(Some(false)), u8);\n" -" dbg_bits!(Some(Some(true)), u8);\n" -" dbg_bits!(Some(None::), u8);\n" -" dbg_bits!(None::>, u8);\n" -"\n" -" println!(\"Bitwise representation of Option<&i32>\");\n" -" dbg_bits!(None::<&i32>, usize);\n" -" dbg_bits!(Some(&0i32), usize);\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/enums/sizes.md:105 +#: src/enums/sizes.md:109 msgid "" "More complex example if you want to discuss what happens when we chain more " "than 256 `Option`s together." msgstr "" -#: src/enums/sizes.md:107 +#: src/control-flow/novel.md:3 +msgid "" +"Rust has a few control flow constructs which differ from other languages. " +"They are used for pattern matching:" +msgstr "" + +#: src/control-flow/novel.md:6 src/control-flow/if-let-expressions.md:1 +msgid "`if let` expressions" +msgstr "" + +#: src/control-flow/novel.md:7 +#, fuzzy +msgid "`while let` expressions" +msgstr "عبارت while let" + +#: src/control-flow/novel.md:8 src/control-flow/match-expressions.md:1 +msgid "`match` expressions" +msgstr "" + +#: src/control-flow/if-let-expressions.md:3 +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/control-flow/if-let-expressions.md:7 msgid "" "```rust,editable\n" -"#![recursion_limit = \"1000\"]\n" -"\n" -"use std::mem::transmute;\n" -"\n" -"macro_rules! dbg_bits {\n" -" ($e:expr, $bit_type:ty) => {\n" -" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, " -"$bit_type>($e));\n" -" };\n" -"}\n" -"\n" -"// Macro to wrap a value in 2^n Some() where n is the number of \"@\" " -"signs.\n" -"// Increasing the recursion limit is required to evaluate this macro.\n" -"macro_rules! many_options {\n" -" ($value:expr) => { Some($value) };\n" -" ($value:expr, @) => {\n" -" Some(Some($value))\n" -" };\n" -" ($value:expr, @ $($more:tt)+) => {\n" -" many_options!(many_options!($value, $($more)+), $($more)+)\n" -" };\n" -"}\n" -"\n" "fn main() {\n" -" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" -" // representation of types.\n" -" unsafe {\n" -" assert_eq!(many_options!(false), Some(false));\n" -" assert_eq!(many_options!(false, @), Some(Some(false)));\n" -" assert_eq!(many_options!(false, @@), " -"Some(Some(Some(Some(false)))));\n" -"\n" -" println!(\"Bitwise representation of a chain of 128 Option's.\");\n" -" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" -" dbg_bits!(many_options!(true, @@@@@@@), u8);\n" -"\n" -" println!(\"Bitwise representation of a chain of 256 Option's.\");\n" -" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(true, @@@@@@@@), u16);\n" -"\n" -" println!(\"Bitwise representation of a chain of 257 Option's.\");\n" -" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" +" let arg = std::env::args().next();\n" +" if let Some(value) = arg {\n" +" println!(\"Program name: {value}\");\n" +" } else {\n" +" println!(\"Missing name?\");\n" " }\n" "}\n" "```" msgstr "" -#: src/methods.md:3 +#: src/control-flow/if-let-expressions.md:18 +#: src/control-flow/while-let-expressions.md:22 +#: src/control-flow/match-expressions.md:23 msgid "" -"Rust allows you to associate functions with your new types. You do this with " -"an `impl` block:" +"See [pattern matching](../pattern-matching.md) for more details on patterns " +"in Rust." msgstr "" -#: src/methods.md:6 +#: src/control-flow/if-let-expressions.md:23 +msgid "" +"Unlike `match`, `if let` does not have to cover all branches. This can make " +"it more concise than `match`." +msgstr "" + +#: src/control-flow/if-let-expressions.md:24 +msgid "A common usage is handling `Some` values when working with `Option`." +msgstr "" + +#: src/control-flow/if-let-expressions.md:25 +msgid "" +"Unlike `match`, `if let` does not support guard clauses for pattern matching." +msgstr "" + +#: src/control-flow/if-let-expressions.md:26 +msgid "" +"Since 1.65, a similar [let-else](https://doc.rust-lang.org/rust-by-example/" +"flow_control/let_else.html) construct allows to do a destructuring " +"assignment, or if it fails, execute a block which is required to abort " +"normal control flow (with `panic`/`return`/`break`/`continue`):" +msgstr "" + +#: src/control-flow/while-let-expressions.md:1 +msgid "`while let` loops" +msgstr "" + +#: src/control-flow/while-let-expressions.md:3 +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:" +msgstr "" + +#: src/control-flow/while-let-expressions.md:18 +msgid "" +"Here the iterator returned by `v.into_iter()` will return a `Option` on " +"every call to `next()`. It returns `Some(x)` until it is done, after which " +"it will return `None`. The `while let` lets us keep iterating through all " +"items." +msgstr "" + +#: src/control-flow/while-let-expressions.md:27 +msgid "" +"Point out that the `while let` loop will keep going as long as the value " +"matches the pattern." +msgstr "" + +#: src/control-flow/while-let-expressions.md:28 +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 `iter.next()`. " +"The `while let` provides syntactic sugar for the above scenario." +msgstr "" + +#: src/control-flow/match-expressions.md:3 +msgid "" +"The [`match` keyword](https://doc.rust-lang.org/reference/expressions/match-" +"expr.html) is used to match a value against one or more patterns. In that " +"sense, it works like a series of `if let` expressions:" +msgstr "" + +#: src/control-flow/match-expressions.md:7 msgid "" "```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"\n" -"impl Person {\n" -" fn say_hello(&self) {\n" -" println!(\"Hello, my name is {}\", self.name);\n" -" }\n" -"}\n" -"\n" "fn main() {\n" -" let peter = Person {\n" -" name: String::from(\"Peter\"),\n" -" age: 27,\n" -" };\n" -" peter.say_hello();\n" +" match std::env::args().next().as_deref() {\n" +" Some(\"cat\") => println!(\"Will do cat things\"),\n" +" Some(\"ls\") => println!(\"Will ls some files\"),\n" +" Some(\"mv\") => println!(\"Let's move some files\"),\n" +" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" +" None => println!(\"Hmm, no program name?\"),\n" +" _ => println!(\"Unknown program name!\"),\n" +" }\n" "}\n" "```" msgstr "" -#: src/methods.md:31 -msgid "It can be helpful to introduce methods by comparing them to functions." -msgstr "" - -#: src/methods.md:32 +#: src/control-flow/match-expressions.md:20 msgid "" -"Methods are called on an instance of a type (such as a struct or enum), the " -"first parameter represents the instance as `self`." +"Like `if let`, 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 `()`." msgstr "" -#: src/methods.md:33 +#: src/control-flow/match-expressions.md:28 +msgid "Save the match expression to a variable and print it out." +msgstr "" + +#: src/control-flow/match-expressions.md:29 +msgid "Remove `.as_deref()` and explain the error." +msgstr "" + +#: src/control-flow/match-expressions.md:30 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." +"`std::env::args().next()` returns an `Option`, but we cannot match " +"against `String`." msgstr "" -#: src/methods.md:34 -msgid "Point out the use of the keyword `self`, a method receiver." -msgstr "" - -#: src/methods.md:35 +#: src/control-flow/match-expressions.md:31 msgid "" -"Show that it is an abbreviated term for `self: Self` and perhaps show how " -"the struct name could also be used." +"`as_deref()` transforms an `Option` to `Option<&T::Target>`. In our case, " +"this turns `Option` into `Option<&str>`." msgstr "" -#: src/methods.md:36 +#: src/control-flow/match-expressions.md:32 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.md:37 -msgid "" -"Note how `self` is used like other structs and dot notation can be used to " -"refer to individual fields." -msgstr "" - -#: src/methods.md:38 -msgid "" -"This might be a good time to demonstrate how the `&self` differs from `self` " -"by modifying the code and trying to run say_hello twice." -msgstr "" - -#: src/methods.md:39 -msgid "We describe the distinction between method receivers next." -msgstr "" - -#: src/methods/receiver.md:3 -msgid "" -"The `&self` above indicates that the method borrows the object immutably. " -"There are other possible receivers for a method:" -msgstr "" - -#: src/methods/receiver.md:6 -msgid "" -"`&self`: borrows the object from the caller using a shared and immutable " -"reference. The object can be used again afterwards." -msgstr "" - -#: src/methods/receiver.md:8 -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/receiver.md:10 -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/receiver.md:14 -msgid "`mut self`: same as above, but the method can mutate the object. " -msgstr "" - -#: src/methods/receiver.md:15 -msgid "" -"No receiver: this becomes a static method on the struct. Typically used to " -"create constructors which are called `new` by convention." -msgstr "" - -#: src/methods/receiver.md:18 -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/receiver.md:24 -msgid "" -"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". " -"These constraints always come together in Rust due to borrow checker rules, " -"and `self` is no exception. It isn't possible to reference a struct from " -"multiple locations and call a mutating (`&mut self`) method on it." -msgstr "" - -#: src/methods/example.md:3 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Race {\n" -" name: String,\n" -" laps: Vec,\n" -"}\n" -"\n" -"impl Race {\n" -" fn new(name: &str) -> Race { // No receiver, a static method\n" -" Race { name: String::from(name), laps: Vec::new() }\n" -" }\n" -"\n" -" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write " -"access to self\n" -" self.laps.push(lap);\n" -" }\n" -"\n" -" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" -" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" -" for (idx, lap) in self.laps.iter().enumerate() {\n" -" println!(\"Lap {idx}: {lap} sec\");\n" -" }\n" -" }\n" -"\n" -" fn finish(self) { // Exclusive ownership of self\n" -" let total = self.laps.iter().sum::();\n" -" println!(\"Race {} is finished, total lap time: {}\", self.name, " -"total);\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let mut race = Race::new(\"Monaco Grand Prix\");\n" -" race.add_lap(70);\n" -" race.add_lap(68);\n" -" race.print_laps();\n" -" race.add_lap(71);\n" -" race.print_laps();\n" -" race.finish();\n" -" // race.add_lap(42);\n" -"}\n" -"```" -msgstr "" - -#: src/methods/example.md:47 -msgid "All four methods here use a different method receiver." -msgstr "" - -#: src/methods/example.md:48 -msgid "" -"You can point out how that changes what the function can do with the " -"variable values and if/how it can be used again in `main`." -msgstr "" - -#: src/methods/example.md:49 -msgid "" -"You can showcase the error that appears when trying to call `finish` twice." -msgstr "" - -#: src/methods/example.md:50 -msgid "" -"Note that although the method receivers are different, the non-static " -"functions are called the same way in the main body. Rust enables automatic " -"referencing and dereferencing when calling methods. Rust automatically adds " -"in the `&`, `*`, `muts` so that that object matches the method signature." -msgstr "" - -#: src/methods/example.md:51 -msgid "" -"You might point out that `print_laps` is using a vector that is iterated " -"over. We describe vectors in more detail in the afternoon. " +"We can now use pattern matching to match against the `&str` inside `Option`." msgstr "" #: src/pattern-matching.md:3 msgid "" -"The `match` keyword let you match a value against one or more _patterns_. " +"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." msgstr "" @@ -6592,6 +4786,1559 @@ msgid "" "with an `|`." msgstr "" +#: src/exercises/day-1/afternoon.md:1 +msgid "Day 1: Afternoon Exercises" +msgstr "" + +#: src/exercises/day-1/afternoon.md:3 +msgid "We will look at two things:" +msgstr "" + +#: src/exercises/day-1/afternoon.md:5 +#, fuzzy +msgid "The Luhn algorithm," +msgstr "الگوریتم Luhn" + +#: src/exercises/day-1/afternoon.md:7 +msgid "An exercise on pattern matching." +msgstr "" + +#: src/exercises/day-1/afternoon.md:11 src/exercises/day-2/afternoon.md:7 +#: src/exercises/bare-metal/afternoon.md:7 +#: src/exercises/concurrency/afternoon.md:13 +msgid "" +"After looking at the exercises, you can look at the [solutions](solutions-" +"afternoon.md) provided." +msgstr "" + +#: src/exercises/day-1/luhn.md:3 +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/exercises/day-1/luhn.md:7 +msgid "Ignore all spaces. Reject number with less than two digits." +msgstr "" + +#: src/exercises/day-1/luhn.md:9 +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/exercises/day-1/luhn.md:12 +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/exercises/day-1/luhn.md:15 +msgid "Sum all the undoubled and doubled digits." +msgstr "" + +#: src/exercises/day-1/luhn.md:17 +msgid "The credit card number is valid if the sum ends with `0`." +msgstr "" + +#: src/exercises/day-1/luhn.md:19 +msgid "" +"Copy the code below to and implement the " +"function." +msgstr "" + +#: src/exercises/day-1/luhn.md:21 +msgid "" +"Try to solve the problem the \"simple\" way first, using `for` loops and " +"integers. Then, revisit the solution and try to implement it with iterators." +msgstr "" + +#: src/exercises/day-1/luhn.md:25 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +" assert!(!luhn(\"foo 0 0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:1 +msgid "Exercise: Expression Evaluation" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:3 +msgid "Let's write a simple recursive evaluator for arithmetic expressions. " +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:5 +msgid "" +"```rust\n" +"/// An operation to perform on two subexpressions.\n" +"#[derive(Debug)]\n" +"enum Operation {\n" +" Add,\n" +" Sub,\n" +" Mul,\n" +" Div,\n" +"}\n" +"\n" +"/// An expression, in tree form.\n" +"#[derive(Debug)]\n" +"enum Expression {\n" +" /// An operation on two subexpressions.\n" +" Op {\n" +" op: Operation,\n" +" left: Box,\n" +" right: Box,\n" +" },\n" +"\n" +" /// A literal value\n" +" Value(i64),\n" +"}\n" +"\n" +"/// The result of evaluating an expression.\n" +"#[derive(Debug, PartialEq, Eq)]\n" +"enum Res {\n" +" /// Evaluation was successful, with the given result.\n" +" Ok(i64),\n" +" /// Evaluation failed, with the given error message.\n" +" Err(String),\n" +"}\n" +"// Allow `Ok` and `Err` as shorthands for `Res::Ok` and `Res::Err`.\n" +"use Res::{Err, Ok};\n" +"\n" +"fn eval(e: Expression) -> Res {\n" +" todo!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_value() {\n" +" assert_eq!(eval(Expression::Value(19)), Ok(19));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_sum() {\n" +" assert_eq!(\n" +" eval(Expression::Op {\n" +" op: Operation::Add,\n" +" left: Box::new(Expression::Value(10)),\n" +" right: Box::new(Expression::Value(20)),\n" +" }),\n" +" Ok(30)\n" +" );\n" +"}\n" +"\n" +"#[test]\n" +"fn test_recursion() {\n" +" let term1 = Expression::Op {\n" +" op: Operation::Mul,\n" +" left: Box::new(Expression::Value(10)),\n" +" right: Box::new(Expression::Value(9)),\n" +" };\n" +" let term2 = Expression::Op {\n" +" op: Operation::Mul,\n" +" left: Box::new(Expression::Op {\n" +" op: Operation::Sub,\n" +" left: Box::new(Expression::Value(3)),\n" +" right: Box::new(Expression::Value(4)),\n" +" }),\n" +" right: Box::new(Expression::Value(5)),\n" +" };\n" +" assert_eq!(\n" +" eval(Expression::Op {\n" +" op: Operation::Add,\n" +" left: Box::new(term1),\n" +" right: Box::new(term2),\n" +" }),\n" +" Ok(85)\n" +" );\n" +"}\n" +"\n" +"#[test]\n" +"fn test_error() {\n" +" assert_eq!(\n" +" eval(Expression::Op {\n" +" op: Operation::Div,\n" +" left: Box::new(Expression::Value(99)),\n" +" right: Box::new(Expression::Value(0)),\n" +" }),\n" +" Err(String::from(\"division by zero\"))\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:100 +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/exercises/day-1/pattern-matching.md:105 +msgid "" +"Some expressions cannot be evaluated and will return an error. The `Res` " +"type represents either a successful value or an error with a message. This " +"is very similar to the standard-library `Result` which we will see later." +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:109 +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." +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:113 +msgid "" +"If you finish early, try writing a test that results in an integer overflow. " +"How could you handle this with `Res::Err` instead of a panic?" +msgstr "" + +#: src/welcome-day-2.md:1 +msgid "Welcome to Day 2" +msgstr "" + +#: src/welcome-day-2.md:3 +msgid "Now that we have seen a fair amount of Rust, we will continue with:" +msgstr "" + +#: src/welcome-day-2.md:5 +msgid "" +"Memory management: stack vs heap, manual memory management, scope-based " +"memory management, and garbage collection." +msgstr "" +"Memory management: stack vs heap, manual memory management, scope-based " +"memory management, و garbage collection." + +#: src/welcome-day-2.md:8 +msgid "" +"Ownership: move semantics, copying and cloning, borrowing, and lifetimes." +msgstr "Ownership: حرکت semantics،copying و cloning, borrowing و lifetimes." + +#: src/welcome-day-2.md:10 +#, fuzzy +msgid "Structs and methods." +msgstr "رشته ها و تکرار کننده‌ها (Strings and Iterators)" + +#: src/welcome-day-2.md:12 +msgid "" +"The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, " +"`Rc` and `Arc`." +msgstr "" + +#: src/welcome-day-2.md:15 +msgid "Modules: visibility, paths, and filesystem hierarchy." +msgstr "" + +#: src/memory-management.md:3 +msgid "Traditionally, languages have fallen into two broad categories:" +msgstr "" + +#: src/memory-management.md:5 +msgid "Full control via manual memory management: C, C++, Pascal, ..." +msgstr "" + +#: src/memory-management.md:6 +msgid "" +"Full safety via automatic memory management at runtime: Java, Python, Go, " +"Haskell, ..." +msgstr "" + +#: src/memory-management.md:8 +msgid "Rust offers a new mix:" +msgstr "" + +#: src/memory-management.md:10 +msgid "" +"Full control _and_ safety via compile time enforcement of correct memory " +"management." +msgstr "" + +#: src/memory-management.md:13 +msgid "It does this with an explicit ownership concept." +msgstr "" + +#: src/memory-management.md:15 +msgid "First, let's refresh how memory management works." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:1 +msgid "The Stack vs The Heap" +msgstr "" + +#: src/memory-management/stack-vs-heap.md:3 +msgid "Stack: Continuous area of memory for local variables." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:4 +msgid "Values have fixed sizes known at compile time." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:5 +msgid "Extremely fast: just move a stack pointer." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:6 +msgid "Easy to manage: follows function calls." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:7 +msgid "Great memory locality." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:9 +msgid "Heap: Storage of values outside of function calls." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:10 +msgid "Values have dynamic sizes determined at runtime." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:11 +msgid "Slightly slower than the stack: some book-keeping needed." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:12 +msgid "No guarantee of memory locality." +msgstr "" + +#: src/memory-management/stack.md:1 +msgid "Stack and Heap Example" +msgstr "" + +#: src/memory-management/stack.md:3 +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/stack.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1 = String::from(\"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:28 +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/stack.md:30 +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/stack.md:34 +msgid "" +"We can inspect the memory layout with `unsafe` Rust. However, you should " +"point out that this is rightfully unsafe!" +msgstr "" + +#: src/memory-management/stack.md:37 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // 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" +" unsafe {\n" +" let (ptr, capacity, len): (usize, usize, usize) = std::mem::" +"transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/manual.md:3 +msgid "You allocate and deallocate heap memory yourself." +msgstr "" + +#: src/memory-management/manual.md:5 +msgid "" +"If not done with care, this can lead to crashes, bugs, security " +"vulnerabilities, and memory leaks." +msgstr "" + +#: src/memory-management/manual.md:7 +msgid "C Example" +msgstr "" + +#: src/memory-management/manual.md:9 +msgid "You must call `free` on every pointer you allocate with `malloc`:" +msgstr "" + +#: src/memory-management/manual.md:11 +msgid "" +"```c\n" +"void foo(size_t n) {\n" +" int* int_array = malloc(n * sizeof(int));\n" +" //\n" +" // ... lots of code\n" +" //\n" +" free(int_array);\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/manual.md:21 +msgid "" +"Memory is leaked if the function returns early between `malloc` and `free`: " +"the pointer is lost and we cannot deallocate the memory. Worse, freeing the " +"pointer twice, or accessing a freed pointer can lead to exploitable security " +"vulnerabilities." +msgstr "" + +#: src/memory-management/scope-based.md:3 +msgid "" +"Constructors and destructors let you hook into the lifetime of an object." +msgstr "" + +#: src/memory-management/scope-based.md:5 +msgid "" +"By wrapping a pointer in an object, you can free memory when the object is " +"destroyed. The compiler guarantees that this happens, even if an exception " +"is raised." +msgstr "" + +#: src/memory-management/scope-based.md:9 +msgid "" +"This is often called _resource acquisition is initialization_ (RAII) and " +"gives you smart pointers." +msgstr "" + +#: src/memory-management/scope-based.md:12 +msgid "C++ Example" +msgstr "" + +#: src/memory-management/scope-based.md:14 +msgid "" +"```c++\n" +"void say_hello(std::unique_ptr person) {\n" +" std::cout << \"Hello \" << person->name << std::endl;\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/scope-based.md:20 +msgid "" +"The `std::unique_ptr` object is allocated on the stack, and points to memory " +"allocated on the heap." +msgstr "" + +#: src/memory-management/scope-based.md:22 +msgid "At the end of `say_hello`, the `std::unique_ptr` destructor will run." +msgstr "" + +#: src/memory-management/scope-based.md:23 +msgid "The destructor frees the `Person` object it points to." +msgstr "" + +#: src/memory-management/scope-based.md:25 +msgid "" +"Special move constructors are used when passing ownership to a function:" +msgstr "" + +#: src/memory-management/garbage-collection.md:1 +msgid "Automatic Memory Management" +msgstr "" + +#: src/memory-management/garbage-collection.md:3 +msgid "" +"An alternative to manual and scope-based memory management is automatic " +"memory management:" +msgstr "" + +#: src/memory-management/garbage-collection.md:6 +msgid "The programmer never allocates or deallocates memory explicitly." +msgstr "" + +#: src/memory-management/garbage-collection.md:7 +msgid "" +"A garbage collector finds unused memory and deallocates it for the " +"programmer." +msgstr "" + +#: src/memory-management/garbage-collection.md:9 +msgid "Java Example" +msgstr "" + +#: src/memory-management/garbage-collection.md:11 +msgid "The `person` object is not deallocated after `sayHello` returns:" +msgstr "" + +#: src/memory-management/garbage-collection.md:13 +msgid "" +"```java\n" +"void sayHello(Person person) {\n" +" System.out.println(\"Hello \" + person.getName());\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/rust.md:1 +msgid "Memory Management in Rust" +msgstr "" + +#: src/memory-management/rust.md:3 +msgid "Memory management in Rust is a mix:" +msgstr "" + +#: src/memory-management/rust.md:5 +msgid "Safe and correct like Java, but without a garbage collector." +msgstr "" + +#: src/memory-management/rust.md:6 +msgid "Scope-based like C++, but the compiler enforces full adherence." +msgstr "" + +#: src/memory-management/rust.md:7 +msgid "" +"A Rust user can choose the right abstraction for the situation, some even " +"have no cost at runtime like C." +msgstr "" + +#: src/memory-management/rust.md:9 +msgid "Rust achieves this by modeling _ownership_ explicitly." +msgstr "" + +#: src/memory-management/rust.md:13 +msgid "" +"If asked how at this point, you can mention that in Rust this is usually " +"handled by RAII wrapper types such as [Box](https://doc.rust-lang.org/std/" +"boxed/struct.Box.html), [Vec](https://doc.rust-lang.org/std/vec/struct.Vec." +"html), [Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html), or [Arc]" +"(https://doc.rust-lang.org/std/sync/struct.Arc.html). These encapsulate " +"ownership and memory allocation via various means, and prevent the potential " +"errors in C." +msgstr "" + +#: src/memory-management/rust.md:15 +msgid "" +"You may be asked about destructors here, the [Drop](https://doc.rust-lang." +"org/std/ops/trait.Drop.html) trait is the Rust equivalent." +msgstr "" + +#: src/ownership.md:3 +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/ownership.md:19 +msgid "" +"At the end of the scope, the variable is _dropped_ and the data is freed." +msgstr "" + +#: src/ownership.md:20 +msgid "A destructor can run here to free up resources." +msgstr "" + +#: src/ownership.md:21 +msgid "We say that the variable _owns_ the value." +msgstr "" + +#: src/ownership/move-semantics.md:3 +msgid "An assignment will transfer _ownership_ between variables:" +msgstr "" + +#: src/ownership/move-semantics.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Hello!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/move-semantics.md:14 +msgid "The assignment of `s1` to `s2` transfers ownership." +msgstr "" + +#: src/ownership/move-semantics.md:15 +msgid "When `s1` goes out of scope, nothing happens: it does not own anything." +msgstr "" + +#: src/ownership/move-semantics.md:16 +msgid "When `s2` goes out of scope, the string data is freed." +msgstr "" + +#: src/ownership/move-semantics.md:17 +msgid "There is always _exactly_ one variable binding which owns a value." +msgstr "" + +#: src/ownership/move-semantics.md:21 +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/ownership/move-semantics.md:23 +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/ownership/move-semantics.md:25 +msgid "" +"Simple values (such as integers) can be marked `Copy` (see later slides)." +msgstr "" + +#: src/ownership/move-semantics.md:27 +msgid "In Rust, clones are explicit (by using `clone`)." +msgstr "" + +#: src/ownership/moved-strings-rust.md:11 +msgid "The heap data from `s1` is reused for `s2`." +msgstr "" + +#: src/ownership/moved-strings-rust.md:12 +msgid "When `s1` goes out of scope, nothing happens (it has been moved from)." +msgstr "" + +#: src/ownership/moved-strings-rust.md:14 +msgid "Before move to `s2`:" +msgstr "" + +#: src/ownership/moved-strings-rust.md:31 +msgid "After move to `s2`:" +msgstr "" + +#: src/ownership/moved-strings-rust.md:33 +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" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:1 +#, fuzzy +msgid "Defensive Copies in Modern C++" +msgstr "آزاد سازی مضاعف در مدرن سی++" + +#: src/ownership/double-free-modern-cpp.md:3 +msgid "Modern C++ solves this differently:" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:5 +msgid "" +"```c++\n" +"std::string s1 = \"Cpp\";\n" +"std::string s2 = s1; // Duplicate the data in s1.\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:10 +msgid "" +"The heap data from `s1` is duplicated and `s2` gets its own independent copy." +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:11 +msgid "When `s1` and `s2` go out of scope, they each free their own memory." +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:13 +msgid "Before copy-assignment:" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:30 +msgid "After copy-assignment:" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:57 +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/ownership/double-free-modern-cpp.md:61 +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/ownership/double-free-modern-cpp.md:66 +msgid "" +"Unlike Rust, `=` in C++ can run arbitrary code as determined by the type " +"which is being copied or moved." +msgstr "" + +#: src/ownership/moves-function-calls.md:3 +msgid "" +"When you pass a value to a function, the value is assigned to the function " +"parameter. This transfers ownership:" +msgstr "" + +#: src/ownership/moves-function-calls.md:6 +msgid "" +"```rust,editable\n" +"fn say_hello(name: String) {\n" +" println!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let name = String::from(\"Alice\");\n" +" say_hello(name);\n" +" // say_hello(name);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:20 +msgid "" +"With the first call to `say_hello`, `main` gives up ownership of `name`. " +"Afterwards, `name` cannot be used anymore within `main`." +msgstr "" + +#: src/ownership/moves-function-calls.md:21 +msgid "" +"The heap memory allocated for `name` will be freed at the end of the " +"`say_hello` function." +msgstr "" + +#: src/ownership/moves-function-calls.md:22 +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/ownership/moves-function-calls.md:23 +msgid "" +"Alternatively, `main` can pass a clone of `name` in the first call (`name." +"clone()`)." +msgstr "" + +#: src/ownership/moves-function-calls.md:24 +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/ownership/copy-clone.md:3 +msgid "" +"While move semantics are the default, certain types are copied by default:" +msgstr "" + +#: src/ownership/copy-clone.md:15 +msgid "These types implement the `Copy` trait." +msgstr "" + +#: src/ownership/copy-clone.md:17 +msgid "You can opt-in your own types to use copy semantics:" +msgstr "" + +#: src/ownership/copy-clone.md:32 +msgid "After the assignment, both `p1` and `p2` own their own data." +msgstr "" + +#: src/ownership/copy-clone.md:33 +msgid "We can also use `p1.clone()` to explicitly copy the data." +msgstr "" + +#: src/ownership/copy-clone.md:37 +msgid "Copying and cloning are not the same thing:" +msgstr "" + +#: src/ownership/copy-clone.md:39 +msgid "" +"Copying refers to bitwise copies of memory regions and does not work on " +"arbitrary objects." +msgstr "" + +#: src/ownership/copy-clone.md:40 +msgid "" +"Copying does not allow for custom logic (unlike copy constructors in C++)." +msgstr "" + +#: src/ownership/copy-clone.md:41 +msgid "" +"Cloning is a more general operation and also allows for custom behavior by " +"implementing the `Clone` trait." +msgstr "" + +#: src/ownership/copy-clone.md:42 +msgid "Copying does not work on types that implement the `Drop` trait." +msgstr "" + +#: src/ownership/copy-clone.md:44 src/ownership/lifetimes-function-calls.md:30 +msgid "In the above example, try the following:" +msgstr "" + +#: src/ownership/copy-clone.md:46 +msgid "" +"Add a `String` field to `struct Point`. It will not compile because `String` " +"is not a `Copy` type." +msgstr "" + +#: src/ownership/copy-clone.md:47 +msgid "" +"Remove `Copy` from the `derive` attribute. The compiler error is now in the " +"`println!` for `p1`." +msgstr "" + +#: src/ownership/copy-clone.md:48 +msgid "Show that it works if you clone `p1` instead." +msgstr "" + +#: src/ownership/copy-clone.md:50 +msgid "" +"If students ask about `derive`, it is sufficient to say that this is a way " +"to generate code in Rust at compile time. In this case the default " +"implementations of `Copy` and `Clone` traits are generated." +msgstr "" + +#: src/ownership/borrowing.md:3 +msgid "" +"Instead of transferring ownership when calling a function, you can let a " +"function _borrow_ the value:" +msgstr "" + +#: src/ownership/borrowing.md:23 +msgid "The `add` function _borrows_ two points and returns a new point." +msgstr "" + +#: src/ownership/borrowing.md:24 +msgid "The caller retains ownership of the inputs." +msgstr "" + +#: src/ownership/borrowing.md:28 +msgid "Notes on stack returns:" +msgstr "" + +#: src/ownership/borrowing.md:29 +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/) 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/ownership/borrowing.md:50 +msgid "The Rust compiler can do return value optimization (RVO)." +msgstr "" + +#: src/ownership/borrowing.md:51 +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." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:3 +msgid "Rust puts constraints on the ways you can borrow values:" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:5 +msgid "You can have one or more `&T` values at any given time, _or_" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:6 +msgid "You can have exactly one `&mut T` value." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:26 +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/ownership/shared-unique-borrows.md:27 +msgid "" +"Move the `println!` statement for `b` before the scope that introduces `c` " +"to make the code compile." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:28 +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/ownership/lifetimes.md:3 +msgid "A borrowed value has a _lifetime_:" +msgstr "" + +#: src/ownership/lifetimes.md:5 +msgid "The lifetime can be implicit: `add(p1: &Point, p2: &Point) -> Point`." +msgstr "" + +#: src/ownership/lifetimes.md:6 +msgid "Lifetimes can also be explicit: `&'a Point`, `&'document str`." +msgstr "" + +#: src/ownership/lifetimes.md:7 src/ownership/lifetimes-function-calls.md:24 +msgid "" +"Read `&'a Point` as \"a borrowed `Point` which is valid for at least the " +"lifetime `a`\"." +msgstr "" + +#: src/ownership/lifetimes.md:9 +msgid "" +"Lifetimes are always inferred by the compiler: you cannot assign a lifetime " +"yourself." +msgstr "" + +#: src/ownership/lifetimes.md:11 +msgid "" +"Lifetime annotations create constraints; the compiler verifies that there is " +"a valid solution." +msgstr "" + +#: src/ownership/lifetimes.md:13 +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)." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:3 +msgid "" +"In addition to borrowing its arguments, a function can return a borrowed " +"value:" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:22 +msgid "`'a` is a generic parameter, it is inferred by the compiler." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:23 +msgid "Lifetimes start with `'` and `'a` is a typical default name." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:26 +msgid "" +"The _at least_ part is important when parameters are in different scopes." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:32 +msgid "" +"Move the declaration of `p2` and `p3` into a new scope (`{ ... }`), " +"resulting in the following code:" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:52 +msgid "Note how this does not compile since `p3` outlives `p2`." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:54 +msgid "" +"Reset the workspace and change the function signature to `fn left_most<'a, " +"'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " +"because the relationship between the lifetimes `'a` and `'b` is unclear." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:55 +msgid "Another way to explain it:" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:56 +msgid "" +"Two references to two values are borrowed by a function and the function " +"returns another reference." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:58 +msgid "" +"It must have come from one of those two inputs (or from a global variable)." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:59 +msgid "" +"Which one is it? The compiler needs to know, so at the call site the " +"returned reference is not used for longer than a variable from where the " +"reference came from." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:3 +msgid "" +"If a data type stores borrowed data, it must be annotated with a lifetime:" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Highlight<'doc>(&'doc str);\n" +"\n" +"fn erase(text: String) {\n" +" println!(\"Bye {text}!\");\n" +"}\n" +"\n" +"fn main() {\n" +" let text = String::from(\"The quick brown fox jumps over the lazy dog." +"\");\n" +" let fox = Highlight(&text[4..19]);\n" +" let dog = Highlight(&text[35..43]);\n" +" // erase(text);\n" +" println!(\"{fox:?}\");\n" +" println!(\"{dog:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:25 +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." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:26 +msgid "" +"If `text` is consumed before the end of the lifetime of `fox` (or `dog`), " +"the borrow checker throws an error." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:27 +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/ownership/lifetimes-data-structures.md:28 +msgid "When possible, make data structures own their data directly." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:29 +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/structs.md:3 +msgid "Like C and C++, Rust has support for custom structs:" +msgstr "" + +#: src/structs.md:5 +msgid "" +"```rust,editable\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" peter.age = 28;\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" let jackie = Person {\n" +" name: String::from(\"Jackie\"),\n" +" ..peter\n" +" };\n" +" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" +"}\n" +"```" +msgstr "" + +#: src/structs.md:33 +msgid "Structs work like in C or C++." +msgstr "" + +#: src/structs.md:34 +msgid "Like in C++, and unlike in C, no typedef is needed to define a type." +msgstr "" + +#: src/structs.md:35 +msgid "Unlike in C++, there is no inheritance between structs." +msgstr "" + +#: src/structs.md:36 +msgid "" +"Methods are defined in an `impl` block, which we will see in following " +"slides." +msgstr "" + +#: src/structs.md:37 +msgid "" +"This may be a good time to let people know there are different types of " +"structs. " +msgstr "" + +#: src/structs.md:38 +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/structs.md:39 +msgid "" +"The next slide will introduce Tuple structs, used when the field names are " +"not important." +msgstr "" + +#: src/structs.md:40 +msgid "" +"The syntax `..peter` 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/structs/tuple-structs.md:3 +msgid "If the field names are unimportant, you can use a tuple struct:" +msgstr "" + +#: src/structs/tuple-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p = Point(17, 23);\n" +" println!(\"({}, {})\", p.0, p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:14 +msgid "This is often used for single-field wrappers (called newtypes):" +msgstr "" + +#: src/structs/tuple-structs.md:16 +msgid "" +"```rust,editable,compile_fail\n" +"struct PoundsOfForce(f64);\n" +"struct Newtons(f64);\n" +"\n" +"fn compute_thruster_force() -> PoundsOfForce {\n" +" todo!(\"Ask a rocket scientist at NASA\")\n" +"}\n" +"\n" +"fn set_thruster_force(force: Newtons) {\n" +" // ...\n" +"}\n" +"\n" +"fn main() {\n" +" let force = compute_thruster_force();\n" +" set_thruster_force(force);\n" +"}\n" +"\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:37 +msgid "" +"Newtypes are a great way to encode additional information about the value in " +"a primitive type, for example:" +msgstr "" + +#: src/structs/tuple-structs.md:38 +msgid "The number is measured in some units: `Newtons` in the example above." +msgstr "" + +#: src/structs/tuple-structs.md:39 +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/structs/tuple-structs.md:40 +msgid "" +"Demonstrate how to add a `f64` value to a `Newtons` type by accessing the " +"single field in the newtype." +msgstr "" + +#: src/structs/tuple-structs.md:41 +msgid "" +"Rust generally doesn’t like inexplicit things, like automatic unwrapping or " +"for instance using booleans as integers." +msgstr "" + +#: src/structs/tuple-structs.md:42 +msgid "Operator overloading is discussed on Day 3 (generics)." +msgstr "" + +#: src/structs/tuple-structs.md:43 +msgid "" +"The example is a subtle reference to the [Mars Climate Orbiter](https://en." +"wikipedia.org/wiki/Mars_Climate_Orbiter) failure." +msgstr "" + +#: src/structs/field-shorthand.md:3 +msgid "" +"If you already have variables with the right names, then you can create the " +"struct using a shorthand:" +msgstr "" + +#: src/structs/field-shorthand.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn new(name: String, age: u8) -> Person {\n" +" Person { name, age }\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person::new(String::from(\"Peter\"), 27);\n" +" println!(\"{peter:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/structs/field-shorthand.md:27 +msgid "" +"The `new` function could be written using `Self` as a type, as it is " +"interchangeable with the struct type name" +msgstr "" + +#: src/structs/field-shorthand.md:41 +msgid "" +"Implement the `Default` trait for the struct. Define some fields and use the " +"default values for the other fields." +msgstr "" + +#: src/structs/field-shorthand.md:43 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"impl Default for Person {\n" +" fn default() -> Person {\n" +" Person {\n" +" name: \"Bot\".to_string(),\n" +" age: 0,\n" +" }\n" +" }\n" +"}\n" +"fn create_default() {\n" +" let tmp = Person {\n" +" ..Person::default()\n" +" };\n" +" let tmp = Person {\n" +" name: \"Sam\".to_string(),\n" +" ..Person::default()\n" +" };\n" +"}\n" +"```" +msgstr "" + +#: src/structs/field-shorthand.md:68 +msgid "Methods are defined in the `impl` block." +msgstr "" + +#: src/structs/field-shorthand.md:69 +msgid "" +"Use struct update syntax to define a new structure using `peter`. Note that " +"the variable `peter` will no longer be accessible afterwards." +msgstr "" + +#: src/structs/field-shorthand.md:70 +msgid "" +"Use `{:#?}` when printing structs to request the `Debug` representation." +msgstr "" + +#: src/methods.md:3 +msgid "" +"Rust allows you to associate functions with your new types. You do this with " +"an `impl` block:" +msgstr "" + +#: src/methods.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn say_hello(&self) {\n" +" println!(\"Hello, my name is {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" peter.say_hello();\n" +"}\n" +"```" +msgstr "" + +#: src/methods.md:31 +msgid "It can be helpful to introduce methods by comparing them to functions." +msgstr "" + +#: src/methods.md:32 +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.md:33 +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.md:34 +msgid "Point out the use of the keyword `self`, a method receiver." +msgstr "" + +#: src/methods.md:35 +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.md:36 +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.md:37 +msgid "" +"Note how `self` is used like other structs and dot notation can be used to " +"refer to individual fields." +msgstr "" + +#: src/methods.md:38 +msgid "" +"This might be a good time to demonstrate how the `&self` differs from `self` " +"by modifying the code and trying to run say_hello twice." +msgstr "" + +#: src/methods.md:39 +msgid "We describe the distinction between method receivers next." +msgstr "" + +#: src/methods/receiver.md:3 +msgid "" +"The `&self` above indicates that the method borrows the object immutably. " +"There are other possible receivers for a method:" +msgstr "" + +#: src/methods/receiver.md:6 +msgid "" +"`&self`: borrows the object from the caller using a shared and immutable " +"reference. The object can be used again afterwards." +msgstr "" + +#: src/methods/receiver.md:8 +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/receiver.md:10 +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/receiver.md:14 +msgid "`mut self`: same as above, but the method can mutate the object. " +msgstr "" + +#: src/methods/receiver.md:15 +msgid "" +"No receiver: this becomes a static method on the struct. Typically used to " +"create constructors which are called `new` by convention." +msgstr "" + +#: src/methods/receiver.md:18 +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/receiver.md:24 +msgid "" +"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". " +"These constraints always come together in Rust due to borrow checker rules, " +"and `self` is no exception. It isn't possible to reference a struct from " +"multiple locations and call a mutating (`&mut self`) method on it." +msgstr "" + +#: src/methods/example.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Race {\n" +" name: String,\n" +" laps: Vec,\n" +"}\n" +"\n" +"impl Race {\n" +" fn new(name: &str) -> Race { // No receiver, a static method\n" +" Race { name: String::from(name), laps: Vec::new() }\n" +" }\n" +"\n" +" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write " +"access to self\n" +" self.laps.push(lap);\n" +" }\n" +"\n" +" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" +" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" +" for (idx, lap) in self.laps.iter().enumerate() {\n" +" println!(\"Lap {idx}: {lap} sec\");\n" +" }\n" +" }\n" +"\n" +" fn finish(self) { // Exclusive ownership of self\n" +" let total = self.laps.iter().sum::();\n" +" println!(\"Race {} is finished, total lap time: {}\", self.name, " +"total);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut race = Race::new(\"Monaco Grand Prix\");\n" +" race.add_lap(70);\n" +" race.add_lap(68);\n" +" race.print_laps();\n" +" race.add_lap(71);\n" +" race.print_laps();\n" +" race.finish();\n" +" // race.add_lap(42);\n" +"}\n" +"```" +msgstr "" + +#: src/methods/example.md:47 +msgid "All four methods here use a different method receiver." +msgstr "" + +#: src/methods/example.md:48 +msgid "" +"You can point out how that changes what the function can do with the " +"variable values and if/how it can be used again in `main`." +msgstr "" + +#: src/methods/example.md:49 +msgid "" +"You can showcase the error that appears when trying to call `finish` twice." +msgstr "" + +#: src/methods/example.md:50 +msgid "" +"Note that although the method receivers are different, the non-static " +"functions are called the same way in the main body. Rust enables automatic " +"referencing and dereferencing when calling methods. Rust automatically adds " +"in the `&`, `*`, `muts` so that that object matches the method signature." +msgstr "" + +#: src/methods/example.md:51 +msgid "" +"You might point out that `print_laps` is using a vector that is iterated " +"over. We describe vectors in more detail in the afternoon. " +msgstr "" + #: src/exercises/day-2/morning.md:1 msgid "Day 2: Morning Exercises" msgstr "" @@ -6601,11 +6348,124 @@ msgid "We will look at implementing methods in two contexts:" msgstr "" #: src/exercises/day-2/morning.md:5 -msgid "Simple struct which tracks health statistics." +msgid "Storing books and querying the collection" msgstr "" #: src/exercises/day-2/morning.md:7 -msgid "Multiple structs and enums for a drawing library." +msgid "Keeping track of health statistics for patients" +msgstr "" + +#: src/exercises/day-2/book-library.md:3 +msgid "" +"We will learn much more about structs and the `Vec` type tomorrow. For " +"now, you just need to know part of its API:" +msgstr "" + +#: src/exercises/day-2/book-library.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut vec = vec![10, 20];\n" +" vec.push(30);\n" +" let midpoint = vec.len() / 2;\n" +" println!(\"middle value: {}\", vec[midpoint]);\n" +" for item in &vec {\n" +" println!(\"item: {item}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/book-library.md:18 +msgid "" +"Use this to model a library's book collection. Copy the code below to " +" and update the types to make it compile:" +msgstr "" + +#: src/exercises/day-2/book-library.md:21 +msgid "" +"```rust,should_panic\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// Implement the methods below. Notice how the `self` parameter\n" +"// changes type to indicate the method's required level of ownership\n" +"// over the object:\n" +"//\n" +"// - `&self` for shared read-only access,\n" +"// - `&mut self` for unique and mutable access,\n" +"// - `self` for unique access by value.\n" +"impl Library {\n" +" fn new() -> Library {\n" +" todo!(\"Initialize and return a `Library` value\")\n" +" }\n" +"\n" +" fn len(&self) -> usize {\n" +" todo!(\"Return the length of `self.books`\")\n" +" }\n" +"\n" +" fn is_empty(&self) -> bool {\n" +" todo!(\"Return `true` if `self.books` is empty\")\n" +" }\n" +"\n" +" fn add_book(&mut self, book: Book) {\n" +" todo!(\"Add a new book to `self.books`\")\n" +" }\n" +"\n" +" fn print_books(&self) {\n" +" todo!(\"Iterate over `self.books` and print each book's title and " +"year\")\n" +" }\n" +"\n" +" fn oldest_book(&self) -> Option<&Book> {\n" +" todo!(\"Return a reference to the oldest book (if any)\")\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut library = Library::new();\n" +"\n" +" println!(\n" +" \"The library is empty: library.is_empty() -> {}\",\n" +" library.is_empty()\n" +" );\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " +"1865));\n" +"\n" +" println!(\n" +" \"The library is no longer empty: library.is_empty() -> {}\",\n" +" library.is_empty()\n" +" );\n" +"\n" +" library.print_books();\n" +"\n" +" match library.oldest_book() {\n" +" Some(book) => println!(\"The oldest book is {}\", book.title),\n" +" None => println!(\"The library is empty!\"),\n" +" }\n" +"\n" +" println!(\"The library has {} books\", library.len());\n" +" library.print_books();\n" +"}\n" +"```" msgstr "" #: src/exercises/day-2/health-statistics.md:3 @@ -6655,36 +6515,38 @@ msgid "" "\n" "impl User {\n" " pub fn new(name: String, age: u32, height: f32) -> Self {\n" -" unimplemented!()\n" +" todo!(\"Create a new User instance\")\n" " }\n" "\n" " pub fn name(&self) -> &str {\n" -" unimplemented!()\n" +" todo!(\"Return the user's name\")\n" " }\n" "\n" " pub fn age(&self) -> u32 {\n" -" unimplemented!()\n" +" todo!(\"Return the user's age\")\n" " }\n" "\n" " pub fn height(&self) -> f32 {\n" -" unimplemented!()\n" +" todo!(\"Return the user's height\")\n" " }\n" "\n" " pub fn doctor_visits(&self) -> u32 {\n" -" unimplemented!()\n" +" todo!(\"Return the number of time the user has visited the " +"doctor\")\n" " }\n" "\n" " pub fn set_age(&mut self, new_age: u32) {\n" -" unimplemented!()\n" +" todo!(\"Set the user's age\")\n" " }\n" "\n" " pub fn set_height(&mut self, new_height: f32) {\n" -" unimplemented!()\n" +" todo!(\"Set the user's height\")\n" " }\n" "\n" " pub fn visit_doctor(&mut self, measurements: Measurements) -> " "HealthReport {\n" -" unimplemented!()\n" +" todo!(\"Update a user's statistics based on measurements from a " +"visit to the doctor\")\n" " }\n" "}\n" "\n" @@ -6730,628 +6592,10 @@ msgid "" "```" msgstr "" -#: src/exercises/day-2/points-polygons.md:1 -msgid "Polygon Struct" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:3 -msgid "" -"We will create a `Polygon` struct which contain some points. Copy the code " -"below to and fill in the missing methods to " -"make the tests pass:" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:7 -msgid "" -"```rust\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]\n" -"\n" -"pub struct Point {\n" -" // add fields\n" -"}\n" -"\n" -"impl Point {\n" -" // add methods\n" -"}\n" -"\n" -"pub struct Polygon {\n" -" // add fields\n" -"}\n" -"\n" -"impl Polygon {\n" -" // add methods\n" -"}\n" -"\n" -"pub struct Circle {\n" -" // add fields\n" -"}\n" -"\n" -"impl Circle {\n" -" // add methods\n" -"}\n" -"\n" -"pub enum Shape {\n" -" Polygon(Polygon),\n" -" Circle(Circle),\n" -"}\n" -"\n" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;\n" -"\n" -" fn round_two_digits(x: f64) -> f64 {\n" -" (x * 100.0).round() / 100.0\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_magnitude() {\n" -" let p1 = Point::new(12, 13);\n" -" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_dist() {\n" -" let p1 = Point::new(10, 10);\n" -" let p2 = Point::new(14, 13);\n" -" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_add() {\n" -" let p1 = Point::new(16, 16);\n" -" let p2 = p1 + Point::new(-4, 3);\n" -" assert_eq!(p2, Point::new(12, 19));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_left_most_point() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -" assert_eq!(poly.left_most_point(), Some(p1));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_iter() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -"\n" -" let points = poly.iter().cloned().collect::>();\n" -" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_shape_perimeters() {\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(Point::new(12, 13));\n" -" poly.add_point(Point::new(17, 11));\n" -" poly.add_point(Point::new(16, 16));\n" -" let shapes = vec![\n" -" Shape::from(poly),\n" -" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" -" ];\n" -" let perimeters = shapes\n" -" .iter()\n" -" .map(Shape::perimeter)\n" -" .map(round_two_digits)\n" -" .collect::>();\n" -" assert_eq!(perimeters, vec![15.48, 31.42]);\n" -" }\n" -"}\n" -"\n" -"#[allow(dead_code)]\n" -"fn main() {}\n" -"```" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:117 -msgid "" -"Since the method signatures are missing from the problem statements, the key " -"part of the exercise is to specify those correctly. You don't have to modify " -"the tests." -msgstr "" - -#: src/exercises/day-2/points-polygons.md:120 -msgid "Other interesting parts of the exercise:" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:122 -msgid "" -"Derive a `Copy` trait for some structs, as in tests the methods sometimes " -"don't borrow their arguments." -msgstr "" - -#: src/exercises/day-2/points-polygons.md:123 -msgid "" -"Discover that `Add` trait must be implemented for two objects to be addable " -"via \"+\". Note that we do not discuss generics until Day 3." -msgstr "" - -#: src/control-flow.md:3 -msgid "" -"As we have seen, `if` is an expression in Rust. It is used to conditionally " -"evaluate one of two blocks, but the blocks can have a value which then " -"becomes the value of the `if` expression. Other control flow expressions " -"work similarly in Rust." -msgstr "" - -#: src/control-flow/blocks.md:3 -msgid "" -"A block in Rust contains a sequence of expressions. Each block has a value " -"and a type, which are those of the last expression of the block:" -msgstr "" - -#: src/control-flow/blocks.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let x = {\n" -" let y = 10;\n" -" println!(\"y: {y}\");\n" -" let z = {\n" -" let w = {\n" -" 3 + 4\n" -" };\n" -" println!(\"w: {w}\");\n" -" y * w\n" -" };\n" -" println!(\"z: {z}\");\n" -" z - y\n" -" };\n" -" println!(\"x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/blocks.md:26 -msgid "" -"If the last expression ends with `;`, then the resulting value and type is " -"`()`." -msgstr "" - -#: src/control-flow/blocks.md:28 -msgid "" -"The same rule is used for functions: the value of the function body is the " -"return value:" -msgstr "" - -#: src/control-flow/blocks.md:31 -msgid "" -"```rust,editable\n" -"fn double(x: i32) -> i32 {\n" -" x + x\n" -"}\n" -"\n" -"fn main() {\n" -" println!(\"doubled: {}\", double(7));\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/blocks.md:44 -msgid "" -"The point of this slide is to show that blocks have a type and value in " -"Rust. " -msgstr "" - -#: src/control-flow/blocks.md:45 -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/if-expressions.md:1 -msgid "`if` expressions" -msgstr "" - -#: src/control-flow/if-expressions.md:3 -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/if-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" if x % 2 == 0 {\n" -" x = x / 2;\n" -" } else {\n" -" x = 3 * x + 1;\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/if-expressions.md:18 -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/if-expressions.md:22 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/if-expressions.md:35 -msgid "" -"Because `if` is an expression and must have a particular type, both of its " -"branch blocks must have the same type. Consider showing what happens if you " -"add `;` after `x / 2` in the second example." -msgstr "" - -#: src/control-flow/if-let-expressions.md:1 -msgid "`if let` expressions" -msgstr "" - -#: src/control-flow/if-let-expressions.md:3 -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/control-flow/if-let-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let arg = std::env::args().next();\n" -" if let Some(value) = arg {\n" -" println!(\"Program name: {value}\");\n" -" } else {\n" -" println!(\"Missing name?\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/if-let-expressions.md:18 -#: src/control-flow/while-let-expressions.md:21 -#: src/control-flow/match-expressions.md:23 -msgid "" -"See [pattern matching](../pattern-matching.md) for more details on patterns " -"in Rust." -msgstr "" - -#: src/control-flow/if-let-expressions.md:23 -msgid "" -"Unlike `match`, `if let` does not have to cover all branches. This can make " -"it more concise than `match`." -msgstr "" - -#: src/control-flow/if-let-expressions.md:24 -msgid "A common usage is handling `Some` values when working with `Option`." -msgstr "" - -#: src/control-flow/if-let-expressions.md:25 -msgid "" -"Unlike `match`, `if let` does not support guard clauses for pattern matching." -msgstr "" - -#: src/control-flow/if-let-expressions.md:26 -msgid "" -"Since 1.65, a similar [let-else](https://doc.rust-lang.org/rust-by-example/" -"flow_control/let_else.html) construct allows to do a destructuring " -"assignment, or if it fails, execute a block which is required to abort " -"normal control flow (with `panic`/`return`/`break`/`continue`):" -msgstr "" - -#: src/control-flow/if-let-expressions.md:28 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"{:?}\", second_word_to_upper(\"foo bar\"));\n" -"}\n" -" \n" -"fn second_word_to_upper(s: &str) -> Option {\n" -" let mut it = s.split(' ');\n" -" let (Some(_), Some(item)) = (it.next(), it.next()) else {\n" -" return None;\n" -" };\n" -" Some(item.to_uppercase())\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/while-expressions.md:1 -msgid "`while` loops" -msgstr "" - -#: src/control-flow/while-expressions.md:3 -msgid "" -"The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-" -"expr.html#predicate-loops) works very similar to other languages:" -msgstr "" - -#: src/control-flow/while-expressions.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" while x != 1 {\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -" }\n" -" println!(\"Final x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/while-let-expressions.md:1 -msgid "`while let` loops" -msgstr "" - -#: src/control-flow/while-let-expressions.md:3 -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:" -msgstr "" - -#: src/control-flow/while-let-expressions.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();\n" -"\n" -" while let Some(x) = iter.next() {\n" -" println!(\"x: {x}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/while-let-expressions.md:17 -msgid "" -"Here the iterator returned by `v.into_iter()` will return a `Option` on " -"every call to `next()`. It returns `Some(x)` until it is done, after which " -"it will return `None`. The `while let` lets us keep iterating through all " -"items." -msgstr "" - -#: src/control-flow/while-let-expressions.md:26 -msgid "" -"Point out that the `while let` loop will keep going as long as the value " -"matches the pattern." -msgstr "" - -#: src/control-flow/while-let-expressions.md:27 -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 `iter.next()`. " -"The `while let` provides syntactic sugar for the above scenario." -msgstr "" - -#: src/control-flow/for-expressions.md:1 -msgid "`for` loops" -msgstr "" - -#: src/control-flow/for-expressions.md:3 -msgid "" -"The [`for` loop](https://doc.rust-lang.org/std/keyword.for.html) is closely " -"related to the [`while let` loop](while-let-expressions.md). It will " -"automatically call `into_iter()` on the expression and then iterate over it:" -msgstr "" - -#: src/control-flow/for-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -"\n" -" for x in v {\n" -" println!(\"x: {x}\");\n" -" }\n" -" \n" -" for i in (0..10).step_by(2) {\n" -" println!(\"i: {i}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/for-expressions.md:21 -msgid "You can use `break` and `continue` here as usual." -msgstr "" - -#: src/control-flow/for-expressions.md:25 -msgid "Index iteration is not a special syntax in Rust for just that case." -msgstr "" - -#: src/control-flow/for-expressions.md:26 -msgid "`(0..10)` is a range that implements an `Iterator` trait. " -msgstr "" - -#: src/control-flow/for-expressions.md:27 -msgid "" -"`step_by` is a method that returns another `Iterator` that skips every other " -"element. " -msgstr "" - -#: src/control-flow/for-expressions.md:28 -msgid "" -"Modify the elements in the vector and explain the compiler errors. Change " -"vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." -msgstr "" - -#: src/control-flow/loop-expressions.md:1 -msgid "`loop` expressions" -msgstr "" - -#: src/control-flow/loop-expressions.md:3 -msgid "" -"Finally, there is a [`loop` keyword](https://doc.rust-lang.org/reference/" -"expressions/loop-expr.html#infinite-loops) which creates an endless loop." -msgstr "" - -#: src/control-flow/loop-expressions.md:6 -msgid "Here you must either `break` or `return` to stop the loop:" -msgstr "" - -#: src/control-flow/loop-expressions.md:8 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" loop {\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -" if x == 1 {\n" -" break;\n" -" }\n" -" }\n" -" println!(\"Final x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/loop-expressions.md:27 -msgid "Break the `loop` with a value (e.g. `break 8`) and print it out." -msgstr "" - -#: src/control-flow/loop-expressions.md:28 -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)." -msgstr "" - -#: src/control-flow/match-expressions.md:1 -msgid "`match` expressions" -msgstr "" - -#: src/control-flow/match-expressions.md:3 -msgid "" -"The [`match` keyword](https://doc.rust-lang.org/reference/expressions/match-" -"expr.html) is used to match a value against one or more patterns. In that " -"sense, it works like a series of `if let` expressions:" -msgstr "" - -#: src/control-flow/match-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" match std::env::args().next().as_deref() {\n" -" Some(\"cat\") => println!(\"Will do cat things\"),\n" -" Some(\"ls\") => println!(\"Will ls some files\"),\n" -" Some(\"mv\") => println!(\"Let's move some files\"),\n" -" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" -" None => println!(\"Hmm, no program name?\"),\n" -" _ => println!(\"Unknown program name!\"),\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/match-expressions.md:20 -msgid "" -"Like `if let`, 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 `()`." -msgstr "" - -#: src/control-flow/match-expressions.md:28 -msgid "Save the match expression to a variable and print it out." -msgstr "" - -#: src/control-flow/match-expressions.md:29 -msgid "Remove `.as_deref()` and explain the error." -msgstr "" - -#: src/control-flow/match-expressions.md:30 -msgid "" -"`std::env::args().next()` returns an `Option`, but we cannot match " -"against `String`." -msgstr "" - -#: src/control-flow/match-expressions.md:31 -msgid "" -"`as_deref()` transforms an `Option` to `Option<&T::Target>`. In our case, " -"this turns `Option` into `Option<&str>`." -msgstr "" - -#: src/control-flow/match-expressions.md:32 -msgid "" -"We can now use pattern matching to match against the `&str` inside `Option`." -msgstr "" - -#: src/control-flow/break-continue.md:1 -msgid "`break` and `continue`" -msgstr "" - -#: src/control-flow/break-continue.md:3 -msgid "" -"If you want to exit a loop early, use [`break`](https://doc.rust-lang.org/" -"reference/expressions/loop-expr.html#break-expressions)," -msgstr "" - -#: src/control-flow/break-continue.md:4 -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/break-continue.md:7 -msgid "" -"Both `continue` and `break` can optionally take a label argument which is " -"used to break out of nested loops:" -msgstr "" - -#: src/control-flow/break-continue.md:10 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();\n" -" 'outer: while let Some(x) = iter.next() {\n" -" println!(\"x: {x}\");\n" -" let mut i = 0;\n" -" while i < x {\n" -" println!(\"x: {x}, i: {i}\");\n" -" i += 1;\n" -" if i == 3 {\n" -" break 'outer;\n" -" }\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/break-continue.md:28 -msgid "" -"In this case we break the outer loop after 3 iterations of the inner loop." -msgstr "" - #: src/std.md:3 msgid "" "Rust comes with a standard library which helps establish a set of common " -"types used by Rust library and programs. This way, two libraries can work " +"types used by Rust libraries and programs. This way, two libraries can work " "together smoothly because they both use the same `String` type." msgstr "" @@ -7428,8 +6672,8 @@ msgid "" " let first: Option<&i8> = numbers.first();\n" " println!(\"first: {first:?}\");\n" "\n" -" let idx: Result = numbers.binary_search(&10);\n" -" println!(\"idx: {idx:?}\");\n" +" let arr: Result<[i8; 3], Vec> = numbers.try_into();\n" +" println!(\"arr: {arr:?}\");\n" "}\n" "```" msgstr "" @@ -7449,17 +6693,18 @@ msgid "" msgstr "" #: src/std/option-result.md:21 -msgid "`binary_search` returns `Result`." +msgid "" +"`try_into` attempts to convert the vector into a fixed-sized array. This can " +"fail:" msgstr "" #: src/std/option-result.md:22 -msgid "If found, `Result::Ok` holds the index where the element is found." +msgid "" +"If the vector has the right size, `Result::Ok` is returned with the array." msgstr "" #: src/std/option-result.md:23 -msgid "" -"Otherwise, `Result::Err` contains the index where such an element should be " -"inserted." +msgid "Otherwise, `Result::Err` is returned with the original vector." msgstr "" #: src/std/string.md:3 @@ -7534,7 +6779,7 @@ msgid "" msgstr "" #: src/std/string.md:36 -msgid "Write and compare `let s3 = s1.deref();` and `let s3 = &*s1`;." +msgid "Write and compare `let s3 = s1.deref();` and `let s3 = &*s1;`." msgstr "" #: src/std/string.md:37 @@ -7699,7 +6944,7 @@ msgstr "" msgid "" "```rust,ignore\n" " let pc1 = page_counts\n" -" .get(\"Harry Potter and the Sorcerer's Stone \")\n" +" .get(\"Harry Potter and the Sorcerer's Stone\")\n" " .unwrap_or(&336);\n" " let pc2 = page_counts\n" " .entry(\"The Hunger Games\".to_string())\n" @@ -7748,6 +6993,14 @@ msgid "" "compiles. Where do you think we might run into issues?" msgstr "" +#: src/std/hashmap.md:64 +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/box.md:1 msgid "`Box`" msgstr "" @@ -7768,22 +7021,6 @@ msgid "" "```" msgstr "" -#: src/std/box.md:13 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - -. .- - - - - - -.\n" -": : : :\n" -": five : : :\n" -": +-----+ : : +-----+ :\n" -": | o---|---+-----+-->| 5 | :\n" -": +-----+ : : +-----+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - -' `- - - - - - -'\n" -"```" -msgstr "" - #: src/std/box.md:26 msgid "" "`Box` implements `Deref`, which means that you can [call " @@ -7944,95 +7181,134 @@ msgstr "" #: src/std/rc.md:18 msgid "" -"If you need to mutate the data inside an `Rc`, you will need to wrap the " -"data in a type such as [`Cell` or `RefCell`](../concurrency/shared_state/arc." -"md)." +"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/std/rc.md:20 +#: src/std/rc.md:19 msgid "" -"See [`Arc`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) and " -"[`Mutex`](https://doc.rust-lang.org/std/rc/struct.Weak.html) if you are in a " -"multi-threaded context." +"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/std/rc.md:21 -msgid "" -"You can _downgrade_ a shared pointer into a \\[`Weak`\\]\\[5\\] pointer to " -"create cycles that will get dropped." -msgstr "" - -#: src/std/rc.md:32 +#: src/std/rc.md:29 msgid "" "`Rc`'s count ensures that its contained value is valid for as long as there " "are references." msgstr "" -#: src/std/rc.md:33 +#: src/std/rc.md:30 msgid "`Rc` in Rust is like `std::shared_ptr` in C++." msgstr "" -#: src/std/rc.md:34 +#: src/std/rc.md:31 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/std/rc.md:35 +#: src/std/rc.md:32 msgid "" "`make_mut` actually clones the inner value if necessary (\"clone-on-write\") " "and returns a mutable reference." msgstr "" -#: src/std/rc.md:36 +#: src/std/rc.md:33 msgid "Use `Rc::strong_count` to check the reference count." msgstr "" -#: src/std/rc.md:37 -msgid "" -"Compare the different datatypes mentioned. `Box` enables (im)mutable borrows " -"that are enforced at compile time. `RefCell` enables (im)mutable borrows " -"that are enforced at run time and will panic if it fails at runtime." -msgstr "" - -#: src/std/rc.md:38 +#: src/std/rc.md:34 msgid "" "`Rc::downgrade` gives you a _weakly reference-counted_ object to create " -"cycles that will be dropped properly (likely in combination with `RefCell`)." +"cycles that will be dropped properly (likely in combination with `RefCell`, " +"on the next slide)." msgstr "" -#: src/std/rc.md:42 +#: src/std/cell.md:1 +msgid "`Cell` and `RefCell`" +msgstr "" + +#: src/std/cell.md:3 +msgid "" +"[`Cell`](https://doc.rust-lang.org/std/cell/struct.Cell.html) and [`RefCell`]" +"(https://doc.rust-lang.org/std/cell/struct.RefCell.html) implement what Rust " +"calls _interior mutability:_ mutation of values in an immutable context." +msgstr "" + +#: src/std/cell.md:8 +msgid "" +"`Cell` is typically used for simple types, as it requires copying or moving " +"values. More complex interior types typically use `RefCell`, which tracks " +"shared and exclusive references at runtime and panics if they are misused." +msgstr "" + +#: src/std/cell.md:12 msgid "" "```rust,editable\n" -"use std::rc::{Rc, Weak};\n" "use std::cell::RefCell;\n" +"use std::rc::Rc;\n" "\n" -"#[derive(Debug)]\n" +"#[derive(Debug, Default)]\n" "struct Node {\n" " value: i64,\n" -" parent: Option>>,\n" " children: Vec>>,\n" "}\n" "\n" +"impl Node {\n" +" fn new(value: i64) -> Rc> {\n" +" Rc::new(RefCell::new(Node { value, ..Node::default() }))\n" +" }\n" +"\n" +" fn sum(&self) -> i64 {\n" +" self.value + self.children.iter().map(|c| c.borrow().sum()).sum::" +"()\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let mut root = Rc::new(RefCell::new(Node {\n" -" value: 42,\n" -" parent: None,\n" -" children: vec![],\n" -" }));\n" -" let child = Rc::new(RefCell::new(Node {\n" -" value: 43,\n" -" children: vec![],\n" -" parent: Some(Rc::downgrade(&root))\n" -" }));\n" -" root.borrow_mut().children.push(child);\n" +" let root = Node::new(1);\n" +" root.borrow_mut().children.push(Node::new(5));\n" +" let subtree = Node::new(10);\n" +" subtree.borrow_mut().children.push(Node::new(11));\n" +" subtree.borrow_mut().children.push(Node::new(12));\n" +" root.borrow_mut().children.push(subtree);\n" "\n" " println!(\"graph: {root:#?}\");\n" +" println!(\"graph sum: {}\", root.borrow().sum());\n" "}\n" "```" msgstr "" +#: src/std/cell.md:47 +msgid "" +"If we were using `Cell` instead of `RefCell` in this example, we would have " +"to move the `Node` out of the `Rc` to push children, then move it back in. " +"This is safe because there's always one, un-referenced value in the cell, " +"but it's not ergonomic." +msgstr "" + +#: src/std/cell.md:48 +msgid "" +"To do anything with a Node, you must call a `RefCell` method, usually " +"`borrow` or `borrow_mut`." +msgstr "" + +#: src/std/cell.md:49 +msgid "" +"Demonstrate that reference loops can be created by adding `root` to `subtree." +"children` (don't try to print it!)." +msgstr "" + +#: src/std/cell.md:50 +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'`." +msgstr "" + #: src/modules.md:3 msgid "We have seen how `impl` blocks let us namespace functions to a type." msgstr "" @@ -8191,26 +7467,11 @@ msgid "" "will typically see something like this at the top of each module:" msgstr "" -#: src/modules/paths.md:16 -msgid "" -"```rust,editable\n" -"use std::collections::HashSet;\n" -"use std::mem::transmute;\n" -"```" -msgstr "" - #: src/modules/filesystem.md:3 msgid "" "Omitting the module content will tell Rust to look for it in another file:" msgstr "" -#: src/modules/filesystem.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"mod garden;\n" -"```" -msgstr "" - #: src/modules/filesystem.md:9 msgid "" "This tells rust that the `garden` module content is found at `src/garden." @@ -8272,17 +7533,6 @@ msgstr "" msgid "Deeper nesting can use folders, even if the main module is a file:" msgstr "" -#: src/modules/filesystem.md:44 -msgid "" -"```ignore\n" -"src/\n" -"├── main.rs\n" -"├── top_module.rs\n" -"└── top_module/\n" -" └── sub_module.rs\n" -"```" -msgstr "" - #: src/modules/filesystem.md:52 msgid "" "The place rust will look for modules can be changed with a compiler " @@ -8311,95 +7561,156 @@ msgstr "" msgid "The exercises for this afternoon will focus on strings and iterators." msgstr "" -#: src/exercises/day-2/luhn.md:3 +#: src/exercises/day-2/iterators-and-ownership.md:3 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:" +"The ownership model of Rust affects many APIs. An example of this is the " +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and " +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html) " +"traits." msgstr "" -#: src/exercises/day-2/luhn.md:7 -msgid "Ignore all spaces. Reject number with less than two digits." +#: src/exercises/day-2/iterators-and-ownership.md:8 src/bare-metal/no_std.md:28 +msgid "`Iterator`" msgstr "" -#: src/exercises/day-2/luhn.md:9 +#: src/exercises/day-2/iterators-and-ownership.md:10 msgid "" -"Moving from right to left, double every second digit: for the number `1234`, " -"we double `3` and `1`." +"Traits are like interfaces: they describe behavior (methods) for a type. The " +"`Iterator` trait simply says that you can call `next` until you get `None` " +"back:" msgstr "" -#: src/exercises/day-2/luhn.md:12 +#: src/exercises/day-2/iterators-and-ownership.md:20 +msgid "You use this trait like this:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:22 msgid "" -"After doubling a digit, sum the digits. So doubling `7` becomes `14` which " -"becomes `5`." -msgstr "" - -#: src/exercises/day-2/luhn.md:15 -msgid "Sum all the undoubled and doubled digits." -msgstr "" - -#: src/exercises/day-2/luhn.md:17 -msgid "The credit card number is valid if the sum ends with `0`." -msgstr "" - -#: src/exercises/day-2/luhn.md:19 -msgid "" -"Copy the following code to and implement the " -"function:" -msgstr "" - -#: src/exercises/day-2/luhn.md:23 -msgid "" -"```rust\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]\n" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" "\n" -"pub fn luhn(cc_number: &str) -> bool {\n" -" unimplemented!()\n" +" println!(\"v[0]: {:?}\", iter.next());\n" +" println!(\"v[1]: {:?}\", iter.next());\n" +" println!(\"v[2]: {:?}\", iter.next());\n" +" println!(\"No more items: {:?}\", iter.next());\n" "}\n" -"\n" -"#[test]\n" -"fn test_non_digit_cc_number() {\n" -" assert!(!luhn(\"foo\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_empty_cc_number() {\n" -" assert!(!luhn(\"\"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_single_digit_cc_number() {\n" -" assert!(!luhn(\"0\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_two_digit_cc_number() {\n" -" assert!(luhn(\" 0 0 \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_valid_cc_number() {\n" -" assert!(luhn(\"4263 9826 4026 9299\"));\n" -" assert!(luhn(\"4539 3195 0343 6467\"));\n" -" assert!(luhn(\"7992 7398 713\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_invalid_cc_number() {\n" -" assert!(!luhn(\"4223 9826 4026 9299\"));\n" -" assert!(!luhn(\"4539 3195 0343 6476\"));\n" -" assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}\n" -"\n" -"#[allow(dead_code)]\n" -"fn main() {}\n" "```" msgstr "" +#: src/exercises/day-2/iterators-and-ownership.md:34 +msgid "What is the type returned by the iterator? Test your answer here:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:36 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:46 +msgid "Why is this type used?" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:48 +msgid "`IntoIterator`" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:50 +msgid "" +"The `Iterator` trait tells you how to _iterate_ once you have created an " +"iterator. The related trait `IntoIterator` tells you how to create the " +"iterator:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:62 +msgid "" +"The syntax here means that every implementation of `IntoIterator` must " +"declare two types:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:65 +msgid "`Item`: the type we iterate over, such as `i8`," +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:66 +msgid "`IntoIter`: the `Iterator` type returned by the `into_iter` method." +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:68 +msgid "" +"Note that `IntoIter` and `Item` are linked: the iterator must have the same " +"`Item` type, which means that it returns `Option`" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:71 +msgid "Like before, what is the type returned by the iterator?" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:73 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::" +"from(\"bar\")];\n" +" let mut iter = v.into_iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:83 +msgid "`for` Loops" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:85 +msgid "" +"Now that we know both `Iterator` and `IntoIterator`, we can build `for` " +"loops. They call `into_iter()` on an expression and iterates over the " +"resulting iterator:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:89 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::" +"from(\"bar\")];\n" +"\n" +" for word in &v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"\n" +" for word in v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:103 +msgid "What is the type of `word` in each loop?" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:105 +msgid "" +"Experiment with the code above and then consult the documentation for [`impl " +"IntoIterator for &Vec`](https://doc.rust-lang.org/std/vec/struct.Vec." +"html#impl-IntoIterator-for-%26'a+Vec%3CT,+A%3E) and [`impl IntoIterator for " +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-" +"for-Vec%3CT,+A%3E) to check your answers." +msgstr "" + #: src/exercises/day-2/strings-iterators.md:3 msgid "" "In this exercise, you are implementing a routing component of a web server. " @@ -8587,40 +7898,10 @@ msgstr "" msgid "Generic code is turned into non-generic code based on the call sites:" msgstr "" -#: src/generics/monomorphization.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let integer = Some(5);\n" -" let float = Some(5.0);\n" -"}\n" -"```" -msgstr "" - #: src/generics/monomorphization.md:12 msgid "behaves as if you wrote" msgstr "" -#: src/generics/monomorphization.md:14 -msgid "" -"```rust,editable\n" -"enum Option_i32 {\n" -" Some(i32),\n" -" None,\n" -"}\n" -"\n" -"enum Option_f64 {\n" -" Some(f64),\n" -" None,\n" -"}\n" -"\n" -"fn main() {\n" -" let integer = Option_i32::Some(5);\n" -" let float = Option_f64::Some(5.0);\n" -"}\n" -"```" -msgstr "" - #: src/generics/monomorphization.md:31 msgid "" "This is a zero-cost abstraction: you get exactly the same result as if you " @@ -8635,39 +7916,32 @@ msgstr "" #: src/traits.md:5 msgid "" "```rust,editable\n" +"struct Dog { name: String, age: i8 }\n" +"struct Cat { lives: i8 } // No name needed, cats won't respond anyway.\n" +"\n" "trait Pet {\n" -" fn name(&self) -> String;\n" +" fn talk(&self) -> String;\n" "}\n" "\n" -"struct Dog {\n" -" name: String,\n" -"}\n" -"\n" -"struct Cat;\n" -"\n" "impl Pet for Dog {\n" -" fn name(&self) -> String {\n" -" self.name.clone()\n" -" }\n" +" fn talk(&self) -> String { format!(\"Woof, my name is {}!\", self." +"name) }\n" "}\n" "\n" "impl Pet for Cat {\n" -" fn name(&self) -> String {\n" -" String::from(\"The cat\") // No name, cats won't respond to it " -"anyway.\n" -" }\n" +" fn talk(&self) -> String { String::from(\"Miau!\") }\n" "}\n" "\n" "fn greet(pet: &P) {\n" -" println!(\"Who's a cutie? {} is!\", pet.name());\n" +" println!(\"Oh you're a cutie! What's your name? {}\", pet.talk());\n" "}\n" "\n" "fn main() {\n" -" let fido = Dog { name: \"Fido\".into() };\n" -" greet(&fido);\n" +" let captain_floof = Cat { lives: 9 };\n" +" let fido = Dog { name: String::from(\"Fido\"), age: 5 };\n" "\n" -" let captain_floof = Cat;\n" " greet(&captain_floof);\n" +" greet(&fido);\n" "}\n" "```" msgstr "" @@ -8681,122 +7955,136 @@ msgstr "" #: src/traits/trait-objects.md:5 msgid "" "```rust,editable\n" +"struct Dog { name: String, age: i8 }\n" +"struct Cat { lives: i8 } // No name needed, cats won't respond anyway.\n" +"\n" "trait Pet {\n" -" fn name(&self) -> String;\n" +" fn talk(&self) -> String;\n" "}\n" "\n" -"struct Dog {\n" -" name: String,\n" -"}\n" -"\n" -"struct Cat;\n" -"\n" "impl Pet for Dog {\n" -" fn name(&self) -> String {\n" -" self.name.clone()\n" -" }\n" +" fn talk(&self) -> String { format!(\"Woof, my name is {}!\", self." +"name) }\n" "}\n" "\n" "impl Pet for Cat {\n" -" fn name(&self) -> String {\n" -" String::from(\"The cat\") // No name, cats won't respond to it " -"anyway.\n" -" }\n" +" fn talk(&self) -> String { String::from(\"Miau!\") }\n" "}\n" "\n" "fn main() {\n" " let pets: Vec> = vec![\n" -" Box::new(Cat),\n" -" Box::new(Dog { name: String::from(\"Fido\") }),\n" +" Box::new(Cat { lives: 9 }),\n" +" Box::new(Dog { name: String::from(\"Fido\"), age: 5 }),\n" " ];\n" " for pet in pets {\n" -" println!(\"Hello {}!\", pet.name());\n" +" println!(\"Hello, who are you? {}\", pet.talk());\n" " }\n" "}\n" "```" msgstr "" -#: src/traits/trait-objects.md:40 +#: src/traits/trait-objects.md:32 msgid "Memory layout after allocating `pets`:" msgstr "" -#: src/traits/trait-objects.md:42 +#: src/traits/trait-objects.md:34 msgid "" "```bob\n" " Stack Heap\n" ".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - " "- -.\n" ": : : :\n" -": " -"pets : : :\n" -": +-----------+-------+ : : +-----+-----" -"+ :\n" -": | ptr | o---+---+-----+-->| o o | o o " -"| :\n" -": | len | 2 | : : +-|-|-+-|-|-" -"+ :\n" -": | capacity | 2 | : : | | | | +---------------" -"+ :\n" -": +-----------+-------+ : : | | | '-->| name: \"Fido\" " -"| :\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" -" : | | '---->| \"::name\" " +"+ :\n" +" : | | '---->| \"::talk\" " "| :\n" " : | | +----------------------" -"+ : \n" +"+ :\n" " : | " -"| : \n" -" : | | +-" -"+ : \n" -" : | '-->|" -"\\| : \n" -" : | +-" -"+ : \n" +"| :\n" +" : | | " +"data :\n" +" : | | +-------+-------" +"+ :\n" +" : | '-->| lives | 9 " +"| :\n" +" : | +-------+-------" +"+ :\n" " : " -"| : \n" +"| :\n" +" : | " +"vtable :\n" " : | +----------------------" -"+ : \n" -" : '---->| \"::name\" " -"| : \n" +"+ :\n" +" : '---->| \"::talk\" " +"| :\n" " : +----------------------" "+ :\n" " : :\n" " '- - - - - - - - - - - - - - - - - - - - - " "- -'\n" -"\n" "```" msgstr "" -#: src/traits/trait-objects.md:72 +#: src/traits/trait-objects.md:68 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." +"impossible to have things like `Vec` in the example above." msgstr "" -#: src/traits/trait-objects.md:73 +#: src/traits/trait-objects.md:70 msgid "" "`dyn Pet` is a way to tell the compiler about a dynamically sized type that " "implements `Pet`." msgstr "" -#: src/traits/trait-objects.md:74 +#: src/traits/trait-objects.md:72 msgid "" -"In the example, `pets` holds _fat pointers_ to objects that implement `Pet`. " -"The fat pointer consists of two components, a pointer to the actual object " -"and a pointer to the virtual method table for the `Pet` implementation of " -"that particular object." +"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/traits/trait-objects.md:75 +#: src/traits/trait-objects.md:74 +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/traits/trait-objects.md:77 +msgid "" +"The data for the `Dog` named Fido is the `name` and `age` fields. The `Cat` " +"has a `lives` field." +msgstr "" + +#: src/traits/trait-objects.md:79 msgid "Compare these outputs in the above example:" msgstr "" -#: src/traits/trait-objects.md:76 +#: src/traits/trait-objects.md:80 msgid "" "```rust,ignore\n" " println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::" @@ -8884,36 +8172,10 @@ msgstr "" msgid "Make `Equals` a super trait for `NotEquals`." msgstr "" -#: src/traits/default-methods.md:38 -msgid "" -"```rust,editable,compile_fail\n" -"trait NotEquals: Equals {\n" -" fn not_equals(&self, other: &Self) -> bool {\n" -" !self.equals(other)\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/traits/default-methods.md:46 msgid "Provide a blanket implementation of `NotEquals` for `Equals`." msgstr "" -#: src/traits/default-methods.md:47 -msgid "" -"```rust,editable,compile_fail\n" -"trait NotEquals {\n" -" fn not_equals(&self, other: &Self) -> bool;\n" -"}\n" -"\n" -"impl NotEquals for T where T: Equals {\n" -" fn not_equals(&self, other: &Self) -> bool {\n" -" !self.equals(other)\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/traits/default-methods.md:58 msgid "" "With the blanket implementation, you no longer need `Equals` as a super " @@ -8962,18 +8224,6 @@ msgstr "" msgid "Show a `where` clause, students will encounter it when reading code." msgstr "" -#: src/traits/trait-bounds.md:37 -msgid "" -"```rust,ignore\n" -"fn duplicate(a: T) -> (T, T)\n" -"where\n" -" T: Clone,\n" -"{\n" -" (a.clone(), a.clone())\n" -"}\n" -"```" -msgstr "" - #: src/traits/trait-bounds.md:46 msgid "It declutters the function signature if you have many parameters." msgstr "" @@ -9173,17 +8423,18 @@ msgid "" " .into_iter()\n" " .map(|prime| prime * prime)\n" " .collect::>();\n" +" println!(\"prime_squares: {prime_squares:?}\");\n" "}\n" "```" msgstr "" -#: src/traits/from-iterator.md:17 +#: src/traits/from-iterator.md:18 msgid "" "`Iterator` implements `fn collect(self) -> B where B: FromIterator, Self: Sized`" msgstr "" -#: src/traits/from-iterator.md:23 +#: src/traits/from-iterator.md:24 msgid "" "There are also implementations which let you do cool things like convert an " "`Iterator>` into a `Result, E>`." @@ -9345,21 +8596,54 @@ msgid "" "```" msgstr "" -#: src/traits/drop.md:34 src/traits/operators.md:26 -msgid "Discussion points:" +#: src/traits/drop.md:34 +msgid "Note that `std::mem::drop` is not the same as `std::ops::Drop::drop`." +msgstr "" + +#: src/traits/drop.md:35 +msgid "Values are automatically dropped when they go out of scope." msgstr "" #: src/traits/drop.md:36 +msgid "" +"When a value is dropped, if it implements `std::ops::Drop` then its `Drop::" +"drop` implementation will be called." +msgstr "" + +#: src/traits/drop.md:38 +msgid "" +"All its fields will then be dropped too, whether or not it implements `Drop`." +msgstr "" + +#: src/traits/drop.md:39 +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/traits/drop.md:42 +msgid "" +"This can be useful for objects that do some work on `drop`: releasing locks, " +"closing files, etc." +msgstr "" + +#: src/traits/drop.md:45 src/traits/operators.md:26 +msgid "Discussion points:" +msgstr "" + +#: src/traits/drop.md:47 msgid "Why doesn't `Drop::drop` take `self`?" msgstr "" -#: src/traits/drop.md:37 +#: src/traits/drop.md:48 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/traits/drop.md:40 +#: src/traits/drop.md:51 msgid "Try replacing `drop(a)` with `a.drop()`." msgstr "" @@ -9606,13 +8890,26 @@ msgid "Day 3: Morning Exercises" msgstr "" #: src/exercises/day-3/morning.md:3 -msgid "We will design a classical GUI library traits and trait objects." +msgid "We will design a classical GUI library using traits and trait objects." msgstr "" +#: src/exercises/day-3/morning.md:5 +msgid "" +"We will also look at enum dispatch with an exercise involving points and " +"polygons." +msgstr "" + +#: src/exercises/day-3/simple-gui.md:1 +#: src/exercises/day-3/solutions-morning.md:3 +#, fuzzy +msgid "Drawing A Simple GUI" +msgstr "یک کتابخانه GUI ساده" + #: src/exercises/day-3/simple-gui.md:3 msgid "" "Let us design a classical GUI library using our new knowledge of traits and " -"trait objects." +"trait objects. We'll only implement the drawing of it (as text) for " +"simplicity." msgstr "" #: src/exercises/day-3/simple-gui.md:6 @@ -9625,25 +8922,26 @@ msgstr "" #: src/exercises/day-3/simple-gui.md:9 msgid "" -"`Button`: has a `label` and a callback function which is invoked when the " -"button is pressed." +"`Button`: has a `label`. In reality, it would also take a callback function " +"to allow the program to do something when the button is clicked but we won't " +"include that since we're only drawing the GUI." msgstr "" -#: src/exercises/day-3/simple-gui.md:11 +#: src/exercises/day-3/simple-gui.md:12 msgid "`Label`: has a `label`." msgstr "" -#: src/exercises/day-3/simple-gui.md:13 +#: src/exercises/day-3/simple-gui.md:14 msgid "The widgets will implement a `Widget` trait, see below." msgstr "" -#: src/exercises/day-3/simple-gui.md:15 +#: src/exercises/day-3/simple-gui.md:16 msgid "" "Copy the code below to , fill in the missing " "`draw_into` methods so that you implement the `Widget` trait:" msgstr "" -#: src/exercises/day-3/simple-gui.md:18 +#: src/exercises/day-3/simple-gui.md:19 msgid "" "```rust,should_panic\n" "// TODO: remove this when you're done with your implementation.\n" @@ -9678,14 +8976,12 @@ msgid "" "\n" "pub struct Button {\n" " label: Label,\n" -" callback: Box,\n" "}\n" "\n" "impl Button {\n" -" fn new(label: &str, callback: Box) -> Button {\n" +" fn new(label: &str) -> Button {\n" " Button {\n" " label: Label::new(label),\n" -" callback,\n" " }\n" " }\n" "}\n" @@ -9751,32 +9047,18 @@ msgid "" " window.add_widget(Box::new(Label::new(\"This is a small text GUI demo." "\")));\n" " window.add_widget(Box::new(Button::new(\n" -" \"Click me!\",\n" -" Box::new(|| println!(\"You clicked the button!\")),\n" +" \"Click me!\"\n" " )));\n" " window.draw();\n" "}\n" "```" msgstr "" -#: src/exercises/day-3/simple-gui.md:130 +#: src/exercises/day-3/simple-gui.md:128 msgid "The output of the above program can be something simple like this:" msgstr "" -#: src/exercises/day-3/simple-gui.md:132 -msgid "" -"```text\n" -"========\n" -"Rust GUI Demo 1.23\n" -"========\n" -"\n" -"This is a small text GUI demo.\n" -"\n" -"| Click me! |\n" -"```" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:142 +#: src/exercises/day-3/simple-gui.md:140 msgid "" "If you want to draw aligned text, you can use the [fill/alignment](https://" "doc.rust-lang.org/std/fmt/index.html#fillalignment) formatting operators. In " @@ -9784,7 +9066,7 @@ msgid "" "and how you can control alignment:" msgstr "" -#: src/exercises/day-3/simple-gui.md:147 +#: src/exercises/day-3/simple-gui.md:145 msgid "" "```rust,editable\n" "fn main() {\n" @@ -9796,25 +9078,156 @@ msgid "" "```" msgstr "" -#: src/exercises/day-3/simple-gui.md:156 +#: src/exercises/day-3/simple-gui.md:154 msgid "" "Using such alignment tricks, you can for example produce output like this:" msgstr "" -#: src/exercises/day-3/simple-gui.md:158 +#: src/exercises/day-3/points-polygons.md:1 +msgid "Polygon Struct" +msgstr "" + +#: src/exercises/day-3/points-polygons.md:3 msgid "" -"```text\n" -"+--------------------------------+\n" -"| Rust GUI Demo 1.23 |\n" -"+================================+\n" -"| This is a small text GUI demo. |\n" -"| +-----------+ |\n" -"| | Click me! | |\n" -"| +-----------+ |\n" -"+--------------------------------+\n" +"We will create a `Polygon` struct which contain some points. Copy the code " +"below to and fill in the missing methods to " +"make the tests pass:" +msgstr "" + +#: src/exercises/day-3/points-polygons.md:7 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub struct Point {\n" +" // add fields\n" +"}\n" +"\n" +"impl Point {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Polygon {\n" +" // add fields\n" +"}\n" +"\n" +"impl Polygon {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Circle {\n" +" // add fields\n" +"}\n" +"\n" +"impl Circle {\n" +" // add methods\n" +"}\n" +"\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" "```" msgstr "" +#: src/exercises/day-3/points-polygons.md:117 +msgid "" +"Since the method signatures are missing from the problem statements, the key " +"part of the exercise is to specify those correctly. You don't have to modify " +"the tests." +msgstr "" + +#: src/exercises/day-3/points-polygons.md:120 +msgid "Other interesting parts of the exercise:" +msgstr "" + +#: src/exercises/day-3/points-polygons.md:122 +msgid "" +"Derive a `Copy` trait for some structs, as in tests the methods sometimes " +"don't borrow their arguments." +msgstr "" + +#: src/exercises/day-3/points-polygons.md:123 +msgid "" +"Discover that `Add` trait must be implemented for two objects to be addable " +"via \"+\". Note that we do not discuss generics until Day 3." +msgstr "" + #: src/error-handling.md:3 msgid "Error handling in Rust is done using explicit control flow:" msgstr "" @@ -9871,14 +9284,14 @@ msgid "" "\n" "fn main() {\n" " let result = panic::catch_unwind(|| {\n" -" println!(\"hello!\");\n" +" \"No problem here!\"\n" " });\n" -" assert!(result.is_ok());\n" -" \n" +" println!(\"{result:?}\");\n" +"\n" " let result = panic::catch_unwind(|| {\n" " panic!(\"oh no!\");\n" " });\n" -" assert!(result.is_err());\n" +" println!(\"{result:?}\");\n" "}\n" "```" msgstr "" @@ -9950,27 +9363,10 @@ msgid "" "turn the common" msgstr "" -#: src/error-handling/try-operator.md:6 -msgid "" -"```rust,ignore\n" -"match some_expression {\n" -" Ok(value) => value,\n" -" Err(err) => return Err(err),\n" -"}\n" -"```" -msgstr "" - #: src/error-handling/try-operator.md:13 msgid "into the much simpler" msgstr "" -#: src/error-handling/try-operator.md:15 -msgid "" -"```rust,ignore\n" -"some_expression?\n" -"```" -msgstr "" - #: src/error-handling/try-operator.md:19 msgid "We can use this to simplify our error handling code:" msgstr "" @@ -10020,10 +9416,10 @@ msgid "" "The return type of the function has to be compatible with the nested " "functions it calls. For instance, a function returning a `Result` " "can only apply the `?` operator on a function returning a `Result`. It cannot apply the `?` operator on a function returning a `Result` or an `Option`. Reciprocally, a function returning an " -"`Option` can only apply the `?` operator on a function returning an " -"`Option`." +"Err>`. It cannot apply the `?` operator on a function returning an " +"`Option` or `Result` unless `OtherErr` implements " +"`From`. Reciprocally, a function returning an `Option` can only " +"apply the `?` operator on a function returning an `Option`." msgstr "" #: src/error-handling/try-operator.md:57 @@ -10039,27 +9435,10 @@ msgid "" "indicated:" msgstr "" -#: src/error-handling/converting-error-types.md:5 -msgid "" -"```rust,ignore\n" -"expression?\n" -"```" -msgstr "" - #: src/error-handling/converting-error-types.md:9 msgid "works the same as" msgstr "" -#: src/error-handling/converting-error-types.md:11 -msgid "" -"```rust,ignore\n" -"match expression {\n" -" Ok(value) => value,\n" -" Err(err) => return Err(From::from(err)),\n" -"}\n" -"```" -msgstr "" - #: src/error-handling/converting-error-types.md:18 msgid "" "The `From::from` call here means we attempt to convert the error type to the " @@ -10381,7 +9760,7 @@ msgid "" "/// Shortens a string to the given length.\n" "///\n" "/// ```\n" -"/// use playground::shorten_string;\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" @@ -10401,6 +9780,12 @@ msgstr "" #: src/testing/doc-tests.md:20 msgid "" +"Adding `# ` in the code will hide it from the docs, but will still compile/" +"run it." +msgstr "" + +#: src/testing/doc-tests.md:21 +msgid "" "Test the above code on the [Rust Playground](https://play.rust-lang.org/?" "version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." msgstr "" @@ -10413,18 +9798,6 @@ msgstr "" msgid "Create a `.rs` file under `tests/`:" msgstr "" -#: src/testing/integration-tests.md:7 -msgid "" -"```rust,ignore\n" -"use my_library::init;\n" -"\n" -"#[test]\n" -"fn test_init() {\n" -" assert!(init().is_ok());\n" -"}\n" -"```" -msgstr "" - #: src/testing/integration-tests.md:16 msgid "These tests only have access to the public API of your crate." msgstr "" @@ -10631,6 +10004,14 @@ msgstr "" #: src/unsafe/mutable-static-variables.md:32 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." +msgstr "" + +#: src/unsafe/mutable-static-variables.md:36 +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." @@ -10702,7 +10083,7 @@ msgid "" "}\n" "\n" "fn count_chars(s: &str) -> usize {\n" -" s.chars().map(|_| 1).sum()\n" +" s.chars().count()\n" "}\n" "```" msgstr "" @@ -10874,7 +10255,7 @@ msgstr "" 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 filenames of a directory." +"functions you would use from C to read the names of files in a directory." msgstr "" #: src/exercises/day-3/safe-ffi-wrapper.md:7 @@ -10973,7 +10354,7 @@ msgstr "" #: src/exercises/day-3/safe-ffi-wrapper.md:27 msgid "" "`&CStr` to `&[u8]`: a slice of bytes is the universal interface for \"some " -"unknow data\"," +"unknown data\"," msgstr "" #: src/exercises/day-3/safe-ffi-wrapper.md:28 @@ -11132,15 +10513,6 @@ msgid "" "have access to one or create a new one with:" msgstr "" -#: src/android/setup.md:6 -msgid "" -"```shell\n" -"source build/envsetup.sh\n" -"lunch aosp_cf_x86_64_phone-userdebug\n" -"acloud create\n" -"```" -msgstr "" - #: src/android/setup.md:12 msgid "" "Please see the [Android Developer Codelab](https://source.android.com/docs/" @@ -11289,13 +10661,6 @@ msgid "" "```" msgstr "" -#: src/android/build-rules/binary.md:35 -msgid "" -"```text\n" -"Hello from Rust!\n" -"```" -msgstr "" - #: src/android/build-rules/library.md:1 msgid "Rust Libraries" msgstr "" @@ -11386,14 +10751,6 @@ msgid "" "```" msgstr "" -#: src/android/build-rules/library.md:67 -msgid "" -"```text\n" -"Hello Bob, it is very\n" -"nice to meet you!\n" -"```" -msgstr "" - #: src/android/aidl.md:3 msgid "" "The [Android Interface Definition Language (AIDL)](https://developer.android." @@ -11421,19 +10778,6 @@ msgid "" "_birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl_:" msgstr "" -#: src/android/aidl/interface.md:7 -msgid "" -"```java\n" -"package com.example.birthdayservice;\n" -"\n" -"/** Birthday service interface. */\n" -"interface IBirthdayService {\n" -" /** Generate a Happy Birthday message. */\n" -" String wishHappyBirthday(String name, int years);\n" -"}\n" -"```" -msgstr "" - #: src/android/aidl/interface.md:17 msgid "_birthday_service/aidl/Android.bp_:" msgstr "" @@ -11590,46 +10934,10 @@ msgstr "" msgid "In another terminal, check that the service runs:" msgstr "" -#: src/android/aidl/deploy.md:13 -msgid "" -"```shell\n" -"adb shell service check birthdayservice\n" -"```" -msgstr "" - -#: src/android/aidl/deploy.md:17 -msgid "" -"```text\n" -"Service birthdayservice: found\n" -"```" -msgstr "" - #: src/android/aidl/deploy.md:21 msgid "You can also call the service with `service call`:" msgstr "" -#: src/android/aidl/deploy.md:23 -msgid "" -"```shell\n" -"adb shell service call birthdayservice 1 s16 Bob i32 24\n" -"```" -msgstr "" - -#: src/android/aidl/deploy.md:27 -msgid "" -"```text\n" -"Result: Parcel(\n" -" 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" -" 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" -" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'\n" -" 0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'\n" -" 0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'\n" -" 0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'\n" -" 0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'\n" -" 0x00000070: 00210073 00000000 's.!..... ')\n" -"```" -msgstr "" - #: src/android/aidl/client.md:1 msgid "AIDL Client" msgstr "" @@ -11712,32 +11020,12 @@ msgid "" "```" msgstr "" -#: src/android/aidl/client.md:62 -msgid "" -"```text\n" -"Happy Birthday Charlie, congratulations with the 60 years!\n" -"```" -msgstr "" - #: src/android/aidl/changing.md:3 msgid "" "Let us extend the API with more functionality: we want to let clients " "specify a list of lines for the birthday card:" msgstr "" -#: src/android/aidl/changing.md:6 -msgid "" -"```java\n" -"package com.example.birthdayservice;\n" -"\n" -"/** Birthday service interface. */\n" -"interface IBirthdayService {\n" -" /** Generate a Happy Birthday message. */\n" -" String wishHappyBirthday(String name, int years, in String[] text);\n" -"}\n" -"```" -msgstr "" - #: src/android/logging.md:3 msgid "" "You should use the `log` crate to automatically log to `logcat` (on-device) " @@ -11809,24 +11097,6 @@ msgstr "" msgid "The logs show up in `adb logcat`:" msgstr "" -#: src/android/logging.md:52 -msgid "" -"```shell\n" -"adb logcat -s rust\n" -"```" -msgstr "" - -#: src/android/logging.md:56 -msgid "" -"```text\n" -"09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.\n" -"09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going " -"fine.\n" -"09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went " -"wrong!\n" -"```" -msgstr "" - #: src/android/interoperability.md:3 msgid "" "Rust has excellent support for interoperability with other languages. This " @@ -11910,18 +11180,6 @@ msgstr "" msgid "_interoperability/bindgen/libbirthday.h_:" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:10 -msgid "" -"```c\n" -"typedef struct card {\n" -" const char* name;\n" -" int years;\n" -"} card;\n" -"\n" -"void print_card(const card* card);\n" -"```" -msgstr "" - #: src/android/interoperability/with-c/bindgen.md:19 msgid "_interoperability/bindgen/libbirthday.c_:" msgstr "" @@ -12064,13 +11322,6 @@ msgid "" "```" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:122 -msgid "" -"```shell\n" -"atest libbirthday_bindgen_test\n" -"```" -msgstr "" - #: src/android/interoperability/with-c/rust.md:1 msgid "Calling Rust" msgstr "" @@ -12206,6 +11457,42 @@ msgid "" "using this." msgstr "" +#: src/android/interoperability/cpp.md:14 +msgid "" +"At this point, the instructor should switch to the [CXX tutorial](https://" +"cxx.rs/tutorial.html)." +msgstr "" + +#: src/android/interoperability/cpp.md:16 +msgid "Walk the students through the tutorial step by step." +msgstr "" + +#: src/android/interoperability/cpp.md:18 +msgid "" +"Highlight how CXX presents a clean interface without unsafe code in _both " +"languages_." +msgstr "" + +#: src/android/interoperability/cpp.md:20 +msgid "" +"Show the correspondence between [Rust and C++ types](https://cxx.rs/bindings." +"html):" +msgstr "" + +#: src/android/interoperability/cpp.md:22 +msgid "" +"Explain how a Rust `String` cannot map to a C++ `std::string` (the latter " +"does not uphold the UTF-8 invariant). Show that despite being different " +"types, `rust::String` in C++ can be easily constructed from a C++ `std::" +"string`, making it very ergonomic to use." +msgstr "" + +#: src/android/interoperability/cpp.md:28 +msgid "" +"Explain that a Rust function returning `Result` becomes a function " +"which throws a `E` exception in C++ (and vice versa)." +msgstr "" + #: src/android/interoperability/java.md:1 msgid "Interoperability with Java" msgstr "" @@ -12308,15 +11595,6 @@ msgstr "" msgid "Finally, you can build, sync, and run the binary:" msgstr "" -#: src/android/interoperability/java.md:75 -msgid "" -"```shell\n" -"m helloworld_jni\n" -"adb sync # requires adb root && adb remount\n" -"adb shell /system/bin/helloworld_jni\n" -"```" -msgstr "" - #: src/exercises/android/morning.md:3 msgid "" "This is a group exercise: We will look at one of the projects you work with " @@ -12385,50 +11663,15 @@ msgid "" "To get started, install some tools we'll need later. On gLinux or Debian:" msgstr "" -#: src/bare-metal.md:22 -msgid "" -"```bash\n" -"sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom pkg-" -"config qemu-system-arm\n" -"rustup update\n" -"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" -"rustup component add llvm-tools-preview\n" -"cargo install cargo-binutils cargo-embed\n" -"```" -msgstr "" - #: src/bare-metal.md:30 msgid "" "And give users in the `plugdev` group access to the micro:bit programmer:" msgstr "" -#: src/bare-metal.md:32 -msgid "" -"```bash\n" -"echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", " -"GROUP=\"plugdev\"' |\\\n" -" sudo tee /etc/udev/rules.d/50-microbit.rules\n" -"sudo udevadm control --reload-rules\n" -"```" -msgstr "" - -#: src/bare-metal.md:38 +#: src/bare-metal.md:38 src/bare-metal/microcontrollers/debugging.md:27 msgid "On MacOS:" msgstr "" -#: src/bare-metal.md:40 -msgid "" -"```bash\n" -"xcode-select --install\n" -"brew install gdb picocom qemu\n" -"brew install --cask gcc-aarch64-embedded\n" -"rustup update\n" -"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" -"rustup component add llvm-tools-preview\n" -"cargo install cargo-binutils cargo-embed\n" -"```" -msgstr "" - #: src/bare-metal/no_std.md:1 msgid "`no_std`" msgstr "" @@ -12541,21 +11784,6 @@ msgstr "" msgid "A minimal `no_std` program" msgstr "" -#: src/bare-metal/minimal.md:3 -msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"use core::panic::PanicInfo;\n" -"\n" -"#[panic_handler]\n" -"fn panic(_panic: &PanicInfo) -> ! {\n" -" loop {}\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/minimal.md:17 msgid "This will compile to an empty binary." msgstr "" @@ -12658,25 +11886,6 @@ msgid "" "Cortex M microcontrollers." msgstr "" -#: src/bare-metal/microcontrollers.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate panic_halt as _;\n" -"\n" -"mod interrupts;\n" -"\n" -"use cortex_m_rt::entry;\n" -"\n" -"#[entry]\n" -"fn main() -> ! {\n" -" loop {}\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers.md:21 msgid "" "Next we'll look at how to access peripherals, with increasing levels of " @@ -12777,13 +11986,6 @@ msgstr "" msgid "Run the example with:" msgstr "" -#: src/bare-metal/microcontrollers/mmio.md:68 -msgid "" -"```sh\n" -"cargo embed --bin mmio\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/pacs.md:1 msgid "Peripheral Access Crates" msgstr "" @@ -12867,13 +12069,6 @@ msgid "" "pac -- -d --no-show-raw-insn` to see the resulting binary." msgstr "" -#: src/bare-metal/microcontrollers/pacs.md:61 -msgid "" -"```sh\n" -"cargo embed --bin pac\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/hals.md:1 msgid "HAL crates" msgstr "" @@ -12930,13 +12125,6 @@ msgid "" "STM32, GD32, nRF, NXP, MSP430, AVR and PIC microcontrollers." msgstr "" -#: src/bare-metal/microcontrollers/hals.md:45 -msgid "" -"```sh\n" -"cargo embed --bin hal\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/board-support.md:1 msgid "Board support crates" msgstr "" @@ -12947,30 +12135,6 @@ msgid "" "board for convenience." msgstr "" -#: src/bare-metal/microcontrollers/board-support.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate panic_halt as _;\n" -"\n" -"use cortex_m_rt::entry;\n" -"use microbit::hal::prelude::*;\n" -"use microbit::Board;\n" -"\n" -"#[entry]\n" -"fn main() -> ! {\n" -" let mut board = Board::take().unwrap();\n" -"\n" -" board.display_pins.col1.set_low().unwrap();\n" -" board.display_pins.row1.set_high().unwrap();\n" -"\n" -" loop {}\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/board-support.md:28 msgid "" "In this case the board support crate is just providing more useful names, " @@ -12987,13 +12151,6 @@ msgstr "" msgid "`microbit-v2` includes a simple driver for the LED matrix." msgstr "" -#: src/bare-metal/microcontrollers/board-support.md:36 -msgid "" -"```sh\n" -"cargo embed --bin board_support\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/type-state.md:1 msgid "The type state pattern" msgstr "" @@ -13126,23 +12283,12 @@ msgid "" msgstr "" #: src/bare-metal/microcontrollers/probe-rs.md:6 -msgid "SWD" -msgstr "" - -#: src/bare-metal/microcontrollers/probe-rs.md:6 -msgid " and JTAG via CMSIS-DAP, ST-Link and J-Link probes" +msgid "" +"SWD (Serial Wire Debug) and JTAG via CMSIS-DAP, ST-Link and J-Link probes" msgstr "" #: src/bare-metal/microcontrollers/probe-rs.md:7 -msgid "GDB stub and Microsoft " -msgstr "" - -#: src/bare-metal/microcontrollers/probe-rs.md:7 -msgid "DAP" -msgstr "" - -#: src/bare-metal/microcontrollers/probe-rs.md:7 -msgid " server" +msgid "GDB stub and Microsoft DAP (Debug Adapter Protocol) server" msgstr "" #: src/bare-metal/microcontrollers/probe-rs.md:8 @@ -13150,17 +12296,10 @@ msgid "Cargo integration" msgstr "" #: src/bare-metal/microcontrollers/probe-rs.md:10 -msgid "`cargo-embed` is a cargo subcommand to build and flash binaries, log " -msgstr "" - -#: src/bare-metal/microcontrollers/probe-rs.md:11 -msgid "RTT" -msgstr "" - -#: src/bare-metal/microcontrollers/probe-rs.md:11 msgid "" -" output and connect GDB. It's configured by an `Embed.toml` file in your " -"project directory." +"`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/bare-metal/microcontrollers/probe-rs.md:16 @@ -13207,59 +12346,25 @@ msgid "" msgstr "" #: src/bare-metal/microcontrollers/debugging.md:3 -msgid "Embed.toml:" -msgstr "" - -#: src/bare-metal/microcontrollers/debugging.md:5 -msgid "" -"```toml\n" -"[default.general]\n" -"chip = \"nrf52833_xxAA\"\n" -"\n" -"[debug.gdb]\n" -"enabled = true\n" -"```" +msgid "_Embed.toml_:" msgstr "" #: src/bare-metal/microcontrollers/debugging.md:13 msgid "In one terminal under `src/bare-metal/microcontrollers/examples/`:" msgstr "" -#: src/bare-metal/microcontrollers/debugging.md:15 -msgid "" -"```sh\n" -"cargo embed --bin board_support debug\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/debugging.md:19 msgid "In another terminal in the same directory:" msgstr "" #: src/bare-metal/microcontrollers/debugging.md:21 -msgid "" -"```sh\n" -"gdb-multiarch target/thumbv7em-none-eabihf/debug/board_support --eval-" -"command=\"target remote :1337\"\n" -"```" +msgid "On gLinux or Debian:" msgstr "" -#: src/bare-metal/microcontrollers/debugging.md:27 +#: src/bare-metal/microcontrollers/debugging.md:34 msgid "In GDB, try running:" msgstr "" -#: src/bare-metal/microcontrollers/debugging.md:29 -msgid "" -"```gdb\n" -"b src/bin/board_support.rs:29\n" -"b src/bin/board_support.rs:30\n" -"b src/bin/board_support.rs:32\n" -"c\n" -"c\n" -"c\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/other-projects.md:1 #: src/bare-metal/aps/other-projects.md:1 msgid "Other projects" @@ -13407,7 +12512,7 @@ msgid "" msgstr "" #: src/exercises/bare-metal/compass.md:26 src/exercises/bare-metal/rtc.md:19 -msgid "`src/main.rs`:" +msgid "_src/main.rs_:" msgstr "" #: src/exercises/bare-metal/compass.md:30 @@ -13448,85 +12553,26 @@ msgid "" msgstr "" #: src/exercises/bare-metal/compass.md:64 src/exercises/bare-metal/rtc.md:385 -msgid "`Cargo.toml` (you shouldn't need to change this):" -msgstr "" - -#: src/exercises/bare-metal/compass.md:68 -msgid "" -"```toml\n" -"[workspace]\n" -"\n" -"[package]\n" -"name = \"compass\"\n" -"version = \"0.1.0\"\n" -"edition = \"2021\"\n" -"publish = false\n" -"\n" -"[dependencies]\n" -"cortex-m-rt = \"0.7.3\"\n" -"embedded-hal = \"0.2.6\"\n" -"lsm303agr = \"0.2.2\"\n" -"microbit-v2 = \"0.13.0\"\n" -"panic-halt = \"0.2.0\"\n" -"```" +msgid "_Cargo.toml_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/compass.md:85 -msgid "`Embed.toml` (you shouldn't need to change this):" -msgstr "" - -#: src/exercises/bare-metal/compass.md:89 -msgid "" -"```toml\n" -"[default.general]\n" -"chip = \"nrf52833_xxAA\"\n" -"\n" -"[debug.gdb]\n" -"enabled = true\n" -"\n" -"[debug.reset]\n" -"halt_afterwards = true\n" -"```" +msgid "_Embed.toml_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/compass.md:100 src/exercises/bare-metal/rtc.md:985 -msgid "`.cargo/config.toml` (you shouldn't need to change this):" -msgstr "" - -#: src/exercises/bare-metal/compass.md:104 -msgid "" -"```toml\n" -"[build]\n" -"target = \"thumbv7em-none-eabihf\" # Cortex-M4F\n" -"\n" -"[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))']\n" -"rustflags = [\"-C\", \"link-arg=-Tlink.x\"]\n" -"```" +msgid "_.cargo/config.toml_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/compass.md:112 msgid "See the serial output on Linux with:" msgstr "" -#: src/exercises/bare-metal/compass.md:114 -msgid "" -"```sh\n" -"picocom --baud 115200 --imap lfcrlf /dev/ttyACM0\n" -"```" -msgstr "" - #: src/exercises/bare-metal/compass.md:118 msgid "" "Or on Mac OS something like (the device name may be slightly different):" msgstr "" -#: src/exercises/bare-metal/compass.md:120 -msgid "" -"```sh\n" -"picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502\n" -"```" -msgstr "" - #: src/exercises/bare-metal/compass.md:124 msgid "Use Ctrl+A Ctrl+Q to quit picocom." msgstr "" @@ -13677,7 +12723,7 @@ msgstr "" 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 cachable aliases to the same memory. Even if the host " +"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, " @@ -13712,15 +12758,8 @@ msgstr "" #: src/bare-metal/aps/inline-assembly.md:3 msgid "" "Sometimes we need to use assembly to do things that aren't possible with " -"Rust code. For example, to make an " -msgstr "" - -#: src/bare-metal/aps/inline-assembly.md:4 -msgid "HVC" -msgstr "" - -#: src/bare-metal/aps/inline-assembly.md:4 -msgid " to tell the firmware to power off the system:" +"Rust code. For example, to make an HVC (hypervisor call) to tell the " +"firmware to power off the system:" msgstr "" #: src/bare-metal/aps/inline-assembly.md:6 @@ -14205,43 +13244,6 @@ msgid "" "We can use a struct to represent the memory layout of the UART's registers." msgstr "" -#: src/bare-metal/aps/better-uart/registers.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"#[repr(C, align(4))]\n" -"struct Registers {\n" -" dr: u16,\n" -" _reserved0: [u8; 2],\n" -" rsr: ReceiveStatus,\n" -" _reserved1: [u8; 19],\n" -" fr: Flags,\n" -" _reserved2: [u8; 6],\n" -" ilpr: u8,\n" -" _reserved3: [u8; 3],\n" -" ibrd: u16,\n" -" _reserved4: [u8; 2],\n" -" fbrd: u8,\n" -" _reserved5: [u8; 3],\n" -" lcr_h: u8,\n" -" _reserved6: [u8; 3],\n" -" cr: u16,\n" -" _reserved7: [u8; 3],\n" -" ifls: u8,\n" -" _reserved8: [u8; 3],\n" -" imsc: u16,\n" -" _reserved9: [u8; 2],\n" -" ris: u16,\n" -" _reserved10: [u8; 2],\n" -" mis: u16,\n" -" _reserved11: [u8; 2],\n" -" icr: u16,\n" -" _reserved12: [u8; 2],\n" -" dmacr: u8,\n" -" _reserved13: [u8; 3],\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/aps/better-uart/registers.md:41 msgid "" "[`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-" @@ -14521,63 +13523,6 @@ msgid "" "calling into Rust code:" msgstr "" -#: src/bare-metal/aps/exceptions.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"use log::error;\n" -"use smccc::psci::system_off;\n" -"use smccc::Hvc;\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" -" error!(\"sync_exception_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" -" error!(\"irq_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" -" error!(\"fiq_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" -" error!(\"serr_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"sync_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"irq_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"fiq_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"serr_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/aps/exceptions.md:64 msgid "EL is exception level; all our examples this afternoon run in EL1." msgstr "" @@ -14664,7 +13609,7 @@ msgstr "" 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 cachable aliases to the same memory. Even if the host " +"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 " @@ -14688,43 +13633,6 @@ msgid "" "types." msgstr "" -#: src/bare-metal/useful-crates/zerocopy.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"use zerocopy::AsBytes;\n" -"\n" -"#[repr(u32)]\n" -"#[derive(AsBytes, Debug, Default)]\n" -"enum RequestType {\n" -" #[default]\n" -" In = 0,\n" -" Out = 1,\n" -" Flush = 4,\n" -"}\n" -"\n" -"#[repr(C)]\n" -"#[derive(AsBytes, Debug, Default)]\n" -"struct VirtioBlockRequest {\n" -" request_type: RequestType,\n" -" reserved: u32,\n" -" sector: u64,\n" -"}\n" -"\n" -"fn main() {\n" -" let request = VirtioBlockRequest {\n" -" request_type: RequestType::Flush,\n" -" sector: 42,\n" -" ..Default::default()\n" -" };\n" -"\n" -" assert_eq!(\n" -" request.as_bytes(),\n" -" &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0]\n" -" );\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/useful-crates/zerocopy.md:40 msgid "" "This is not suitable for MMIO (as it doesn't use volatile reads and writes), " @@ -14826,25 +13734,6 @@ msgid "" "space for PCI BARs:" msgstr "" -#: src/bare-metal/useful-crates/buddy_system_allocator.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"use buddy_system_allocator::FrameAllocator;\n" -"use core::alloc::Layout;\n" -"\n" -"fn main() {\n" -" let mut allocator = FrameAllocator::<32>::new();\n" -" allocator.add_frame(0x200_0000, 0x400_0000);\n" -"\n" -" let layout = Layout::from_size_align(0x100, 0x100).unwrap();\n" -" let bar = allocator\n" -" .alloc_aligned(layout)\n" -" .expect(\"Failed to allocate 0x100 byte MMIO region\");\n" -" println!(\"Allocated 0x100 byte MMIO region at {:#x}\", bar);\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/useful-crates/buddy_system_allocator.md:26 msgid "PCI BARs always have alignment equal to their size." msgstr "" @@ -14869,22 +13758,6 @@ msgid "" "and panics if you try to use more than are allocated." msgstr "" -#: src/bare-metal/useful-crates/tinyvec.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"use tinyvec::{array_vec, ArrayVec};\n" -"\n" -"fn main() {\n" -" let mut numbers: ArrayVec<[u32; 5]> = array_vec!(42, 66);\n" -" println!(\"{numbers:?}\");\n" -" numbers.push(7);\n" -" println!(\"{numbers:?}\");\n" -" numbers.remove(1);\n" -" println!(\"{numbers:?}\");\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/useful-crates/tinyvec.md:23 msgid "" "`tinyvec` requires that the element type implement `Default` for " @@ -14913,21 +13786,6 @@ msgid "" "equivalents of many of these primitives." msgstr "" -#: src/bare-metal/useful-crates/spin.md:9 -msgid "" -"```rust,editable,compile_fail\n" -"use spin::mutex::SpinMutex;\n" -"\n" -"static counter: SpinMutex = SpinMutex::new(0);\n" -"\n" -"fn main() {\n" -" println!(\"count: {}\", counter.lock());\n" -" *counter.lock() += 2;\n" -" println!(\"count: {}\", counter.lock());\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/useful-crates/spin.md:23 msgid "Be careful to avoid deadlock if you take locks in interrupt handlers." msgstr "" @@ -14958,48 +13816,6 @@ msgid "" "to convert the ELF to a raw binary ready to be run." msgstr "" -#: src/bare-metal/android.md:7 -msgid "" -"```soong\n" -"rust_ffi_static {\n" -" name: \"libvmbase_example\",\n" -" defaults: [\"vmbase_ffi_defaults\"],\n" -" crate_name: \"vmbase_example\",\n" -" srcs: [\"src/main.rs\"],\n" -" rustlibs: [\n" -" \"libvmbase\",\n" -" ],\n" -"}\n" -"\n" -"cc_binary {\n" -" name: \"vmbase_example\",\n" -" defaults: [\"vmbase_elf_defaults\"],\n" -" srcs: [\n" -" \"idmap.S\",\n" -" ],\n" -" static_libs: [\n" -" \"libvmbase_example\",\n" -" ],\n" -" linker_scripts: [\n" -" \"image.ld\",\n" -" \":vmbase_sections\",\n" -" ],\n" -"}\n" -"\n" -"raw_binary {\n" -" name: \"vmbase_example_bin\",\n" -" stem: \"vmbase_example.bin\",\n" -" src: \":vmbase_example\",\n" -" enabled: false,\n" -" target: {\n" -" android_arm64: {\n" -" enabled: true,\n" -" },\n" -" },\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/android/vmbase.md:3 msgid "" "For VMs running under crosvm on aarch64, the [vmbase](https://android." @@ -15008,22 +13824,6 @@ msgid "" "build rules, along with an entry point, UART console logging and more." msgstr "" -#: src/bare-metal/android/vmbase.md:6 -msgid "" -"```rust,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"use vmbase::{main, println};\n" -"\n" -"main!(main);\n" -"\n" -"pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {\n" -" println!(\"Hello world\");\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/android/vmbase.md:21 msgid "" "The `main!` macro marks your main function, to be called from the `vmbase` " @@ -15148,7 +13948,7 @@ msgstr "" #: src/exercises/bare-metal/rtc.md:75 msgid "" -"`src/exceptions.rs` (you should only need to change this for the 3rd part of " +"_src/exceptions.rs_ (you should only need to change this for the 3rd part of " "the exercise):" msgstr "" @@ -15227,7 +14027,7 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:149 -msgid "`src/logger.rs` (you shouldn't need to change this):" +msgid "_src/logger.rs_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/rtc.md:153 @@ -15292,7 +14092,7 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:210 -msgid "`src/pl011.rs` (you shouldn't need to change this):" +msgid "_src/pl011.rs_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/rtc.md:214 @@ -15474,32 +14274,8 @@ msgid "" "```" msgstr "" -#: src/exercises/bare-metal/rtc.md:389 -msgid "" -"```toml\n" -"[workspace]\n" -"\n" -"[package]\n" -"name = \"rtc\"\n" -"version = \"0.1.0\"\n" -"edition = \"2021\"\n" -"publish = false\n" -"\n" -"[dependencies]\n" -"arm-gic = \"0.1.0\"\n" -"bitflags = \"2.0.0\"\n" -"chrono = { version = \"0.4.24\", default-features = false }\n" -"log = \"0.4.17\"\n" -"smccc = \"0.1.1\"\n" -"spin = \"0.9.8\"\n" -"\n" -"[build-dependencies]\n" -"cc = \"1.0.73\"\n" -"```" -msgstr "" - #: src/exercises/bare-metal/rtc.md:410 -msgid "`build.rs` (you shouldn't need to change this):" +msgid "_build.rs_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/rtc.md:414 @@ -15538,7 +14314,7 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:446 -msgid "`entry.S` (you shouldn't need to change this):" +msgid "_entry.S_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/rtc.md:450 @@ -15704,7 +14480,7 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:595 -msgid "`exceptions.S` (you shouldn't need to change this):" +msgid "_exceptions.S_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/rtc.md:599 @@ -15902,7 +14678,7 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:780 -msgid "`idmap.S` (you shouldn't need to change this):" +msgid "_idmap.S_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/rtc.md:784 @@ -15955,7 +14731,7 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:829 -msgid "`image.ld` (you shouldn't need to change this):" +msgid "_image.ld_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/rtc.md:833 @@ -16070,7 +14846,7 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:940 -msgid "`Makefile` (you shouldn't need to change this):" +msgid "_Makefile_ (you shouldn't need to change this):" msgstr "" #: src/exercises/bare-metal/rtc.md:944 @@ -16118,15 +14894,6 @@ msgid "" "```" msgstr "" -#: src/exercises/bare-metal/rtc.md:989 -msgid "" -"```toml\n" -"[build]\n" -"target = \"aarch64-unknown-none\"\n" -"rustflags = [\"-C\", \"link-arg=-Timage.ld\"]\n" -"```" -msgstr "" - #: src/exercises/bare-metal/rtc.md:995 msgid "Run the code in QEMU with `make qemu`." msgstr "" @@ -16276,7 +15043,6 @@ msgstr "" msgid "" "```rust,editable\n" "use std::sync::mpsc;\n" -"use std::thread;\n" "\n" "fn main() {\n" " let (tx, rx) = mpsc::channel();\n" @@ -16294,14 +15060,14 @@ msgid "" "```" msgstr "" -#: src/concurrency/channels.md:27 +#: src/concurrency/channels.md:26 msgid "" "`mpsc` stands for Multi-Producer, Single-Consumer. `Sender` and `SyncSender` " "implement `Clone` (so you can make multiple producers) but `Receiver` does " "not." msgstr "" -#: src/concurrency/channels.md:29 +#: src/concurrency/channels.md:28 msgid "" "`send()` and `recv()` return `Result`. If they return `Err`, it means the " "counterpart `Sender` or `Receiver` is dropped and the channel is closed." @@ -16395,7 +15161,7 @@ msgstr "" #: src/concurrency/send-sync.md:3 msgid "" -"How does Rust know to forbid shared access across thread? The answer is in " +"How does Rust know to forbid shared access across threads? The answer is in " "two traits:" msgstr "" @@ -16561,8 +15327,8 @@ msgstr "" #: src/concurrency/send-sync/examples.md:31 msgid "" -"`MutexGuard`: Uses OS level primitives which must be deallocated on the " -"thread which created them." +"`MutexGuard`: Uses OS level primitives which must be deallocated on " +"the thread which created them." msgstr "" #: src/concurrency/send-sync/examples.md:34 @@ -16646,7 +15412,7 @@ msgstr "" #: src/concurrency/shared_state/arc.md:31 msgid "" "`Arc` implements `Clone` whether or not `T` does. It implements `Send` " -"and `Sync` iff `T` implements them both." +"and `Sync` if and only if `T` implements them both." msgstr "" #: src/concurrency/shared_state/arc.md:33 @@ -16893,7 +15659,7 @@ msgid "" "}\n" "\n" "static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" +" &[\"Socrates\", \"Hypatia\", \"Plato\", \"Aristotle\", \"Pythagoras\"];\n" "\n" "fn main() {\n" " // Create forks\n" @@ -16935,15 +15701,6 @@ msgid "" "reqwest/). Create a new Cargo project and `reqwest` it as a dependency with:" msgstr "" -#: src/exercises/concurrency/link-checker.md:11 -msgid "" -"```shell\n" -"cargo new link-checker\n" -"cd link-checker\n" -"cargo add --features blocking,rustls-tls reqwest\n" -"```" -msgstr "" - #: src/exercises/concurrency/link-checker.md:17 msgid "" "If `cargo add` fails with `error: no such subcommand`, then please edit the " @@ -16956,26 +15713,12 @@ msgid "" "rs/scraper/) for that:" msgstr "" -#: src/exercises/concurrency/link-checker.md:22 -msgid "" -"```shell\n" -"cargo add scraper\n" -"```" -msgstr "" - #: src/exercises/concurrency/link-checker.md:26 msgid "" "Finally, we'll need some way of handling errors. We use [`thiserror`]" "(https://docs.rs/thiserror/) for that:" msgstr "" -#: src/exercises/concurrency/link-checker.md:29 -msgid "" -"```shell\n" -"cargo add thiserror\n" -"```" -msgstr "" - #: src/exercises/concurrency/link-checker.md:33 msgid "" "The `cargo add` calls will update the `Cargo.toml` file to look like this:" @@ -17081,13 +15824,6 @@ msgstr "" msgid "Run the code in `src/main.rs` with" msgstr "" -#: src/exercises/concurrency/link-checker.md:122 -msgid "" -"```shell\n" -"cargo run\n" -"```" -msgstr "" - #: src/exercises/concurrency/link-checker.md:128 msgid "" "Use threads to check the links in parallel: send the URLs to be checked to a " @@ -17229,25 +15965,6 @@ msgid "" "doc.rust-lang.org/std/task/enum.Poll.html)." msgstr "" -#: src/async/futures.md:8 -msgid "" -"```rust\n" -"use std::pin::Pin;\n" -"use std::task::Context;\n" -"\n" -"pub trait Future {\n" -" type Output;\n" -" fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll;\n" -"}\n" -"\n" -"pub enum Poll {\n" -" Ready(T),\n" -" Pending,\n" -"}\n" -"```" -msgstr "" - #: src/async/futures.md:23 msgid "" "An async function returns an `impl Future`. It's also possible (but " @@ -17468,21 +16185,28 @@ msgstr "" #: src/async/tasks.md:54 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/async/tasks.md:56 +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/async/tasks.md:57 +#: src/async/tasks.md:59 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`. " msgstr "" -#: src/async/tasks.md:61 +#: src/async/tasks.md:63 msgid "" "Refactor the async block into a function, and improve the error handling " -"using `?`." +"using `?`. " msgstr "" #: src/async/channels.md:3 @@ -17699,7 +16423,7 @@ 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 seconds." +"that take 500ms." msgstr "" #: src/async/control-flow/select.md:67 @@ -17924,19 +16648,6 @@ msgid "" "Instead, add a `timeout_fut` containing that future outside of the `loop`:" msgstr "" -#: src/async/pitfalls/pin.md:79 -msgid "" -"```rust,compile_fail\n" -"let mut timeout_fut = sleep(Duration::from_millis(100));\n" -"loop {\n" -" select! {\n" -" ..,\n" -" _ = timeout_fut => { println!(..); },\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/async/pitfalls/pin.md:88 msgid "" "This still doesn't work. Follow the compiler errors, adding `&mut` to the " @@ -17944,19 +16655,6 @@ msgid "" "pin`:" msgstr "" -#: src/async/pitfalls/pin.md:92 -msgid "" -"```rust,compile_fail\n" -"let mut timeout_fut = Box::pin(sleep(Duration::from_millis(100)));\n" -"loop {\n" -" select! {\n" -" ..,\n" -" _ = &mut timeout_fut => { println!(..); },\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/async/pitfalls/pin.md:102 msgid "" "This compiles, but once the timeout expires it is `Poll::Ready` on every " @@ -18158,7 +16856,7 @@ msgstr "" #: src/async/pitfalls/cancellation.md:82 msgid "" -"`LinesReader` can be made cancellation-safe by makeing `buf` part of the " +"`LinesReader` can be made cancellation-safe by making `buf` part of the " "struct:" msgstr "" @@ -18275,7 +16973,7 @@ msgid "" "}\n" "\n" "static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" +" &[\"Socrates\", \"Hypatia\", \"Plato\", \"Aristotle\", \"Pythagoras\"];\n" "\n" "#[tokio::main]\n" "async fn main() {\n" @@ -18333,7 +17031,7 @@ msgstr "" 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/0.3.2/tokio_websockets/) for the " +"(https://docs.rs/tokio-websockets/0.4.0/tokio_websockets/) for the " "communication between the client and the server." msgstr "" @@ -18342,7 +17040,7 @@ msgid "Create a new Cargo project and add the following dependencies:" msgstr "" #: src/exercises/concurrency/chat-app.md:15 -msgid "`Cargo.toml`:" +msgid "_Cargo.toml_:" msgstr "" #: src/exercises/concurrency/chat-app.md:19 @@ -18354,10 +17052,11 @@ msgid "" "edition = \"2021\"\n" "\n" "[dependencies]\n" -"futures-util = \"0.3.28\"\n" +"futures-util = { version = \"0.3.28\", features = [\"sink\"] }\n" "http = \"0.2.9\"\n" "tokio = { version = \"1.28.1\", features = [\"full\"] }\n" -"tokio-websockets = \"0.3.2\"\n" +"tokio-websockets = { version = \"0.4.0\", features = [\"client\", " +"\"fastrand\", \"server\", \"sha1_smol\"] }\n" "```" msgstr "" @@ -18368,15 +17067,15 @@ msgstr "" #: src/exercises/concurrency/chat-app.md:33 msgid "" "You are going to need the following functions from `tokio` and " -"[`tokio_websockets`](https://docs.rs/tokio-websockets/0.3.2/" +"[`tokio_websockets`](https://docs.rs/tokio-websockets/0.4.0/" "tokio_websockets/). Spend a few minutes to familiarize yourself with the " "API. " msgstr "" #: src/exercises/concurrency/chat-app.md:37 msgid "" -"[WebsocketStream::next()](https://docs.rs/tokio-websockets/0.3.2/" -"tokio_websockets/proto/struct.WebsocketStream.html#method.next): for " +"[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 "" @@ -18423,14 +17122,15 @@ msgid "" msgstr "" #: src/exercises/concurrency/chat-app.md:59 -#: src/exercises/concurrency/solutions-afternoon.md:123 -msgid "`src/bin/server.rs`:" +#: src/exercises/concurrency/solutions-afternoon.md:99 +msgid "_src/bin/server.rs_:" msgstr "" #: src/exercises/concurrency/chat-app.md:63 msgid "" "```rust,compile_fail\n" "use futures_util::sink::SinkExt;\n" +"use futures_util::stream::StreamExt;\n" "use std::error::Error;\n" "use std::net::SocketAddr;\n" "use tokio::net::{TcpListener, TcpStream};\n" @@ -18469,14 +17169,15 @@ msgid "" "```" msgstr "" -#: src/exercises/concurrency/chat-app.md:102 -#: src/exercises/concurrency/solutions-afternoon.md:208 -msgid "`src/bin/client.rs`:" +#: src/exercises/concurrency/chat-app.md:103 +#: src/exercises/concurrency/solutions-afternoon.md:166 +msgid "_src/bin/client.rs_:" msgstr "" -#: src/exercises/concurrency/chat-app.md:106 +#: src/exercises/concurrency/chat-app.md:107 msgid "" "```rust,compile_fail\n" +"use futures_util::stream::StreamExt;\n" "use futures_util::SinkExt;\n" "use http::Uri;\n" "use tokio::io::{AsyncBufReadExt, BufReader};\n" @@ -18484,10 +17185,10 @@ msgid "" "\n" "#[tokio::main]\n" "async fn main() -> Result<(), tokio_websockets::Error> {\n" -" let mut ws_stream = ClientBuilder::from_uri(Uri::" -"from_static(\"ws://127.0.0.1:2000\"))\n" -" .connect()\n" -" .await?;\n" +" let (mut ws_stream, _) =\n" +" ClientBuilder::from_uri(Uri::from_static(\"ws://127.0.0.1:2000\"))\n" +" .connect()\n" +" .await?;\n" "\n" " let stdin = tokio::io::stdin();\n" " let mut stdin = BufReader::new(stdin).lines();\n" @@ -18499,48 +17200,34 @@ msgid "" "```" msgstr "" -#: src/exercises/concurrency/chat-app.md:127 +#: src/exercises/concurrency/chat-app.md:130 msgid "Running the binaries" msgstr "" -#: src/exercises/concurrency/chat-app.md:128 +#: src/exercises/concurrency/chat-app.md:131 msgid "Run the server with:" msgstr "" -#: src/exercises/concurrency/chat-app.md:130 -msgid "" -"```shell\n" -"cargo run --bin server\n" -"```" -msgstr "" - -#: src/exercises/concurrency/chat-app.md:134 +#: src/exercises/concurrency/chat-app.md:137 msgid "and the client with:" msgstr "" -#: src/exercises/concurrency/chat-app.md:136 -msgid "" -"```shell\n" -"cargo run --bin client\n" -"```" -msgstr "" - -#: src/exercises/concurrency/chat-app.md:142 +#: src/exercises/concurrency/chat-app.md:145 msgid "Implement the `handle_connection` function in `src/bin/server.rs`." msgstr "" -#: src/exercises/concurrency/chat-app.md:143 +#: src/exercises/concurrency/chat-app.md:146 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/exercises/concurrency/chat-app.md:146 +#: src/exercises/concurrency/chat-app.md:149 msgid "Complete the main function in `src/bin/client.rs`." msgstr "" -#: src/exercises/concurrency/chat-app.md:147 +#: src/exercises/concurrency/chat-app.md:150 msgid "" "Hint: As before, use `tokio::select!` in a continuous loop for concurrently " "performing two tasks: (1) reading user messages from standard input and " @@ -18548,7 +17235,7 @@ msgid "" "displaying them for the user." msgstr "" -#: src/exercises/concurrency/chat-app.md:151 +#: src/exercises/concurrency/chat-app.md:154 msgid "" "Optional: Once you are done, change the code to broadcast messages to all " "clients, but the sender of the message." @@ -18568,6 +17255,322 @@ msgid "" "comprehensive-rust/discussions). We would love to hear from you." msgstr "" +#: src/glossary.md:3 +msgid "" +"The following is a glossary which aims to give a short definition of many " +"Rust terms. For translations, this also serves to connect the term back to " +"the English original." +msgstr "" + +#: src/glossary.md:30 +msgid "" +"allocate: \n" +"Dynamic memory allocation on [the heap](memory-management/stack-vs-heap.md)." +msgstr "" + +#: src/glossary.md:32 +msgid "argument:" +msgstr "" + +#: src/glossary.md:33 +msgid "" +"Bare-metal Rust: \n" +"Low-level Rust development, often deployed to a system without an operating " +"system. See [Bare-metal Rust](bare-metal.md)." +msgstr "" + +#: src/glossary.md:36 +msgid "" +"block: \n" +"See [Blocks](control-flow/blocks.md) and _scope_." +msgstr "" + +#: src/glossary.md:38 +msgid "" +"borrow: \n" +"See [Borrowing](ownership/borrowing.md)." +msgstr "" + +#: src/glossary.md:40 +msgid "" +"borrow checker: \n" +"The part of the Rust compiler which checks that all borrows are valid." +msgstr "" + +#: src/glossary.md:42 +msgid "" +"brace: \n" +"`{` and `}`. Also called _curly brace_, they delimit _blocks_." +msgstr "" + +#: src/glossary.md:44 +msgid "build:" +msgstr "" + +#: src/glossary.md:45 +msgid "call:" +msgstr "" + +#: src/glossary.md:46 +msgid "" +"channel: \n" +"Used to safely pass messages [between threads](concurrency/channels.md)." +msgstr "" + +#: src/glossary.md:48 +msgid "" +"Comprehensive Rust 🦀: \n" +"The courses here are jointly called Comprehensive Rust 🦀." +msgstr "" + +#: src/glossary.md:50 +#, fuzzy +msgid "concurrency:" +msgstr "همزمانی" + +#: src/glossary.md:51 +msgid "" +"Concurrency in Rust: \n" +"See [Concurrency in Rust](concurrency.md)." +msgstr "" + +#: src/glossary.md:53 +msgid "constant:" +msgstr "" + +#: src/glossary.md:54 +#, fuzzy +msgid "control flow:" +msgstr "کنترل جریان" + +#: src/glossary.md:55 +msgid "crash:" +msgstr "" + +#: src/glossary.md:56 +#, fuzzy +msgid "enumeration:" +msgstr "پیاده سازی" + +#: src/glossary.md:57 +msgid "error:" +msgstr "" + +#: src/glossary.md:58 +#, fuzzy +msgid "error handling:" +msgstr "مدیریت خطا (Error Handling)" + +#: src/glossary.md:59 +#, fuzzy +msgid "exercise:" +msgstr "تمرین‌ها" + +#: src/glossary.md:60 +#, fuzzy +msgid "function:" +msgstr "توابع" + +#: src/glossary.md:61 +#, fuzzy +msgid "garbage collector:" +msgstr "Garbage Collection" + +#: src/glossary.md:62 +#, fuzzy +msgid "generics:" +msgstr "Generics" + +#: src/glossary.md:63 +msgid "immutable:" +msgstr "" + +#: src/glossary.md:64 +#, fuzzy +msgid "integration test:" +msgstr "Integration Tests" + +#: src/glossary.md:65 +msgid "keyword:" +msgstr "" + +#: src/glossary.md:66 +#, fuzzy +msgid "library:" +msgstr "کتابخانه" + +#: src/glossary.md:67 +msgid "macro:" +msgstr "" + +#: src/glossary.md:68 +#, fuzzy +msgid "main function:" +msgstr "فراخوانی متدهای ناامن" + +#: src/glossary.md:69 +msgid "match:" +msgstr "" + +#: src/glossary.md:70 +msgid "memory leak:" +msgstr "" + +#: src/glossary.md:71 +#, fuzzy +msgid "method:" +msgstr "متدها" + +#: src/glossary.md:72 +#, fuzzy +msgid "module:" +msgstr "ماژول‌ها" + +#: src/glossary.md:73 +msgid "move:" +msgstr "" + +#: src/glossary.md:74 +msgid "mutable:" +msgstr "" + +#: src/glossary.md:75 +#, fuzzy +msgid "ownership:" +msgstr "مالکیت" + +#: src/glossary.md:76 +#, fuzzy +msgid "panic:" +msgstr "Panics" + +#: src/glossary.md:77 +msgid "parameter:" +msgstr "" + +#: src/glossary.md:78 +msgid "pattern:" +msgstr "" + +#: src/glossary.md:79 +msgid "payload:" +msgstr "" + +#: src/glossary.md:80 +msgid "program:" +msgstr "" + +#: src/glossary.md:81 +msgid "programming language:" +msgstr "" + +#: src/glossary.md:82 +#, fuzzy +msgid "receiver:" +msgstr "درایور" + +#: src/glossary.md:83 +msgid "reference counting:" +msgstr "" + +#: src/glossary.md:84 +msgid "return:" +msgstr "" + +#: src/glossary.md:85 +#, fuzzy +msgid "Rust:" +msgstr "Rustdoc" + +#: src/glossary.md:86 +msgid "" +"Rust Fundamentals: \n" +"Days 1 to 3 of this course." +msgstr "" + +#: src/glossary.md:88 +msgid "" +"Rust in Android: \n" +"See [Rust in Android](android.md)." +msgstr "" + +#: src/glossary.md:90 +msgid "safe:" +msgstr "" + +#: src/glossary.md:91 +msgid "scope:" +msgstr "" + +#: src/glossary.md:92 +#, fuzzy +msgid "standard library:" +msgstr "کتابخانه‌های استاندارد" + +#: src/glossary.md:93 +msgid "static:" +msgstr "" + +#: src/glossary.md:94 +#, fuzzy +msgid "string:" +msgstr "String" + +#: src/glossary.md:95 +#, fuzzy +msgid "struct:" +msgstr "ساختارها" + +#: src/glossary.md:96 +msgid "test:" +msgstr "" + +#: src/glossary.md:97 +#, fuzzy +msgid "thread:" +msgstr "تردها" + +#: src/glossary.md:98 +msgid "thread safety:" +msgstr "" + +#: src/glossary.md:99 +#, fuzzy +msgid "trait:" +msgstr "صفت‌ها" + +#: src/glossary.md:100 +msgid "type:" +msgstr "" + +#: src/glossary.md:101 +#, fuzzy +msgid "type inference:" +msgstr "Type Inference" + +#: src/glossary.md:102 +msgid "undefined behavior:" +msgstr "" + +#: src/glossary.md:103 +#, fuzzy +msgid "union:" +msgstr "Unions" + +#: src/glossary.md:104 +#, fuzzy +msgid "unit test:" +msgstr "تست‌های واحد (Unit Tests)" + +#: src/glossary.md:105 +msgid "unsafe:" +msgstr "" + +#: src/glossary.md:106 +#, fuzzy +msgid "variable:\\" +msgstr "متغیرها" + #: src/other-resources.md:1 msgid "Other Rust Resources" msgstr "" @@ -18750,6 +17753,15 @@ msgid "" "directory for details, including the license terms." msgstr "" +#: src/credits.md:34 +msgid "" +"The [Why Rust? - An Example in C](why-rust/an-example-in-c.md) section has " +"been taken from the presentation slides of [Colin Finck's Master Thesis]" +"(https://colinfinck.de/Master_Thesis_Colin_Finck.pdf). It has been " +"relicensed under the terms of the Apache 2.0 license for this course by the " +"author." +msgstr "" + #: src/exercises/solutions.md:3 msgid "You will find solutions to the exercises on the following pages." msgstr "" @@ -18761,13 +17773,6 @@ msgid "" "different or better solution than what is presented here." msgstr "" -#: src/exercises/solutions.md:10 -msgid "" -"**Note:** Please ignore the `// ANCHOR: label` and `// ANCHOR_END: label` " -"comments you see in the solutions. They are there to make it possible to re-" -"use parts of the solutions as the exercises." -msgstr "" - #: src/exercises/day-1/solutions-morning.md:1 msgid "Day 1 Morning Exercises" msgstr "" @@ -18779,23 +17784,7 @@ msgstr "" #: src/exercises/day-1/solutions-morning.md:7 msgid "" "```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: transpose\n" "fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" -" // ANCHOR_END: transpose\n" " let mut result = [[0; 3]; 3];\n" " for i in 0..3 {\n" " for j in 0..3 {\n" @@ -18805,15 +17794,12 @@ msgid "" " return result;\n" "}\n" "\n" -"// ANCHOR: pretty_print\n" "fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" -" // ANCHOR_END: pretty_print\n" " for row in matrix {\n" " println!(\"{row:?}\");\n" " }\n" "}\n" "\n" -"// ANCHOR: tests\n" "#[test]\n" "fn test_transpose() {\n" " let matrix = [\n" @@ -18831,9 +17817,7 @@ msgid "" " ]\n" " );\n" "}\n" -"// ANCHOR_END: tests\n" "\n" -"// ANCHOR: main\n" "fn main() {\n" " let matrix = [\n" " [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" @@ -18851,11 +17835,11 @@ msgid "" "```" msgstr "" -#: src/exercises/day-1/solutions-morning.md:78 +#: src/exercises/day-1/solutions-morning.md:57 msgid "Bonus question" msgstr "" -#: src/exercises/day-1/solutions-morning.md:80 +#: src/exercises/day-1/solutions-morning.md:59 msgid "" "It requires more advanced concepts. It might seem that we could use a slice-" "of-slices (`&[&[i32]]`) as the input type to transpose and thus make our " @@ -18863,21 +17847,21 @@ msgid "" "return type cannot be `&[&[i32]]` since it needs to own the data you return." msgstr "" -#: src/exercises/day-1/solutions-morning.md:82 +#: src/exercises/day-1/solutions-morning.md:61 msgid "" "You can attempt to use something like `Vec>`, but this doesn't work " "out-of-the-box either: it's hard to convert from `Vec>` to " "`&[&[i32]]` so now you cannot easily use `pretty_print` either." msgstr "" -#: src/exercises/day-1/solutions-morning.md:84 +#: src/exercises/day-1/solutions-morning.md:63 msgid "" "Once we get to traits and generics, we'll be able to use the [`std::convert::" "AsRef`](https://doc.rust-lang.org/std/convert/trait.AsRef.html) trait to " "abstract over anything that can be referenced as a slice." msgstr "" -#: src/exercises/day-1/solutions-morning.md:86 +#: src/exercises/day-1/solutions-morning.md:65 msgid "" "```rust\n" "use std::convert::AsRef;\n" @@ -18907,7 +17891,7 @@ msgid "" "```" msgstr "" -#: src/exercises/day-1/solutions-morning.md:113 +#: src/exercises/day-1/solutions-morning.md:92 msgid "" "In addition, the type itself would not enforce that the child slices are of " "the same length, so such variable could contain an invalid matrix." @@ -18917,32 +17901,243 @@ msgstr "" msgid "Day 1 Afternoon Exercises" msgstr "" -#: src/exercises/day-1/solutions-afternoon.md:3 -msgid "Designing a Library" -msgstr "" - #: src/exercises/day-1/solutions-afternoon.md:5 -msgid "([back to exercise](book-library.md))" +msgid "([back to exercise](luhn.md))" msgstr "" #: src/exercises/day-1/solutions-afternoon.md:7 msgid "" "```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" let mut sum = 0;\n" +" let mut double = false;\n" +" let mut digit_seen = 0;\n" "\n" -"// ANCHOR: setup\n" +" for c in cc_number.chars().filter(|&f| f != ' ').rev() {\n" +" if let Some(digit) = c.to_digit(10) {\n" +" if double {\n" +" let double_digit = digit * 2;\n" +" sum += if double_digit > 9 {\n" +" double_digit - 9\n" +" } else {\n" +" double_digit\n" +" };\n" +" } else {\n" +" sum += digit;\n" +" }\n" +" double = !double;\n" +" digit_seen += 1;\n" +" } else {\n" +" return false;\n" +" }\n" +" }\n" +"\n" +" if digit_seen < 2 {\n" +" return false;\n" +" }\n" +"\n" +" sum % 10 == 0\n" +"}\n" +"\n" +"fn main() {\n" +" let cc_number = \"1234 5678 1234 5670\";\n" +" println!(\n" +" \"Is {cc_number} a valid credit card number? {}\",\n" +" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" +" );\n" +"}\n" +"\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +" assert!(!luhn(\"foo 0 0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:86 +#, fuzzy +msgid "Pattern matching" +msgstr "تطبیق الگو" + +#: src/exercises/day-1/solutions-afternoon.md:88 +msgid "" +"```rust\n" +"/// An operation to perform on two subexpressions.\n" +"#[derive(Debug)]\n" +"enum Operation {\n" +" Add,\n" +" Sub,\n" +" Mul,\n" +" Div,\n" +"}\n" +"\n" +"/// An expression, in tree form.\n" +"#[derive(Debug)]\n" +"enum Expression {\n" +" /// An operation on two subexpressions.\n" +" Op {\n" +" op: Operation,\n" +" left: Box,\n" +" right: Box,\n" +" },\n" +"\n" +" /// A literal value\n" +" Value(i64),\n" +"}\n" +"\n" +"/// The result of evaluating an expression.\n" +"#[derive(Debug, PartialEq, Eq)]\n" +"enum Res {\n" +" /// Evaluation was successful, with the given result.\n" +" Ok(i64),\n" +" /// Evaluation failed, with the given error message.\n" +" Err(String),\n" +"}\n" +"// Allow `Ok` and `Err` as shorthands for `Res::Ok` and `Res::Err`.\n" +"use Res::{Err, Ok};\n" +"\n" +"fn eval(e: Expression) -> Res {\n" +" match e {\n" +" Expression::Op { op, left, right } => {\n" +" let left = match eval(*left) {\n" +" Ok(v) => v,\n" +" Err(msg) => return Err(msg),\n" +" };\n" +" let right = match eval(*right) {\n" +" Ok(v) => v,\n" +" Err(msg) => return Err(msg),\n" +" };\n" +" Ok(match op {\n" +" Operation::Add => left + right,\n" +" Operation::Sub => left - right,\n" +" Operation::Mul => left * right,\n" +" Operation::Div => {\n" +" if right == 0 {\n" +" return Err(String::from(\"division by zero\"));\n" +" } else {\n" +" left / right\n" +" }\n" +" }\n" +" })\n" +" }\n" +" Expression::Value(v) => Ok(v),\n" +" }\n" +"}\n" +"\n" +"#[test]\n" +"fn test_value() {\n" +" assert_eq!(eval(Expression::Value(19)), Ok(19));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_sum() {\n" +" assert_eq!(\n" +" eval(Expression::Op {\n" +" op: Operation::Add,\n" +" left: Box::new(Expression::Value(10)),\n" +" right: Box::new(Expression::Value(20)),\n" +" }),\n" +" Ok(30)\n" +" );\n" +"}\n" +"\n" +"#[test]\n" +"fn test_recursion() {\n" +" let term1 = Expression::Op {\n" +" op: Operation::Mul,\n" +" left: Box::new(Expression::Value(10)),\n" +" right: Box::new(Expression::Value(9)),\n" +" };\n" +" let term2 = Expression::Op {\n" +" op: Operation::Mul,\n" +" left: Box::new(Expression::Op {\n" +" op: Operation::Sub,\n" +" left: Box::new(Expression::Value(3)),\n" +" right: Box::new(Expression::Value(4)),\n" +" }),\n" +" right: Box::new(Expression::Value(5)),\n" +" };\n" +" assert_eq!(\n" +" eval(Expression::Op {\n" +" op: Operation::Add,\n" +" left: Box::new(term1),\n" +" right: Box::new(term2),\n" +" }),\n" +" Ok(85)\n" +" );\n" +"}\n" +"\n" +"#[test]\n" +"fn test_error() {\n" +" assert_eq!(\n" +" eval(Expression::Op {\n" +" op: Operation::Div,\n" +" left: Box::new(Expression::Value(99)),\n" +" right: Box::new(Expression::Value(0)),\n" +" }),\n" +" Err(String::from(\"division by zero\"))\n" +" );\n" +"}\n" +"fn main() {\n" +" let expr = Expression::Op {\n" +" op: Operation::Sub,\n" +" left: Box::new(Expression::Value(20)),\n" +" right: Box::new(Expression::Value(10)),\n" +" };\n" +" println!(\"expr: {:?}\", expr);\n" +" println!(\"result: {:?}\", eval(expr));\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:1 +msgid "Day 2 Morning Exercises" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:3 +msgid "Designing a Library" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:5 +msgid "([back to exercise](book-library.md))" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:7 +msgid "" +"```rust\n" "struct Library {\n" " books: Vec,\n" "}\n" @@ -18962,65 +18157,37 @@ msgid "" " }\n" "}\n" "\n" -"// Implement the methods below. Update the `self` parameter to\n" -"// indicate the method's required level of ownership over the object:\n" +"// Implement the methods below. Notice how the `self` parameter\n" +"// changes type to indicate the method's required level of ownership\n" +"// over the object:\n" "//\n" "// - `&self` for shared read-only access,\n" "// - `&mut self` for unique and mutable access,\n" "// - `self` for unique access by value.\n" "impl Library {\n" -" // ANCHOR_END: setup\n" "\n" -" // ANCHOR: Library_new\n" " fn new() -> Library {\n" -" // ANCHOR_END: Library_new\n" " Library { books: Vec::new() }\n" " }\n" "\n" -" // ANCHOR: Library_len\n" -" //fn len(self) -> usize {\n" -" // todo!(\"Return the length of `self.books`\")\n" -" //}\n" -" // ANCHOR_END: Library_len\n" " fn len(&self) -> usize {\n" " self.books.len()\n" " }\n" "\n" -" // ANCHOR: Library_is_empty\n" -" //fn is_empty(self) -> bool {\n" -" // todo!(\"Return `true` if `self.books` is empty\")\n" -" //}\n" -" // ANCHOR_END: Library_is_empty\n" " fn is_empty(&self) -> bool {\n" " self.books.is_empty()\n" " }\n" "\n" -" // ANCHOR: Library_add_book\n" -" //fn add_book(self, book: Book) {\n" -" // todo!(\"Add a new book to `self.books`\")\n" -" //}\n" -" // ANCHOR_END: Library_add_book\n" " fn add_book(&mut self, book: Book) {\n" " self.books.push(book)\n" " }\n" "\n" -" // ANCHOR: Library_print_books\n" -" //fn print_books(self) {\n" -" // todo!(\"Iterate over `self.books` and each book's title and " -"year\")\n" -" //}\n" -" // ANCHOR_END: Library_print_books\n" " fn print_books(&self) {\n" " for book in &self.books {\n" " println!(\"{}, published in {}\", book.title, book.year);\n" " }\n" " }\n" "\n" -" // ANCHOR: Library_oldest_book\n" -" //fn oldest_book(self) -> Option<&Book> {\n" -" // todo!(\"Return a reference to the oldest book (if any)\")\n" -" //}\n" -" // ANCHOR_END: Library_oldest_book\n" " fn oldest_book(&self) -> Option<&Book> {\n" " // Using a closure and a built-in method:\n" " // self.books.iter().min_by_key(|book| book.year)\n" @@ -19037,36 +18204,33 @@ msgid "" " }\n" "}\n" "\n" -"// ANCHOR: main\n" -"// This shows the desired behavior. Uncomment the code below and\n" -"// implement the missing methods. You will need to update the\n" -"// method signatures, including the \"self\" parameter! You may\n" -"// also need to update the variable bindings within main.\n" "fn main() {\n" -" let library = Library::new();\n" +" let mut library = Library::new();\n" "\n" -" //println!(\"The library is empty: library.is_empty() -> {}\", library." -"is_empty());\n" -" //\n" -" //library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " +" println!(\n" +" \"The library is empty: library.is_empty() -> {}\",\n" +" library.is_empty()\n" +" );\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " "1865));\n" -" //\n" -" //println!(\"The library is no longer empty: library.is_empty() -> {}\", " -"library.is_empty());\n" -" //\n" -" //\n" -" //library.print_books();\n" -" //\n" -" //match library.oldest_book() {\n" -" // Some(book) => println!(\"The oldest book is {}\", book.title),\n" -" // None => println!(\"The library is empty!\"),\n" -" //}\n" -" //\n" -" //println!(\"The library has {} books\", library.len());\n" -" //library.print_books();\n" +"\n" +" println!(\n" +" \"The library is no longer empty: library.is_empty() -> {}\",\n" +" library.is_empty()\n" +" );\n" +"\n" +" library.print_books();\n" +"\n" +" match library.oldest_book() {\n" +" Some(book) => println!(\"The oldest book is {}\", book.title),\n" +" None => println!(\"The library is empty!\"),\n" +" }\n" +"\n" +" println!(\"The library has {} books\", library.len());\n" +" library.print_books();\n" "}\n" -"// ANCHOR_END: main\n" "\n" "#[test]\n" "fn test_library_len() {\n" @@ -19122,42 +18286,372 @@ msgid "" "```" msgstr "" -#: src/exercises/day-2/solutions-morning.md:1 -msgid "Day 2 Morning Exercises" +#: src/exercises/day-2/solutions-morning.md:153 +msgid "([back to exercise](health-statistics.md))" msgstr "" -#: src/exercises/day-2/solutions-morning.md:5 +#: src/exercises/day-2/solutions-morning.md:155 +msgid "" +"```rust\n" +"pub struct User {\n" +" name: String,\n" +" age: u32,\n" +" height: f32,\n" +" visit_count: usize,\n" +" last_blood_pressure: Option<(u32, u32)>,\n" +"}\n" +"\n" +"pub struct Measurements {\n" +" height: f32,\n" +" blood_pressure: (u32, u32),\n" +"}\n" +"\n" +"pub struct HealthReport<'a> {\n" +" patient_name: &'a str,\n" +" visit_count: u32,\n" +" height_change: f32,\n" +" blood_pressure_change: Option<(i32, i32)>,\n" +"}\n" +"\n" +"impl User {\n" +" pub fn new(name: String, age: u32, height: f32) -> Self {\n" +" Self {\n" +" name,\n" +" age,\n" +" height,\n" +" visit_count: 0,\n" +" last_blood_pressure: None,\n" +" }\n" +" }\n" +"\n" +" pub fn name(&self) -> &str {\n" +" &self.name\n" +" }\n" +"\n" +" pub fn age(&self) -> u32 {\n" +" self.age\n" +" }\n" +"\n" +" pub fn height(&self) -> f32 {\n" +" self.height\n" +" }\n" +"\n" +" pub fn doctor_visits(&self) -> u32 {\n" +" self.visit_count as u32\n" +" }\n" +"\n" +" pub fn set_age(&mut self, new_age: u32) {\n" +" self.age = new_age\n" +" }\n" +"\n" +" pub fn set_height(&mut self, new_height: f32) {\n" +" self.height = new_height\n" +" }\n" +"\n" +" pub fn visit_doctor(&mut self, measurements: Measurements) -> " +"HealthReport {\n" +" self.visit_count += 1;\n" +" let bp = measurements.blood_pressure;\n" +" let report = HealthReport {\n" +" patient_name: &self.name,\n" +" visit_count: self.visit_count as u32,\n" +" height_change: measurements.height - self.height,\n" +" blood_pressure_change: match self.last_blood_pressure {\n" +" Some(lbp) => Some((\n" +" bp.0 as i32 - lbp.0 as i32,\n" +" bp.1 as i32 - lbp.1 as i32\n" +" )),\n" +" None => None,\n" +" }\n" +" };\n" +" self.height = measurements.height;\n" +" self.last_blood_pressure = Some(bp);\n" +" report\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_height() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.height(), 155.2);\n" +"}\n" +"\n" +"#[test]\n" +"fn test_set_age() {\n" +" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.age(), 32);\n" +" bob.set_age(33);\n" +" assert_eq!(bob.age(), 33);\n" +"}\n" +"\n" +"#[test]\n" +"fn test_visit() {\n" +" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.doctor_visits(), 0);\n" +" let report = bob.visit_doctor(Measurements {\n" +" height: 156.1,\n" +" blood_pressure: (120, 80),\n" +" });\n" +" assert_eq!(report.patient_name, \"Bob\");\n" +" assert_eq!(report.visit_count, 1);\n" +" assert_eq!(report.blood_pressure_change, None);\n" +"\n" +" let report = bob.visit_doctor(Measurements {\n" +" height: 156.1,\n" +" blood_pressure: (115, 76),\n" +" });\n" +"\n" +" assert_eq!(report.visit_count, 2);\n" +" assert_eq!(report.blood_pressure_change, Some((-5, -4)));\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:1 +msgid "Day 2 Afternoon Exercises" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:5 +msgid "([back to exercise](strings-iterators.md))" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +"\n" +" let mut request_segments = request_path.split('/');\n" +"\n" +" for prefix_segment in prefix.split('/') {\n" +" let Some(request_segment) = request_segments.next() else {\n" +" return false;\n" +" };\n" +" if request_segment != prefix_segment && prefix_segment != \"*\" {\n" +" return false;\n" +" }\n" +" }\n" +" true\n" +"\n" +" // Alternatively, Iterator::zip() lets us iterate simultaneously over " +"prefix\n" +" // and request segments. The zip() iterator is finished as soon as one " +"of\n" +" // the source iterators is finished, but we need to iterate over all " +"request\n" +" // segments. A neat trick that makes zip() work is to use map() and " +"chain()\n" +" // to produce an iterator that returns Some(str) for each pattern " +"segments,\n" +" // and then returns None indefinitely.\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/" +"abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/" +"books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/" +"publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/" +"publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:1 +msgid "Day 3 Morning Exercise" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:5 +msgid "([back to exercise](simple-gui.md))" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:7 +msgid "" +"```rust\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"\n" +" fn inner_width(&self) -> usize {\n" +" std::cmp::max(\n" +" self.title.chars().count(),\n" +" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +" )\n" +" }\n" +"}\n" +"\n" +"\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" // Add 4 paddings for borders\n" +" self.inner_width() + 4\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" let mut inner = String::new();\n" +" for widget in &self.widgets {\n" +" widget.draw_into(&mut inner);\n" +" }\n" +"\n" +" let inner_width = self.inner_width();\n" +"\n" +" // TODO: after learning about error handling, you can change\n" +" // draw_into to return Result<(), std::fmt::Error>. Then use\n" +" // the ?-operator here instead of .unwrap().\n" +" writeln!(buffer, \"+-{:- usize {\n" +" self.label.width() + 8 // add a bit of padding\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" let width = self.width();\n" +" let mut label = String::new();\n" +" self.label.draw_into(&mut label);\n" +"\n" +" writeln!(buffer, \"+{:- usize {\n" +" self.label\n" +" .lines()\n" +" .map(|line| line.chars().count())\n" +" .max()\n" +" .unwrap_or(0)\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" writeln!(buffer, \"{}\", &self.label).unwrap();\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo." +"\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\"\n" +" )));\n" +" window.draw();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:144 msgid "([back to exercise](points-polygons.md))" msgstr "" -#: src/exercises/day-2/solutions-morning.md:7 +#: src/exercises/day-3/solutions-morning.md:146 msgid "" "```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" "#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" -"// ANCHOR: Point\n" "pub struct Point {\n" -" // ANCHOR_END: Point\n" " x: i32,\n" " y: i32,\n" "}\n" "\n" -"// ANCHOR: Point-impl\n" "impl Point {\n" -" // ANCHOR_END: Point-impl\n" " pub fn new(x: i32, y: i32) -> Point {\n" " Point { x, y }\n" " }\n" @@ -19193,15 +18687,11 @@ msgid "" " }\n" "}\n" "\n" -"// ANCHOR: Polygon\n" "pub struct Polygon {\n" -" // ANCHOR_END: Polygon\n" " points: Vec,\n" "}\n" "\n" -"// ANCHOR: Polygon-impl\n" "impl Polygon {\n" -" // ANCHOR_END: Polygon-impl\n" " pub fn new() -> Polygon {\n" " Polygon { points: Vec::new() }\n" " }\n" @@ -19245,16 +18735,12 @@ msgid "" " }\n" "}\n" "\n" -"// ANCHOR: Circle\n" "pub struct Circle {\n" -" // ANCHOR_END: Circle\n" " center: Point,\n" " radius: i32,\n" "}\n" "\n" -"// ANCHOR: Circle-impl\n" "impl Circle {\n" -" // ANCHOR_END: Circle-impl\n" " pub fn new(center: Point, radius: i32) -> Circle {\n" " Circle { center, radius }\n" " }\n" @@ -19268,12 +18754,10 @@ msgid "" " }\n" "}\n" "\n" -"// ANCHOR: Shape\n" "pub enum Shape {\n" " Polygon(Polygon),\n" " Circle(Circle),\n" "}\n" -"// ANCHOR_END: Shape\n" "\n" "impl From for Shape {\n" " fn from(poly: Polygon) -> Self {\n" @@ -19296,7 +18780,6 @@ msgid "" " }\n" "}\n" "\n" -"// ANCHOR: unit-tests\n" "#[cfg(test)]\n" "mod tests {\n" " use super::*;\n" @@ -19367,387 +18850,11 @@ msgid "" " assert_eq!(perimeters, vec![15.48, 31.42]);\n" " }\n" "}\n" -"// ANCHOR_END: unit-tests\n" "\n" "fn main() {}\n" "```" msgstr "" -#: src/exercises/day-2/solutions-afternoon.md:1 -msgid "Day 2 Afternoon Exercises" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:5 -msgid "([back to exercise](luhn.md))" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:7 -msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: luhn\n" -"pub fn luhn(cc_number: &str) -> bool {\n" -" // ANCHOR_END: luhn\n" -" let mut digits_seen = 0;\n" -" let mut sum = 0;\n" -" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ')." -"enumerate() {\n" -" match ch.to_digit(10) {\n" -" Some(d) => {\n" -" sum += if i % 2 == 1 {\n" -" let dd = d * 2;\n" -" dd / 10 + dd % 10\n" -" } else {\n" -" d\n" -" };\n" -" digits_seen += 1;\n" -" }\n" -" None => return false,\n" -" }\n" -" }\n" -"\n" -" if digits_seen < 2 {\n" -" return false;\n" -" }\n" -"\n" -" sum % 10 == 0\n" -"}\n" -"\n" -"fn main() {\n" -" let cc_number = \"1234 5678 1234 5670\";\n" -" println!(\n" -" \"Is {cc_number} a valid credit card number? {}\",\n" -" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" -" );\n" -"}\n" -"\n" -"// ANCHOR: unit-tests\n" -"#[test]\n" -"fn test_non_digit_cc_number() {\n" -" assert!(!luhn(\"foo\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_empty_cc_number() {\n" -" assert!(!luhn(\"\"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_single_digit_cc_number() {\n" -" assert!(!luhn(\"0\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_two_digit_cc_number() {\n" -" assert!(luhn(\" 0 0 \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_valid_cc_number() {\n" -" assert!(luhn(\"4263 9826 4026 9299\"));\n" -" assert!(luhn(\"4539 3195 0343 6467\"));\n" -" assert!(luhn(\"7992 7398 713\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_invalid_cc_number() {\n" -" assert!(!luhn(\"4223 9826 4026 9299\"));\n" -" assert!(!luhn(\"4539 3195 0343 6476\"));\n" -" assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}\n" -"// ANCHOR_END: unit-tests\n" -"```" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:99 -msgid "([back to exercise](strings-iterators.md))" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:101 -msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: prefix_matches\n" -"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" -" // ANCHOR_END: prefix_matches\n" -"\n" -" let mut request_segments = request_path.split('/');\n" -"\n" -" for prefix_segment in prefix.split('/') {\n" -" let Some(request_segment) = request_segments.next() else {\n" -" return false;\n" -" };\n" -" if request_segment != prefix_segment && prefix_segment != \"*\" {\n" -" return false;\n" -" }\n" -" }\n" -" true\n" -"\n" -" // Alternatively, Iterator::zip() lets us iterate simultaneously over " -"prefix\n" -" // and request segments. The zip() iterator is finished as soon as one " -"of\n" -" // the source iterators is finished, but we need to iterate over all " -"request\n" -" // segments. A neat trick that makes zip() work is to use map() and " -"chain()\n" -" // to produce an iterator that returns Some(str) for each pattern " -"segments,\n" -" // and then returns None indefinitely.\n" -"}\n" -"\n" -"// ANCHOR: unit-tests\n" -"#[test]\n" -"fn test_matches_without_wildcard() {\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/" -"abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/" -"books\"));\n" -"\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/" -"publishers\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_matches_with_wildcard() {\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books\"\n" -" ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/bar/books\"\n" -" ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books/book1\"\n" -" ));\n" -"\n" -" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/" -"publishers\"));\n" -" assert!(!prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/booksByAuthor\"\n" -" ));\n" -"}\n" -"// ANCHOR_END: unit-tests\n" -"\n" -"fn main() {}\n" -"```" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:1 -msgid "Day 3 Morning Exercise" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:5 -msgid "([back to exercise](simple-gui.md))" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:7 -msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: setup\n" -"pub trait Widget {\n" -" /// Natural width of `self`.\n" -" fn width(&self) -> usize;\n" -"\n" -" /// Draw the widget into a buffer.\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" -"\n" -" /// Draw the widget on standard output.\n" -" fn draw(&self) {\n" -" let mut buffer = String::new();\n" -" self.draw_into(&mut buffer);\n" -" println!(\"{buffer}\");\n" -" }\n" -"}\n" -"\n" -"pub struct Label {\n" -" label: String,\n" -"}\n" -"\n" -"impl Label {\n" -" fn new(label: &str) -> Label {\n" -" Label {\n" -" label: label.to_owned(),\n" -" }\n" -" }\n" -"}\n" -"\n" -"pub struct Button {\n" -" label: Label,\n" -" callback: Box,\n" -"}\n" -"\n" -"impl Button {\n" -" fn new(label: &str, callback: Box) -> Button {\n" -" Button {\n" -" label: Label::new(label),\n" -" callback,\n" -" }\n" -" }\n" -"}\n" -"\n" -"pub struct Window {\n" -" title: String,\n" -" widgets: Vec>,\n" -"}\n" -"\n" -"impl Window {\n" -" fn new(title: &str) -> Window {\n" -" Window {\n" -" title: title.to_owned(),\n" -" widgets: Vec::new(),\n" -" }\n" -" }\n" -"\n" -" fn add_widget(&mut self, widget: Box) {\n" -" self.widgets.push(widget);\n" -" }\n" -"\n" -" fn inner_width(&self) -> usize {\n" -" std::cmp::max(\n" -" self.title.chars().count(),\n" -" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" -" )\n" -" }\n" -"}\n" -"\n" -"// ANCHOR_END: setup\n" -"\n" -"// ANCHOR: Window-width\n" -"impl Widget for Window {\n" -" fn width(&self) -> usize {\n" -" // ANCHOR_END: Window-width\n" -" // Add 4 paddings for borders\n" -" self.inner_width() + 4\n" -" }\n" -"\n" -" // ANCHOR: Window-draw_into\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" // ANCHOR_END: Window-draw_into\n" -" let mut inner = String::new();\n" -" for widget in &self.widgets {\n" -" widget.draw_into(&mut inner);\n" -" }\n" -"\n" -" let inner_width = self.inner_width();\n" -"\n" -" // TODO: after learning about error handling, you can change\n" -" // draw_into to return Result<(), std::fmt::Error>. Then use\n" -" // the ?-operator here instead of .unwrap().\n" -" writeln!(buffer, \"+-{:- usize {\n" -" // ANCHOR_END: Button-width\n" -" self.label.width() + 8 // add a bit of padding\n" -" }\n" -"\n" -" // ANCHOR: Button-draw_into\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" // ANCHOR_END: Button-draw_into\n" -" let width = self.width();\n" -" let mut label = String::new();\n" -" self.label.draw_into(&mut label);\n" -"\n" -" writeln!(buffer, \"+{:- usize {\n" -" // ANCHOR_END: Label-width\n" -" self.label\n" -" .lines()\n" -" .map(|line| line.chars().count())\n" -" .max()\n" -" .unwrap_or(0)\n" -" }\n" -"\n" -" // ANCHOR: Label-draw_into\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" // ANCHOR_END: Label-draw_into\n" -" writeln!(buffer, \"{}\", &self.label).unwrap();\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: main\n" -"fn main() {\n" -" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" -" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo." -"\")));\n" -" window.add_widget(Box::new(Button::new(\n" -" \"Click me!\",\n" -" Box::new(|| println!(\"You clicked the button!\")),\n" -" )));\n" -" window.draw();\n" -"}\n" -"// ANCHOR_END: main\n" -"```" -msgstr "" - #: src/exercises/day-3/solutions-afternoon.md:1 msgid "Day 3 Afternoon Exercises" msgstr "" @@ -19759,21 +18866,6 @@ msgstr "" #: src/exercises/day-3/solutions-afternoon.md:7 msgid "" "```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: ffi\n" "mod ffi {\n" " use std::os::raw::{c_char, c_int};\n" " #[cfg(not(target_os = \"macos\"))]\n" @@ -19843,14 +18935,11 @@ msgid "" " path: CString,\n" " dir: *mut ffi::DIR,\n" "}\n" -"// ANCHOR_END: ffi\n" "\n" -"// ANCHOR: DirectoryIterator\n" "impl DirectoryIterator {\n" " fn new(path: &str) -> Result {\n" " // Call opendir and return a Ok value if that worked,\n" " // otherwise return Err with a message.\n" -" // ANCHOR_END: DirectoryIterator\n" " let path = CString::new(path).map_err(|err| format!(\"Invalid path: " "{err}\"))?;\n" " // SAFETY: path.as_ptr() cannot be NULL.\n" @@ -19863,12 +18952,10 @@ msgid "" " }\n" "}\n" "\n" -"// ANCHOR: Iterator\n" "impl Iterator for DirectoryIterator {\n" " type Item = OsString;\n" " fn next(&mut self) -> Option {\n" " // Keep calling readdir until we get a NULL pointer back.\n" -" // ANCHOR_END: Iterator\n" " // SAFETY: self.dir is never NULL.\n" " let dirent = unsafe { ffi::readdir(self.dir) };\n" " if dirent.is_null() {\n" @@ -19883,11 +18970,9 @@ msgid "" " }\n" "}\n" "\n" -"// ANCHOR: Drop\n" "impl Drop for DirectoryIterator {\n" " fn drop(&mut self) {\n" " // Call closedir as needed.\n" -" // ANCHOR_END: Drop\n" " if !self.dir.is_null() {\n" " // SAFETY: self.dir is not NULL.\n" " if unsafe { ffi::closedir(self.dir) } != 0 {\n" @@ -19897,13 +18982,11 @@ msgid "" " }\n" "}\n" "\n" -"// ANCHOR: main\n" "fn main() -> Result<(), String> {\n" " let iter = DirectoryIterator::new(\".\")?;\n" " println!(\"files: {:#?}\", iter.collect::>());\n" " Ok(())\n" "}\n" -"// ANCHOR_END: main\n" "\n" "#[cfg(test)]\n" "mod tests {\n" @@ -19959,21 +19042,6 @@ msgstr "" #: src/exercises/bare-metal/solutions-morning.md:7 msgid "" "```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: top\n" "#![no_main]\n" "#![no_std]\n" "\n" @@ -19981,7 +19049,6 @@ msgid "" "\n" "use core::fmt::Write;\n" "use cortex_m_rt::entry;\n" -"// ANCHOR_END: top\n" "use core::cmp::{max, min};\n" "use lsm303agr::{AccelOutputDataRate, Lsm303agr, MagOutputDataRate};\n" "use microbit::display::blocking::Display;\n" @@ -19995,7 +19062,6 @@ msgid "" "const COMPASS_SCALE: i32 = 30000;\n" "const ACCELEROMETER_SCALE: i32 = 700;\n" "\n" -"// ANCHOR: main\n" "#[entry]\n" "fn main() -> ! {\n" " let board = Board::take().unwrap();\n" @@ -20009,7 +19075,6 @@ msgid "" " );\n" "\n" " // Set up the I2C controller and Inertial Measurement Unit.\n" -" // ANCHOR_END: main\n" " writeln!(serial, \"Setting up IMU...\").unwrap();\n" " let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::" "K100);\n" @@ -20026,12 +19091,10 @@ msgid "" " let mut mode = Mode::Compass;\n" " let mut button_pressed = false;\n" "\n" -" // ANCHOR: loop\n" " writeln!(serial, \"Ready.\").unwrap();\n" "\n" " loop {\n" " // Read compass data and log it to the serial port.\n" -" // ANCHOR_END: loop\n" " while !(imu.mag_status().unwrap().xyz_new_data\n" " && imu.accel_status().unwrap().xyz_new_data)\n" " {}\n" @@ -20128,34 +19191,18 @@ msgid "([back to exercise](rtc.md))" msgstr "" #: src/exercises/bare-metal/solutions-afternoon.md:7 -msgid "`main.rs`:" +msgid "_main.rs_:" msgstr "" #: src/exercises/bare-metal/solutions-afternoon.md:9 msgid "" "```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: top\n" "#![no_main]\n" "#![no_std]\n" "\n" "mod exceptions;\n" "mod logger;\n" "mod pl011;\n" -"// ANCHOR_END: top\n" "mod pl031;\n" "\n" "use crate::pl031::Rtc;\n" @@ -20163,7 +19210,6 @@ msgid "" "use arm_gic::{irq_enable, wfi};\n" "use chrono::{TimeZone, Utc};\n" "use core::hint::spin_loop;\n" -"// ANCHOR: imports\n" "use crate::pl011::Uart;\n" "use arm_gic::gicv3::GicV3;\n" "use core::panic::PanicInfo;\n" @@ -20177,14 +19223,12 @@ msgid "" "\n" "/// Base address of the primary PL011 UART.\n" "const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" -"// ANCHOR_END: imports\n" "\n" "/// Base address of the PL031 RTC.\n" "const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;\n" "/// The IRQ used by the PL031 RTC.\n" "const PL031_IRQ: IntId = IntId::spi(2);\n" "\n" -"// ANCHOR: main\n" "#[no_mangle]\n" "extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" " // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " @@ -20202,7 +19246,6 @@ msgid "" " let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, " "GICR_BASE_ADDRESS) };\n" " gic.setup();\n" -" // ANCHOR_END: main\n" "\n" " // Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 " "device,\n" @@ -20264,7 +19307,6 @@ msgid "" " );\n" " info!(\"Finished waiting\");\n" "\n" -" // ANCHOR: main_end\n" " system_off::().unwrap();\n" "}\n" "\n" @@ -20274,31 +19316,16 @@ msgid "" " system_off::().unwrap();\n" " loop {}\n" "}\n" -"// ANCHOR_END: main_end\n" "```" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md:149 -msgid "`pl031.rs`:" +#: src/exercises/bare-metal/solutions-afternoon.md:127 +msgid "_pl031.rs_:" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md:151 +#: src/exercises/bare-metal/solutions-afternoon.md:129 msgid "" "```rust\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" "use core::ptr::{addr_of, addr_of_mut};\n" "\n" "#[repr(C, align(4))]\n" @@ -20379,8 +19406,8 @@ msgid "" "\n" " /// Returns whether there is currently an interrupt pending.\n" " ///\n" -" /// This should be true iff `matched` returns true and the interrupt is\n" -" /// masked.\n" +" /// This should be true if and only if `matched` returns true and the\n" +" /// interrupt is masked.\n" " pub fn interrupt_pending(&self) -> bool {\n" " // Safe because we know that self.registers points to the control\n" " // registers of a PL031 device which is appropriately mapped.\n" @@ -20427,21 +19454,6 @@ msgstr "" #: src/exercises/concurrency/solutions-morning.md:7 msgid "" "```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: Philosopher\n" "use std::sync::{mpsc, Arc, Mutex};\n" "use std::thread;\n" "use std::time::Duration;\n" @@ -20450,39 +19462,32 @@ msgid "" "\n" "struct Philosopher {\n" " name: String,\n" -" // ANCHOR_END: Philosopher\n" " left_fork: Arc>,\n" " right_fork: Arc>,\n" " thoughts: mpsc::SyncSender,\n" "}\n" "\n" -"// ANCHOR: Philosopher-think\n" "impl Philosopher {\n" " fn think(&self) {\n" " self.thoughts\n" " .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" " .unwrap();\n" " }\n" -" // ANCHOR_END: Philosopher-think\n" "\n" -" // ANCHOR: Philosopher-eat\n" " fn eat(&self) {\n" -" // ANCHOR_END: Philosopher-eat\n" " println!(\"{} is trying to eat\", &self.name);\n" " let left = self.left_fork.lock().unwrap();\n" " let right = self.right_fork.lock().unwrap();\n" "\n" -" // ANCHOR: Philosopher-eat-end\n" " println!(\"{} is eating...\", &self.name);\n" " thread::sleep(Duration::from_millis(10));\n" " }\n" "}\n" "\n" "static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" +" &[\"Socrates\", \"Hypatia\", \"Plato\", \"Aristotle\", \"Pythagoras\"];\n" "\n" "fn main() {\n" -" // ANCHOR_END: Philosopher-eat-end\n" " let (tx, rx) = mpsc::sync_channel(10);\n" "\n" " let forks = (0..PHILOSOPHERS.len())\n" @@ -20524,34 +19529,19 @@ msgid "" "```" msgstr "" -#: src/exercises/concurrency/solutions-morning.md:104 +#: src/exercises/concurrency/solutions-morning.md:82 msgid "Link Checker" msgstr "" -#: src/exercises/concurrency/solutions-morning.md:106 +#: src/exercises/concurrency/solutions-morning.md:84 msgid "([back to exercise](link-checker.md))" msgstr "" -#: src/exercises/concurrency/solutions-morning.md:108 +#: src/exercises/concurrency/solutions-morning.md:86 msgid "" "```rust,compile_fail\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" "use std::{sync::Arc, sync::Mutex, sync::mpsc, thread};\n" "\n" -"// ANCHOR: setup\n" "use reqwest::{blocking::Client, Url};\n" "use scraper::{Html, Selector};\n" "use thiserror::Error;\n" @@ -20563,9 +19553,7 @@ msgid "" " #[error(\"bad http response: {0}\")]\n" " BadResponse(String),\n" "}\n" -"// ANCHOR_END: setup\n" "\n" -"// ANCHOR: visit_page\n" "#[derive(Debug)]\n" "struct CrawlCommand {\n" " url: Url,\n" @@ -20606,7 +19594,6 @@ msgid "" " }\n" " Ok(link_urls)\n" "}\n" -"// ANCHOR_END: visit_page\n" "\n" "struct CrawlState {\n" " domain: String,\n" @@ -20631,7 +19618,7 @@ msgid "" " url_domain == self.domain\n" " }\n" "\n" -" /// Mark the given page as visited, returning true if it had already\n" +" /// Mark the given page as visited, returning false if it had already\n" " /// been visited.\n" " fn mark_visited(&mut self, url: &Url) -> bool {\n" " self.visited_pages.insert(url.as_str().to_string())\n" @@ -20738,21 +19725,6 @@ msgstr "" #: src/exercises/concurrency/solutions-afternoon.md:7 msgid "" "```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: Philosopher\n" "use std::sync::Arc;\n" "use tokio::time;\n" "use tokio::sync::mpsc::{self, Sender};\n" @@ -20762,13 +19734,11 @@ msgid "" "\n" "struct Philosopher {\n" " name: String,\n" -" // ANCHOR_END: Philosopher\n" " left_fork: Arc>,\n" " right_fork: Arc>,\n" " thoughts: Sender,\n" "}\n" "\n" -"// ANCHOR: Philosopher-think\n" "impl Philosopher {\n" " async fn think(&self) {\n" " self.thoughts\n" @@ -20776,12 +19746,9 @@ msgid "" "await\n" " .unwrap();\n" " }\n" -" // ANCHOR_END: Philosopher-think\n" "\n" -" // ANCHOR: Philosopher-eat\n" " async fn eat(&self) {\n" " // Pick up forks...\n" -" // ANCHOR_END: Philosopher-eat\n" " let _first_lock = self.left_fork.lock().await;\n" " // Add a delay before picking the second fork to allow the " "execution\n" @@ -20789,22 +19756,18 @@ msgid "" " time::sleep(time::Duration::from_millis(1)).await;\n" " let _second_lock = self.right_fork.lock().await;\n" "\n" -" // ANCHOR: Philosopher-eat-body\n" " println!(\"{} is eating...\", &self.name);\n" " time::sleep(time::Duration::from_millis(5)).await;\n" -" // ANCHOR_END: Philosopher-eat-body\n" "\n" " // The locks are dropped here\n" -" // ANCHOR: Philosopher-eat-end\n" " }\n" "}\n" "\n" "static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" +" &[\"Socrates\", \"Hypatia\", \"Plato\", \"Aristotle\", \"Pythagoras\"];\n" "\n" "#[tokio::main]\n" "async fn main() {\n" -" // ANCHOR_END: Philosopher-eat-end\n" " // Create forks\n" " let mut forks = vec![];\n" " (0..PHILOSOPHERS.len()).for_each(|_| forks.push(Arc::new(Mutex::" @@ -20854,43 +19817,26 @@ msgid "" "```" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md:121 +#: src/exercises/concurrency/solutions-afternoon.md:97 msgid "([back to exercise](chat-app.md))" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md:125 +#: src/exercises/concurrency/solutions-afternoon.md:101 msgid "" "```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: setup\n" "use futures_util::sink::SinkExt;\n" +"use futures_util::stream::StreamExt;\n" "use std::error::Error;\n" "use std::net::SocketAddr;\n" "use tokio::net::{TcpListener, TcpStream};\n" "use tokio::sync::broadcast::{channel, Sender};\n" "use tokio_websockets::{Message, ServerBuilder, WebsocketStream};\n" -"// ANCHOR_END: setup\n" "\n" -"// ANCHOR: handle_connection\n" "async fn handle_connection(\n" " addr: SocketAddr,\n" " mut ws_stream: WebsocketStream,\n" " bcast_tx: Sender,\n" ") -> Result<(), Box> {\n" -" // ANCHOR_END: handle_connection\n" "\n" " ws_stream\n" " .send(Message::text(\"Welcome to chat! Type a message\".into()))\n" @@ -20906,9 +19852,10 @@ msgid "" " incoming = ws_stream.next() => {\n" " match incoming {\n" " Some(Ok(msg)) => {\n" -" let msg = msg.as_text()?;\n" -" println!(\"From client {addr:?} {msg:?}\");\n" -" bcast_tx.send(msg.into())?;\n" +" if let Some(text) = msg.as_text() {\n" +" println!(\"From client {addr:?} {text:?}\");\n" +" bcast_tx.send(text.into())?;\n" +" }\n" " }\n" " Some(Err(err)) => return Err(err.into()),\n" " None => return Ok(()),\n" @@ -20919,7 +19866,6 @@ msgid "" " }\n" " }\n" " }\n" -" // ANCHOR: main\n" "}\n" "\n" "#[tokio::main]\n" @@ -20941,28 +19887,13 @@ msgid "" " });\n" " }\n" "}\n" -"// ANCHOR_END: main\n" "```" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md:210 +#: src/exercises/concurrency/solutions-afternoon.md:168 msgid "" "```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: setup\n" +"use futures_util::stream::StreamExt;\n" "use futures_util::SinkExt;\n" "use http::Uri;\n" "use tokio::io::{AsyncBufReadExt, BufReader};\n" @@ -20970,22 +19901,24 @@ msgid "" "\n" "#[tokio::main]\n" "async fn main() -> Result<(), tokio_websockets::Error> {\n" -" let mut ws_stream = ClientBuilder::from_uri(Uri::" -"from_static(\"ws://127.0.0.1:2000\"))\n" -" .connect()\n" -" .await?;\n" +" let (mut ws_stream, _) =\n" +" ClientBuilder::from_uri(Uri::from_static(\"ws://127.0.0.1:2000\"))\n" +" .connect()\n" +" .await?;\n" "\n" " let stdin = tokio::io::stdin();\n" " let mut stdin = BufReader::new(stdin).lines();\n" "\n" -" // ANCHOR_END: setup\n" " // Continuous loop for concurrently sending and receiving messages.\n" " loop {\n" " tokio::select! {\n" " incoming = ws_stream.next() => {\n" " match incoming {\n" -" Some(Ok(msg)) => println!(\"From server: {}\", msg." -"as_text()?),\n" +" Some(Ok(msg)) => {\n" +" if let Some(text) = msg.as_text() {\n" +" println!(\"From server: {}\", text);\n" +" }\n" +" },\n" " Some(Err(err)) => return Err(err.into()),\n" " None => return Ok(()),\n" " }\n"