diff --git a/po/de.po b/po/de.po
index a3c42e59..742d24f5 100644
--- a/po/de.po
+++ b/po/de.po
@@ -10,7 +10,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 3.2.2\n"
+"X-Generator: Poedit 3.3.1\n"
#: src/SUMMARY.md:3
msgid "Welcome to Comprehensive Rust 🦀"
@@ -25,543 +25,544 @@ msgid "Course Structure"
msgstr "Kursstruktur"
#: src/SUMMARY.md:6
-msgid "Day 4"
-msgstr "Der vierte Tag"
-
-#: src/SUMMARY.md:7
msgid "Keyboard Shortcuts"
msgstr "Tastaturkürzel"
-#: src/SUMMARY.md:8
+#: src/SUMMARY.md:7
msgid "Translations"
msgstr "Übersetzungen"
-#: src/SUMMARY.md:9
+#: src/SUMMARY.md:8
msgid "Using Cargo"
msgstr "Cargo verwenden"
-#: src/SUMMARY.md:10
+#: src/SUMMARY.md:9
msgid "Rust Ecosystem"
msgstr "Rust Ökosystem"
-#: src/SUMMARY.md:11
+#: src/SUMMARY.md:10
msgid "Code Samples"
msgstr "Codebeispiele"
-#: src/SUMMARY.md:12
+#: src/SUMMARY.md:11
msgid "Running Cargo Locally"
msgstr "Cargo lokal ausführen"
-#: src/SUMMARY.md:15
+#: src/SUMMARY.md:14
msgid "Day 1: Morning"
msgstr "Tag 1: Morgens"
-#: src/SUMMARY.md:19 src/SUMMARY.md:76 src/SUMMARY.md:129 src/SUMMARY.md:185 src/SUMMARY.md:259
+#: src/SUMMARY.md:18 src/SUMMARY.md:75 src/SUMMARY.md:128 src/SUMMARY.md:185 src/SUMMARY.md:211
+#: src/SUMMARY.md:259
msgid "Welcome"
msgstr "Willkommen"
-#: src/SUMMARY.md:20
+#: src/SUMMARY.md:19
msgid "What is Rust?"
msgstr "Was ist Rust?"
-#: src/SUMMARY.md:21
+#: src/SUMMARY.md:20
msgid "Hello World!"
msgstr "Hallo Welt!"
-#: src/SUMMARY.md:22
+#: src/SUMMARY.md:21
msgid "Small Example"
msgstr "Ein kleines Beispiel"
-#: src/SUMMARY.md:23
+#: src/SUMMARY.md:22
msgid "Why Rust?"
msgstr "Warum Rust?"
-#: src/SUMMARY.md:24
+#: src/SUMMARY.md:23
msgid "Compile Time Guarantees"
msgstr "Kompilierzeitgarantien"
-#: src/SUMMARY.md:25
+#: src/SUMMARY.md:24
msgid "Runtime Guarantees"
msgstr "Laufzeitgarantien"
-#: src/SUMMARY.md:26
+#: src/SUMMARY.md:25
msgid "Modern Features"
msgstr "Moderne Merkmale"
-#: src/SUMMARY.md:27
+#: src/SUMMARY.md:26
msgid "Basic Syntax"
msgstr "Grundlegende Syntax"
-#: src/SUMMARY.md:28
+#: src/SUMMARY.md:27
msgid "Scalar Types"
msgstr "Skalare Typen"
-#: src/SUMMARY.md:29
+#: src/SUMMARY.md:28
msgid "Compound Types"
msgstr "Verbundtypen"
-#: src/SUMMARY.md:30
+#: src/SUMMARY.md:29
msgid "References"
msgstr "Referenzen"
-#: src/SUMMARY.md:31
+#: src/SUMMARY.md:30
msgid "Dangling References"
msgstr "Hängende Referenzen"
-#: src/SUMMARY.md:32
+#: src/SUMMARY.md:31
msgid "Slices"
msgstr "Anteilstypen"
-#: src/SUMMARY.md:33
+#: src/SUMMARY.md:32
msgid "String vs str"
msgstr "String vs. str"
-#: src/SUMMARY.md:34
+#: src/SUMMARY.md:33
msgid "Functions"
msgstr "Funktionen"
-#: src/SUMMARY.md:35
+#: src/SUMMARY.md:34
msgid "Rustdoc"
msgstr ""
-#: src/SUMMARY.md:36 src/SUMMARY.md:83
+#: src/SUMMARY.md:35 src/SUMMARY.md:82
msgid "Methods"
msgstr "Methoden"
-#: src/SUMMARY.md:37
+#: src/SUMMARY.md:36
msgid "Overloading"
msgstr "Überladen"
-#: src/SUMMARY.md:38 src/SUMMARY.md:67 src/SUMMARY.md:91 src/SUMMARY.md:120 src/SUMMARY.md:149
-#: src/SUMMARY.md:177 src/SUMMARY.md:200 src/SUMMARY.md:227 src/SUMMARY.md:247 src/SUMMARY.md:273
-#: src/SUMMARY.md:299
+#: src/SUMMARY.md:37 src/SUMMARY.md:66 src/SUMMARY.md:90 src/SUMMARY.md:119 src/SUMMARY.md:148
+#: src/SUMMARY.md:177 src/SUMMARY.md:204 src/SUMMARY.md:225 src/SUMMARY.md:251 src/SUMMARY.md:273
+#: src/SUMMARY.md:293
msgid "Exercises"
msgstr "Übungen"
-#: src/SUMMARY.md:39
+#: src/SUMMARY.md:38
msgid "Implicit Conversions"
msgstr "Implizite Konvertierungen"
-#: src/SUMMARY.md:40
+#: src/SUMMARY.md:39
msgid "Arrays and for Loops"
msgstr "Arrays und for-Schleifen"
-#: src/SUMMARY.md:42
+#: src/SUMMARY.md:41
msgid "Day 1: Afternoon"
msgstr "Tag 1: Nachmittags"
-#: src/SUMMARY.md:44
+#: src/SUMMARY.md:43
msgid "Variables"
msgstr "Variablen"
-#: src/SUMMARY.md:45
+#: src/SUMMARY.md:44
msgid "Type Inference"
msgstr "Typinferenz"
-#: src/SUMMARY.md:46
+#: src/SUMMARY.md:45
msgid "static & const"
msgstr "static & const"
-#: src/SUMMARY.md:47
+#: src/SUMMARY.md:46
msgid "Scopes and Shadowing"
msgstr "Gültigkeitsbereiche und Verschattungen"
-#: src/SUMMARY.md:48
+#: src/SUMMARY.md:47
msgid "Memory Management"
msgstr "Speicherverwaltung"
-#: src/SUMMARY.md:49
+#: src/SUMMARY.md:48
msgid "Stack vs Heap"
msgstr "Stapelspeicher vs. Haldenspeicher"
-#: src/SUMMARY.md:50
+#: src/SUMMARY.md:49
msgid "Stack Memory"
msgstr "Stapelspeicher"
-#: src/SUMMARY.md:51
+#: src/SUMMARY.md:50
msgid "Manual Memory Management"
msgstr "Manuelle Speicherverwaltung"
-#: src/SUMMARY.md:52
+#: src/SUMMARY.md:51
msgid "Scope-Based Memory Management"
msgstr "Gültigkeitsbereichbasierte Speicherverwaltung"
-#: src/SUMMARY.md:53
+#: src/SUMMARY.md:52
msgid "Garbage Collection"
msgstr "Automatische Speicherbereinigung"
-#: src/SUMMARY.md:54
+#: src/SUMMARY.md:53
msgid "Rust Memory Management"
msgstr "Rust Speicherverwaltung"
-#: src/SUMMARY.md:55
+#: src/SUMMARY.md:54
msgid "Comparison"
msgstr "Vergleich"
-#: src/SUMMARY.md:56
+#: src/SUMMARY.md:55
msgid "Ownership"
msgstr "Eigentümerschaft"
-#: src/SUMMARY.md:57
+#: src/SUMMARY.md:56
msgid "Move Semantics"
msgstr "Semantik des Verschiebens"
-#: src/SUMMARY.md:58
+#: src/SUMMARY.md:57
msgid "Moved Strings in Rust"
msgstr "Verschieben von String in Rust"
-#: src/SUMMARY.md:59
+#: src/SUMMARY.md:58
msgid "Double Frees in Modern C++"
msgstr "Doppel-Freigabe-Fehler in modernem C++"
-#: src/SUMMARY.md:60
+#: src/SUMMARY.md:59
msgid "Moves in Function Calls"
msgstr "Verschieben in Funktionsaufrufen"
-#: src/SUMMARY.md:61
+#: src/SUMMARY.md:60
msgid "Copying and Cloning"
msgstr "Kopieren und Klonen"
-#: src/SUMMARY.md:62
+#: src/SUMMARY.md:61
msgid "Borrowing"
msgstr "Ausleihen"
-#: src/SUMMARY.md:63
+#: src/SUMMARY.md:62
msgid "Shared and Unique Borrows"
msgstr "Geteiltes und einmaliges Ausleihen"
-#: src/SUMMARY.md:64
+#: src/SUMMARY.md:63
msgid "Lifetimes"
msgstr "Lebensdauern"
-#: src/SUMMARY.md:65
+#: src/SUMMARY.md:64
msgid "Lifetimes in Function Calls"
msgstr "Lebensdauern in Funktionsaufrufen"
-#: src/SUMMARY.md:66
+#: src/SUMMARY.md:65
msgid "Lifetimes in Data Structures"
msgstr "Lebensdauern in Datenstrukturen"
-#: src/SUMMARY.md:68
+#: src/SUMMARY.md:67
msgid "Designing a Library"
msgstr "Entwerfen einer Bibliothek"
-#: src/SUMMARY.md:69
+#: src/SUMMARY.md:68
msgid "Iterators and Ownership"
msgstr "Iteratoren und Eigentümerschaft"
-#: src/SUMMARY.md:72
+#: src/SUMMARY.md:71
msgid "Day 2: Morning"
msgstr "Tag 2: Morgens"
-#: src/SUMMARY.md:77
+#: src/SUMMARY.md:76
msgid "Structs"
msgstr "Strukturen"
-#: src/SUMMARY.md:78
+#: src/SUMMARY.md:77
msgid "Tuple Structs"
msgstr "Tupelstrukturen"
-#: src/SUMMARY.md:79
+#: src/SUMMARY.md:78
msgid "Field Shorthand Syntax"
msgstr "Feld Abkürzungs Syntax"
-#: src/SUMMARY.md:80
+#: src/SUMMARY.md:79
msgid "Enums"
msgstr "Aufzählungstypen"
-#: src/SUMMARY.md:81
+#: src/SUMMARY.md:80
msgid "Variant Payloads"
msgstr "Varianteninhalte"
-#: src/SUMMARY.md:82
+#: src/SUMMARY.md:81
msgid "Enum Sizes"
msgstr "Größen von Aufzählungstypen"
-#: src/SUMMARY.md:84
+#: src/SUMMARY.md:83
msgid "Method Receiver"
msgstr "Methodenempfänger"
-#: src/SUMMARY.md:85 src/SUMMARY.md:160 src/SUMMARY.md:195
+#: src/SUMMARY.md:84 src/SUMMARY.md:159 src/SUMMARY.md:272
msgid "Example"
msgstr "Beispiel"
-#: src/SUMMARY.md:86
+#: src/SUMMARY.md:85
msgid "Pattern Matching"
msgstr "Musterabgleich"
-#: src/SUMMARY.md:87
+#: src/SUMMARY.md:86
msgid "Destructuring Enums"
msgstr "Aufzählungstypen destrukturieren"
-#: src/SUMMARY.md:88
+#: src/SUMMARY.md:87
msgid "Destructuring Structs"
msgstr "Strukturen destrukturieren"
-#: src/SUMMARY.md:89
+#: src/SUMMARY.md:88
msgid "Destructuring Arrays"
msgstr "Arrays destrukturieren"
-#: src/SUMMARY.md:90
+#: src/SUMMARY.md:89
msgid "Match Guards"
msgstr "Abgleichsbedingungen"
-#: src/SUMMARY.md:92
+#: src/SUMMARY.md:91
msgid "Health Statistics"
msgstr "Gesundheitsstatistiken"
-#: src/SUMMARY.md:93
+#: src/SUMMARY.md:92
msgid "Points and Polygons"
msgstr "Punkte und Polygone"
-#: src/SUMMARY.md:95
+#: src/SUMMARY.md:94
msgid "Day 2: Afternoon"
msgstr "Tag 2: Nachmittags"
-#: src/SUMMARY.md:97 src/SUMMARY.md:240
+#: src/SUMMARY.md:96 src/SUMMARY.md:286
msgid "Control Flow"
msgstr "Kontrollfluss"
-#: src/SUMMARY.md:98
+#: src/SUMMARY.md:97
msgid "Blocks"
msgstr "Blöcke"
-#: src/SUMMARY.md:99
+#: src/SUMMARY.md:98
msgid "if expressions"
msgstr "if-Ausdrücke"
-#: src/SUMMARY.md:100
+#: src/SUMMARY.md:99
msgid "if let expressions"
msgstr "if let-Ausdrücke"
-#: src/SUMMARY.md:101
+#: src/SUMMARY.md:100
msgid "while expressions"
msgstr "while-Ausdrücke"
-#: src/SUMMARY.md:102
+#: src/SUMMARY.md:101
msgid "while let expressions"
msgstr "while let-Ausdrücke"
-#: src/SUMMARY.md:103
+#: src/SUMMARY.md:102
msgid "for expressions"
msgstr "for-Ausdrücke"
-#: src/SUMMARY.md:104
+#: src/SUMMARY.md:103
msgid "loop expressions"
msgstr "loop-Ausdrücke"
-#: src/SUMMARY.md:105
+#: src/SUMMARY.md:104
msgid "match expressions"
msgstr "match-Ausdrücke"
-#: src/SUMMARY.md:106
+#: src/SUMMARY.md:105
msgid "break & continue"
msgstr "break & continue"
-#: src/SUMMARY.md:107
+#: src/SUMMARY.md:106
msgid "Standard Library"
msgstr "Standardbibliothek"
-#: src/SUMMARY.md:108
+#: src/SUMMARY.md:107
msgid "Option and Result"
msgstr "Option und Result"
-#: src/SUMMARY.md:109
+#: src/SUMMARY.md:108
msgid "String"
msgstr "String"
-#: src/SUMMARY.md:110
+#: src/SUMMARY.md:109
msgid "Vec"
msgstr "Vec"
-#: src/SUMMARY.md:111
+#: src/SUMMARY.md:110
msgid "HashMap"
msgstr "HashMap"
-#: src/SUMMARY.md:112
+#: src/SUMMARY.md:111
msgid "Box"
msgstr "Box"
-#: src/SUMMARY.md:113
+#: src/SUMMARY.md:112
msgid "Recursive Data Types"
msgstr "Rekursive Datentypen"
-#: src/SUMMARY.md:114
+#: src/SUMMARY.md:113
msgid "Niche Optimization"
msgstr "Nischenoptimierung"
-#: src/SUMMARY.md:115
+#: src/SUMMARY.md:114
msgid "Rc"
msgstr "Rc"
-#: src/SUMMARY.md:116
+#: src/SUMMARY.md:115
msgid "Modules"
msgstr "Module"
-#: src/SUMMARY.md:117
+#: src/SUMMARY.md:116
msgid "Visibility"
msgstr "Sichtbarkeit"
-#: src/SUMMARY.md:118
+#: src/SUMMARY.md:117
msgid "Paths"
msgstr "Pfade"
-#: src/SUMMARY.md:119
+#: src/SUMMARY.md:118
msgid "Filesystem Hierarchy"
msgstr "Dateisystemhierarchie"
-#: src/SUMMARY.md:121
+#: src/SUMMARY.md:120
msgid "Luhn Algorithm"
msgstr "Luhn-Algorithmus"
-#: src/SUMMARY.md:122
+#: src/SUMMARY.md:121
msgid "Strings and Iterators"
msgstr "Strings und Iteratoren"
-#: src/SUMMARY.md:125
+#: src/SUMMARY.md:124
msgid "Day 3: Morning"
msgstr "Tag 3: Morgens"
-#: src/SUMMARY.md:130
+#: src/SUMMARY.md:129
msgid "Generics"
msgstr "Generische Datentypen und Methoden"
-#: src/SUMMARY.md:131
+#: src/SUMMARY.md:130
msgid "Generic Data Types"
msgstr "Generische Datentypen"
-#: src/SUMMARY.md:132
+#: src/SUMMARY.md:131
msgid "Generic Methods"
msgstr "Generische Methoden"
-#: src/SUMMARY.md:133
+#: src/SUMMARY.md:132
msgid "Monomorphization"
msgstr "Monomorphisierung"
-#: src/SUMMARY.md:134
+#: src/SUMMARY.md:133
msgid "Traits"
msgstr "Merkmale"
-#: src/SUMMARY.md:135
+#: src/SUMMARY.md:134
msgid "Trait Objects"
msgstr "Merkmalsobjekte"
-#: src/SUMMARY.md:136
+#: src/SUMMARY.md:135
msgid "Deriving Traits"
msgstr "Ableitung von Merkmalen"
-#: src/SUMMARY.md:137
+#: src/SUMMARY.md:136
msgid "Default Methods"
msgstr "Standardmethoden"
-#: src/SUMMARY.md:138
+#: src/SUMMARY.md:137
msgid "Trait Bounds"
msgstr "Merkmalsgrenzen"
-#: src/SUMMARY.md:139
+#: src/SUMMARY.md:138
msgid "impl Trait"
msgstr "impl Merkmal"
-#: src/SUMMARY.md:140
+#: src/SUMMARY.md:139
msgid "Important Traits"
msgstr "Wichtige Merkmale"
-#: src/SUMMARY.md:141
+#: src/SUMMARY.md:140
msgid "Iterator"
msgstr "Iterator"
-#: src/SUMMARY.md:142
+#: src/SUMMARY.md:141
msgid "FromIterator"
msgstr "FromIterator"
-#: src/SUMMARY.md:143
+#: src/SUMMARY.md:142
msgid "From and Into"
msgstr "From und Into"
-#: src/SUMMARY.md:144
+#: src/SUMMARY.md:143
msgid "Read and Write"
msgstr "Read und Write"
-#: src/SUMMARY.md:145
+#: src/SUMMARY.md:144
msgid "Drop"
msgstr "Drop"
-#: src/SUMMARY.md:146
+#: src/SUMMARY.md:145
msgid "Default"
msgstr "Default Merkmal"
-#: src/SUMMARY.md:147
+#: src/SUMMARY.md:146
msgid "Operators: Add, Mul, ..."
msgstr "Operatoren: Add, Mul, ..."
-#: src/SUMMARY.md:148
-msgid "Closures"
-msgstr "Funktionsabschlüsse"
+#: src/SUMMARY.md:147
+msgid "Closures: Fn, FnMut, FnOnce"
+msgstr ""
-#: src/SUMMARY.md:150
+#: src/SUMMARY.md:149
msgid "A Simple GUI Library"
msgstr "Eine einfache GUI-Bibliothek"
-#: src/SUMMARY.md:152
+#: src/SUMMARY.md:151
msgid "Day 3: Afternoon"
msgstr "Tag 3: Nachmittags"
-#: src/SUMMARY.md:154
+#: src/SUMMARY.md:153
msgid "Error Handling"
msgstr "Fehlerbehandlung"
-#: src/SUMMARY.md:155
+#: src/SUMMARY.md:154
msgid "Panics"
msgstr "Laufzeitabbrüche"
-#: src/SUMMARY.md:156
+#: src/SUMMARY.md:155
msgid "Catching Stack Unwinding"
msgstr "Abfangen der Auflösung des Stapelspeichers"
-#: src/SUMMARY.md:157
+#: src/SUMMARY.md:156
msgid "Structured Error Handling"
msgstr "Strukturierte Fehlerbehandlung"
-#: src/SUMMARY.md:158
+#: src/SUMMARY.md:157
msgid "Propagating Errors with ?"
msgstr "Weitergabe von Fehlern mit ?"
-#: src/SUMMARY.md:159
+#: src/SUMMARY.md:158
msgid "Converting Error Types"
msgstr "Fehlertypen konvertieren"
-#: src/SUMMARY.md:161
+#: src/SUMMARY.md:160
msgid "Deriving Error Enums"
msgstr "Ableiten von Fehleraufzählungen"
-#: src/SUMMARY.md:162
+#: src/SUMMARY.md:161
msgid "Dynamic Error Types"
msgstr "Dynamische Fehlertypen"
-#: src/SUMMARY.md:163
+#: src/SUMMARY.md:162
msgid "Adding Context to Errors"
msgstr "Kontext zu Fehlern hinzufügen"
-#: src/SUMMARY.md:164
+#: src/SUMMARY.md:163
msgid "Testing"
msgstr "Testen"
-#: src/SUMMARY.md:165
+#: src/SUMMARY.md:164
msgid "Unit Tests"
msgstr "Unit-Tests"
-#: src/SUMMARY.md:166
+#: src/SUMMARY.md:165
msgid "Test Modules"
msgstr "Testmodule"
-#: src/SUMMARY.md:167
+#: src/SUMMARY.md:166
msgid "Documentation Tests"
msgstr "Dokumentationstests"
-#: src/SUMMARY.md:168
+#: src/SUMMARY.md:167
msgid "Integration Tests"
msgstr "Integrationstests"
+#: src/SUMMARY.md:168
+msgid "Useful crates"
+msgstr "Nützliche Kisten (Crates)"
+
#: src/SUMMARY.md:169
msgid "Unsafe Rust"
msgstr "Unsicheres Rust"
@@ -598,398 +599,398 @@ msgstr "Unsichere Merkmale implementieren"
msgid "Safe FFI Wrapper"
msgstr "Sicherer FFI-Wrapper"
-#: src/SUMMARY.md:181
-msgid "Day 4: Morning"
-msgstr "Tag 4: Morgens"
-
-#: src/SUMMARY.md:186
-msgid "Concurrency"
-msgstr "Nebenläufigkeit"
-
-#: src/SUMMARY.md:187
-msgid "Threads"
-msgstr "Ausführungsstrang"
-
-#: src/SUMMARY.md:188
-msgid "Scoped Threads"
-msgstr "Ausführungsstrang mit Sichtbarkeitsbereich"
-
-#: src/SUMMARY.md:189
-msgid "Channels"
-msgstr "Kanäle"
-
-#: src/SUMMARY.md:190
-msgid "Unbounded Channels"
-msgstr "Unbegrenzte Kanäle"
-
-#: src/SUMMARY.md:191
-msgid "Bounded Channels"
-msgstr "Unbeschränkte Kanäle"
-
-#: src/SUMMARY.md:192
-msgid "Shared State"
-msgstr "Geteilter Zustand"
-
-#: src/SUMMARY.md:193
-msgid "Arc"
-msgstr "Arc"
-
-#: src/SUMMARY.md:194
-msgid "Mutex"
-msgstr "Mutex"
-
-#: src/SUMMARY.md:196
-msgid "Send and Sync"
-msgstr "Send und Sync"
-
-#: src/SUMMARY.md:196
-msgid "Send"
-msgstr "Send"
-
-#: src/SUMMARY.md:196
-msgid "Sync"
-msgstr "Sync"
-
-#: src/SUMMARY.md:199
-msgid "Examples"
-msgstr "Beispiele"
-
-#: src/SUMMARY.md:201
-msgid "Dining Philosophers"
-msgstr "Philosophenproblem"
-
-#: src/SUMMARY.md:202
-msgid "Multi-threaded Link Checker"
-msgstr "Link Überprüfung mit mehreren Ausführungssträngen"
-
-#: src/SUMMARY.md:204
-msgid "Day 4: Afternoon (Android)"
-msgstr "Tag 4: Nachmittags (Android)"
-
-#: src/SUMMARY.md:204 src/SUMMARY.md:297
+#: src/SUMMARY.md:181 src/SUMMARY.md:249
msgid "Android"
msgstr "Android"
-#: src/SUMMARY.md:209
+#: src/SUMMARY.md:186
msgid "Setup"
msgstr "Einrichtung"
-#: src/SUMMARY.md:210
+#: src/SUMMARY.md:187
msgid "Build Rules"
msgstr "Regeln beim Bauen"
-#: src/SUMMARY.md:211
+#: src/SUMMARY.md:188
msgid "Binary"
msgstr "Binärdatei"
-#: src/SUMMARY.md:212
+#: src/SUMMARY.md:189
msgid "Library"
msgstr "Bibliothek"
-#: src/SUMMARY.md:213
+#: src/SUMMARY.md:190
msgid "AIDL"
msgstr "AIDL"
-#: src/SUMMARY.md:214
+#: src/SUMMARY.md:191
msgid "Interface"
msgstr "Schnittstelle"
-#: src/SUMMARY.md:215
+#: src/SUMMARY.md:192
msgid "Implementation"
msgstr "Implementierung"
-#: src/SUMMARY.md:216
+#: src/SUMMARY.md:193
msgid "Server"
msgstr "Server"
-#: src/SUMMARY.md:217
+#: src/SUMMARY.md:194
msgid "Deploy"
msgstr "Einsetzen"
-#: src/SUMMARY.md:218
+#: src/SUMMARY.md:195
msgid "Client"
msgstr "Klient"
-#: src/SUMMARY.md:219
+#: src/SUMMARY.md:196
msgid "Changing API"
msgstr "API verändern"
-#: src/SUMMARY.md:220 src/SUMMARY.md:288
+#: src/SUMMARY.md:197 src/SUMMARY.md:240
msgid "Logging"
msgstr "Protokollierung"
-#: src/SUMMARY.md:221
+#: src/SUMMARY.md:198
msgid "Interoperability"
msgstr "Interoperabilität"
-#: src/SUMMARY.md:222
+#: src/SUMMARY.md:199
msgid "With C"
msgstr "Mit C"
-#: src/SUMMARY.md:223
+#: src/SUMMARY.md:200
msgid "Calling C with Bindgen"
msgstr "Aufruf von C-Funktionen mit Bindgen"
-#: src/SUMMARY.md:224
+#: src/SUMMARY.md:201
msgid "Calling Rust from C"
msgstr "Aufruf von Rust aus C"
-#: src/SUMMARY.md:225
+#: src/SUMMARY.md:202
msgid "With C++"
msgstr "Mit C++"
-#: src/SUMMARY.md:226
+#: src/SUMMARY.md:203
msgid "With Java"
msgstr "Mit Java"
-#: src/SUMMARY.md:229
-msgid "Day 4: Afternoon (Async)"
-msgstr "Tag 4: Nachmittags (Async)"
-
-#: src/SUMMARY.md:233
-msgid "Async Basics"
-msgstr "Async Grundlagen"
-
-#: src/SUMMARY.md:234
-msgid "async/await"
-msgstr ""
-
-#: src/SUMMARY.md:235
-msgid "Futures"
-msgstr ""
-
-#: src/SUMMARY.md:236
-msgid "Runtimes"
-msgstr "Laufzeiten"
-
-#: src/SUMMARY.md:237
-msgid "Tokio"
-msgstr ""
-
-#: src/SUMMARY.md:238
-msgid "Tasks"
-msgstr "Aufgaben"
-
-#: src/SUMMARY.md:239
-msgid "Async Channels"
-msgstr "Async Kanäle"
-
-#: src/SUMMARY.md:241
-msgid "Join"
-msgstr ""
-
-#: src/SUMMARY.md:242
-msgid "Select"
-msgstr ""
-
-#: src/SUMMARY.md:243
-msgid "Pitfalls"
-msgstr "Tücken"
-
-#: src/SUMMARY.md:244
-msgid "Blocking the Executor"
-msgstr "Blockieren des Ausführers"
-
-#: src/SUMMARY.md:245
-msgid "Pin"
-msgstr ""
-
-#: src/SUMMARY.md:246
-msgid "Async Traits"
-msgstr "Async Merkmale"
-
-#: src/SUMMARY.md:249
-msgid "Final Words"
-msgstr "Letzte Worte"
-
-#: src/SUMMARY.md:251
-msgid "Thanks!"
-msgstr "Danke!"
-
-#: src/SUMMARY.md:252
-msgid "Other Resources"
-msgstr "Andere Ressourcen"
-
-#: src/SUMMARY.md:253
-msgid "Credits"
-msgstr "Würdigungen"
-
-#: src/SUMMARY.md:257
-msgid "Bare Metal Rust: Morning"
+#: src/SUMMARY.md:207
+msgid "Bare Metal: Morning"
msgstr "Hardwarenahes Rust: Morgens"
-#: src/SUMMARY.md:260
+#: src/SUMMARY.md:212
msgid "no_std"
msgstr ""
-#: src/SUMMARY.md:261
+#: src/SUMMARY.md:213
msgid "A Minimal Example"
msgstr "Kleines Beispiel"
-#: src/SUMMARY.md:262
+#: src/SUMMARY.md:214
msgid "alloc"
msgstr ""
-#: src/SUMMARY.md:263
+#: src/SUMMARY.md:215
msgid "Microcontrollers"
msgstr "Mikrokontroller"
-#: src/SUMMARY.md:264
+#: src/SUMMARY.md:216
msgid "Raw MMIO"
msgstr "MMIO"
-#: src/SUMMARY.md:265
+#: src/SUMMARY.md:217
msgid "PACs"
msgstr ""
-#: src/SUMMARY.md:266
+#: src/SUMMARY.md:218
msgid "HAL Crates"
msgstr "HAL Kisten"
-#: src/SUMMARY.md:267
+#: src/SUMMARY.md:219
msgid "Board Support Crates"
msgstr "Helfer Kisten"
-#: src/SUMMARY.md:268
+#: src/SUMMARY.md:220
msgid "The Type State Pattern"
msgstr "Das Typzustandsmuster"
-#: src/SUMMARY.md:269
+#: src/SUMMARY.md:221
msgid "embedded-hal"
msgstr ""
-#: src/SUMMARY.md:270
+#: src/SUMMARY.md:222
msgid "probe-rs, cargo-embed"
msgstr ""
-#: src/SUMMARY.md:271
+#: src/SUMMARY.md:223
msgid "Debugging"
msgstr "Debugging"
-#: src/SUMMARY.md:272 src/SUMMARY.md:290
+#: src/SUMMARY.md:224 src/SUMMARY.md:242
msgid "Other Projects"
msgstr "Andere Ressourcen"
-#: src/SUMMARY.md:274
+#: src/SUMMARY.md:226
msgid "Compass"
msgstr "Kompass"
-#: src/SUMMARY.md:276
-msgid "Bare Metal Rust: Afternoon"
-msgstr "Hardwarenahes Rust: Nachmittags"
+#: src/SUMMARY.md:228
+msgid "Bare Metal: Afternoon"
+msgstr "Bare-Metal: Nachmittags"
-#: src/SUMMARY.md:278
+#: src/SUMMARY.md:230
msgid "Application Processors"
msgstr "Applikationsprozessoren"
-#: src/SUMMARY.md:279
+#: src/SUMMARY.md:231
msgid "Inline Assembly"
msgstr ""
-#: src/SUMMARY.md:280
+#: src/SUMMARY.md:232
msgid "MMIO"
msgstr ""
-#: src/SUMMARY.md:281
+#: src/SUMMARY.md:233
msgid "Let's Write a UART Driver"
msgstr "Schreiben eines UART Treibers"
-#: src/SUMMARY.md:282
+#: src/SUMMARY.md:234
msgid "More Traits"
msgstr "Noch mehr Merkmale"
-#: src/SUMMARY.md:283
+#: src/SUMMARY.md:235
msgid "A Better UART Driver"
msgstr "Ein besserer UART Treiber"
-#: src/SUMMARY.md:284
+#: src/SUMMARY.md:236
msgid "Bitflags"
msgstr ""
-#: src/SUMMARY.md:285
+#: src/SUMMARY.md:237
msgid "Multiple Registers"
msgstr "Mehrere Register"
-#: src/SUMMARY.md:286
+#: src/SUMMARY.md:238
msgid "Driver"
msgstr "Treiber"
-#: src/SUMMARY.md:287 src/SUMMARY.md:289
+#: src/SUMMARY.md:239 src/SUMMARY.md:241
msgid "Using It"
msgstr "Benutzung"
-#: src/SUMMARY.md:291
+#: src/SUMMARY.md:243
msgid "Useful Crates"
msgstr "Nützliche Kisten"
-#: src/SUMMARY.md:292
+#: src/SUMMARY.md:244
msgid "zerocopy"
msgstr ""
-#: src/SUMMARY.md:293
+#: src/SUMMARY.md:245
msgid "aarch64-paging"
msgstr ""
-#: src/SUMMARY.md:294
+#: src/SUMMARY.md:246
msgid "buddy_system_allocator"
msgstr ""
-#: src/SUMMARY.md:295
+#: src/SUMMARY.md:247
msgid "tinyvec"
msgstr ""
-#: src/SUMMARY.md:296
+#: src/SUMMARY.md:248
msgid "spin"
msgstr ""
-#: src/SUMMARY.md:298
+#: src/SUMMARY.md:250
msgid "vmbase"
msgstr ""
-#: src/SUMMARY.md:300
+#: src/SUMMARY.md:252
msgid "RTC Driver"
msgstr "RTC Treiber"
+#: src/SUMMARY.md:255
+msgid "Concurrency: Morning"
+msgstr "Nebenläufigkeit: Morgens"
+
+#: src/SUMMARY.md:260
+msgid "Threads"
+msgstr "Ausführungsstrang"
+
+#: src/SUMMARY.md:261
+msgid "Scoped Threads"
+msgstr "Ausführungsstrang mit Sichtbarkeitsbereich"
+
+#: src/SUMMARY.md:262
+msgid "Channels"
+msgstr "Kanäle"
+
+#: src/SUMMARY.md:263
+msgid "Unbounded Channels"
+msgstr "Unbegrenzte Kanäle"
+
+#: src/SUMMARY.md:264
+msgid "Bounded Channels"
+msgstr "Unbeschränkte Kanäle"
+
+#: src/SUMMARY.md:265
+msgid "Send and Sync"
+msgstr "Send und Sync"
+
+#: src/SUMMARY.md:265
+msgid "Send"
+msgstr "Send"
+
+#: src/SUMMARY.md:265
+msgid "Sync"
+msgstr "Sync"
+
+#: src/SUMMARY.md:268
+msgid "Examples"
+msgstr "Beispiele"
+
+#: src/SUMMARY.md:269
+msgid "Shared State"
+msgstr "Geteilter Zustand"
+
+#: src/SUMMARY.md:270
+msgid "Arc"
+msgstr "Arc"
+
+#: src/SUMMARY.md:271
+msgid "Mutex"
+msgstr "Mutex"
+
+#: src/SUMMARY.md:274 src/SUMMARY.md:294
+msgid "Dining Philosophers"
+msgstr "Philosophenproblem"
+
+#: src/SUMMARY.md:275
+msgid "Multi-threaded Link Checker"
+msgstr "Link Überprüfung mit mehreren Ausführungssträngen"
+
+#: src/SUMMARY.md:277
+msgid "Concurrency: Afternoon"
+msgstr "Nebenläufigkeit: Nachmittags"
+
+#: src/SUMMARY.md:279
+msgid "Async Basics"
+msgstr "Async Grundlagen"
+
+#: src/SUMMARY.md:280
+msgid "async/await"
+msgstr ""
+
+#: src/SUMMARY.md:281
+msgid "Futures"
+msgstr ""
+
+#: src/SUMMARY.md:282
+msgid "Runtimes"
+msgstr "Laufzeiten"
+
+#: src/SUMMARY.md:283
+msgid "Tokio"
+msgstr ""
+
+#: src/SUMMARY.md:284
+msgid "Tasks"
+msgstr "Aufgaben"
+
+#: src/SUMMARY.md:285
+msgid "Async Channels"
+msgstr "Async Kanäle"
+
+#: src/SUMMARY.md:287
+msgid "Join"
+msgstr ""
+
+#: src/SUMMARY.md:288
+msgid "Select"
+msgstr ""
+
+#: src/SUMMARY.md:289
+msgid "Pitfalls"
+msgstr "Tücken"
+
+#: src/SUMMARY.md:290
+msgid "Blocking the Executor"
+msgstr "Blockieren des Ausführers"
+
+#: src/SUMMARY.md:291
+msgid "Pin"
+msgstr ""
+
+#: src/SUMMARY.md:292
+msgid "Async Traits"
+msgstr "Async Merkmale"
+
+#: src/SUMMARY.md:295
+msgid "Broadcast Chat Application"
+msgstr ""
+
+#: src/SUMMARY.md:298
+msgid "Final Words"
+msgstr "Letzte Worte"
+
+#: src/SUMMARY.md:302
+msgid "Thanks!"
+msgstr "Danke!"
+
+#: src/SUMMARY.md:303
+msgid "Other Resources"
+msgstr "Andere Ressourcen"
+
#: src/SUMMARY.md:304
+msgid "Credits"
+msgstr "Würdigungen"
+
+#: src/SUMMARY.md:307
msgid "Solutions"
msgstr "Lösungen"
-#: src/SUMMARY.md:309
+#: src/SUMMARY.md:312
msgid "Day 1 Morning"
msgstr "Tag 1 Morgens"
-#: src/SUMMARY.md:310
+#: src/SUMMARY.md:313
msgid "Day 1 Afternoon"
msgstr "Tag 1 Nachmittags"
-#: src/SUMMARY.md:311
+#: src/SUMMARY.md:314
msgid "Day 2 Morning"
msgstr "Tag 2 Morgens"
-#: src/SUMMARY.md:312
+#: src/SUMMARY.md:315
msgid "Day 2 Afternoon"
msgstr "Tag 2 Nachmittags"
-#: src/SUMMARY.md:313
+#: src/SUMMARY.md:316
msgid "Day 3 Morning"
msgstr "Tag 3 Morgens"
-#: src/SUMMARY.md:314
+#: src/SUMMARY.md:317
msgid "Day 3 Afternoon"
msgstr "Tag 3 Nachmittags"
-#: src/SUMMARY.md:315
-msgid "Day 4 Morning"
-msgstr "Tag 4 Morgens"
-
-#: src/SUMMARY.md:316
+#: src/SUMMARY.md:318
msgid "Bare Metal Rust Morning"
msgstr "Hardwarenahes Rust: Morgens"
-#: src/SUMMARY.md:317
+#: src/SUMMARY.md:319
msgid "Bare Metal Rust Afternoon"
msgstr "Hadwarenahes Rust: Nachmittags"
+#: src/SUMMARY.md:320
+msgid "Concurrency Morning"
+msgstr "Nebenläufigkeit Morgens"
+
+#: src/SUMMARY.md:321
+msgid "Concurrency Afternoon"
+msgstr "Nebenläufigkeit Nachmittags"
+
#: src/welcome.md:1
msgid "# Welcome to Comprehensive Rust 🦀"
msgstr "# Willkommen bei Comprehensive Rust 🦀"
@@ -998,7 +999,7 @@ msgstr "# Willkommen bei Comprehensive Rust 🦀"
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)"
+"yml?query=branch%3Amain)"
msgstr ""
#: src/welcome.md:3
@@ -1009,7 +1010,7 @@ msgstr ""
msgid ""
"[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/"
"build.yml?style=flat-square)](https://github.com/google/comprehensive-rust/actions/workflows/build."
-"yml)\n"
+"yml?query=branch%3Amain)\n"
"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?"
"style=flat-square)](https://github.com/google/comprehensive-rust/graphs/contributors)"
msgstr ""
@@ -1038,11 +1039,11 @@ msgstr ""
#: src/welcome.md:7
msgid ""
-"This is a four day Rust course developed by the Android team. The course covers\n"
+"This is a three day Rust course developed by the Android team. The course covers\n"
"the full spectrum of Rust, from basic syntax to advanced topics like generics\n"
"and error handling. It also includes Android-specific content on the last day."
msgstr ""
-"Dies ist ein viertägiger Rust-Kurs, der vom Android-Team entwickelt wurde. Der Kurs umfasst\n"
+"Dies ist ein dreitägiger Rust-Kurs, der vom Android-Team entwickelt wurde. Der Kurs umfasst\n"
"das gesamte Spektrum von Rust, von grundlegender Syntax bis hin zu fortgeschrittenen Themen wie "
"generischen Methoden und Datentypen\n"
"sowie Fehlerbehandlung. Am letzten Tag werden auch Android-spezifische Inhalte behandelt."
@@ -1067,34 +1068,40 @@ msgstr ""
"* Dir gängige Rust-Idiome zu zeigen."
#: src/welcome.md:18
-msgid "On Day 4, we will cover Android-specific things such as:"
-msgstr "An Tag 4 behandeln wir Android-spezifische Dinge wie:"
-
-#: src/welcome.md:20
msgid ""
-"* Building Android components in Rust.\n"
-"* AIDL servers and clients.\n"
-"* Interoperability with C, C++, and Java."
+"The first three days show you the fundamentals of Rust. Following this, you're\n"
+"invited to dive into one or more specialized topics:"
msgstr ""
-"* Erstellen von Android-Komponenten in Rust.\n"
-"* AIDL-Server und -Klienten.\n"
-"* Interoperabilität mit C, C++ und Java."
+"In den ersten drei Tagen zeigen wir die Grundlagen von Rust. Danach, laden wir dich ein\n"
+"sich mit einem oder mehreren Spezialthemen zu befassen:"
-#: src/welcome.md:24
+#: src/welcome.md:21
msgid ""
-"It is important to note that this course does not cover Android **application** \n"
-"development in Rust, and that the Android-specific parts are specifically about\n"
-"writing code for Android itself, the operating system. "
+"* [Android](android.md): a half-day course on using Rust for Android platform\n"
+" development (AOSP). This includes interoperability with C, C++, and Java.\n"
+"* [Bare-metal](bare-metal.md): a full day class on using Rust for bare-metal\n"
+" (embedded) development. Both microcontrollers and application processors are\n"
+" covered.\n"
+"* [Concurrency](concurrency.md): a full day class on concurrency in Rust. We\n"
+" cover both classical concurrency (preemptively scheduling using threads and\n"
+" mutexes) and async/await concurrency (cooperative multitasking using\n"
+" futures)."
msgstr ""
-"Es ist wichtig zu beachten, dass dieser Kurs keine Android **Anwendungsentwicklung** abdeckt \n"
-"und dass es bei den Android-spezifischen Teilen um das \n"
-"Schreiben von Code für das Betriebssystem Android geht. "
+"* [Android](android.md): ein halbtägiger Kurs zur Verwendung von Rust für die Android-Plattform\n"
+" Entwicklung (AOSP). Dazu gehört die Interoperabilität mit C, C++ und Java.\n"
+"* [Bare-Metal](bare-metal.md): ein ganztägiger Kurs über die Verwendung von Rust für Bare-Metal\n"
+" (eingebettete) Entwicklung. Sowohl Mikrocontroller als auch Anwendungsprozessoren\n"
+" bedeckt.\n"
+"* [Concurrency](concurrency.md): ein ganztägiger Kurs zum Thema Parallelität in Rust. Wir\n"
+" decken sowohl die klassische Parallelität ab (präventive Planung mithilfe von Threads als auch\n"
+" Mutexe) und Async/Await-Parallelität (kooperatives Multitasking mit\n"
+" Futures)."
-#: src/welcome.md:28
+#: src/welcome.md:32
msgid "## Non-Goals"
msgstr "## Nicht-Ziele"
-#: src/welcome.md:30
+#: src/welcome.md:34
msgid ""
"Rust is a large language and we won't be able to cover all of it in a few days.\n"
"Some non-goals of this course are:"
@@ -1103,23 +1110,15 @@ msgstr ""
"können.\n"
"Einige Nicht-Ziele dieses Kurses sind:"
-#: src/welcome.md:33
+#: src/welcome.md:37
msgid ""
-"* Learn how to use async Rust --- we'll only mention async Rust when\n"
-" covering traditional concurrency primitives. Please see [Asynchronous\n"
-" Programming in Rust](https://rust-lang.github.io/async-book/) instead for\n"
-" details on this topic.\n"
"* Learn how to develop macros, please see [Chapter 19.5 in the Rust\n"
" Book](https://doc.rust-lang.org/book/ch19-06-macros.html) and [Rust by\n"
" Example](https://doc.rust-lang.org/rust-by-example/macros.html) instead."
msgstr ""
-"* Lernen, wie man asynchrones Rust verwendet – wir erwähnen asynchrones Rust nur dann, wenn\n"
-" wir traditionelle Nebenläufigkeitsprimitive abdecken. Siehe [Asynchronous\n"
-" Programmierung in Rust](https://rust-lang.github.io/async-book/) für\n"
-" Details zu diesem Thema.\n"
-"* Lernen, wie man Makros entwickelt, siehe [Kapitel 19.5 im Rust\n"
-" Buch](https://rust-lang-de.github.io/rustbook-de/ch19-06-macros.html) und [Rust by\n"
-" Example](https://doc.rust-lang.org/rust-by-example/macros.html)."
+"* Erfahren Sie, wie Sie Makros entwickeln, siehe [Kapitel 19.5 im Rust\n"
+" Buch](https://doc.rust-lang.org/book/ch19-06-macros.html) und [Rust von\n"
+" Beispiel](https://doc.rust-lang.org/rust-by-example/macros.html)."
#: src/welcome.md:41
msgid "## Assumptions"
@@ -1147,50 +1146,44 @@ msgstr ""
#: src/cargo/running-locally.md:68 src/welcome-day-1.md:14 src/welcome-day-1/what-is-rust.md:19
#: src/hello-world.md:20 src/hello-world/small-example.md:21 src/why-rust.md:9
#: src/why-rust/compile-time.md:14 src/why-rust/runtime.md:8 src/why-rust/modern.md:19
-#: src/basic-syntax/compound-types.md:28 src/basic-syntax/slices.md:18
+#: src/basic-syntax/scalar-types.md:19 src/basic-syntax/compound-types.md:28
+#: src/basic-syntax/references.md:21 src/basic-syntax/slices.md:18
#: src/basic-syntax/string-slices.md:25 src/basic-syntax/functions.md:33
-#: src/basic-syntax/rustdoc.md:22 src/basic-syntax/functions-interlude.md:25
-#: src/exercises/day-1/morning.md:9 src/exercises/day-1/for-loops.md:90
-#: src/basic-syntax/variables.md:15 src/basic-syntax/type-inference.md:24
-#: src/basic-syntax/static-and-const.md:46 src/basic-syntax/scopes-shadowing.md:23
-#: src/memory-management/stack.md:26 src/memory-management/rust.md:12
-#: src/ownership/move-semantics.md:20 src/ownership/moves-function-calls.md:18
-#: src/ownership/copy-clone.md:33 src/ownership/borrowing.md:25
-#: src/ownership/shared-unique-borrows.md:23 src/ownership/lifetimes-function-calls.md:27
-#: src/ownership/lifetimes-data-structures.md:23 src/exercises/day-1/afternoon.md:9
-#: src/exercises/day-1/book-library.md:102 src/structs/tuple-structs.md:35
-#: src/structs/field-shorthand.md:25 src/enums.md:31 src/enums/variant-payloads.md:33
-#: src/enums/sizes.md:27 src/methods.md:28 src/methods/receiver.md:23 src/methods/example.md:44
-#: src/pattern-matching.md:23 src/pattern-matching/destructuring-enums.md:33
-#: src/pattern-matching/destructuring-structs.md:21 src/pattern-matching/destructuring-arrays.md:19
-#: src/pattern-matching/match-guards.md:20 src/exercises/day-2/morning.md:9
-#: src/exercises/day-2/points-polygons.md:115 src/control-flow/blocks.md:40
-#: src/control-flow/if-expressions.md:29 src/control-flow/if-let-expressions.md:19
-#: src/control-flow/while-let-expressions.md:25 src/control-flow/for-expressions.md:22
-#: src/control-flow/loop-expressions.md:23 src/control-flow/match-expressions.md:25 src/std.md:23
-#: src/std/option-result.md:16 src/std/string.md:28 src/std/vec.md:35 src/std/hashmap.md:36
-#: src/std/box.md:32 src/std/box-recursive.md:31 src/std/rc.md:29 src/modules.md:26
-#: src/modules/visibility.md:37 src/modules/filesystem.md:38 src/exercises/day-2/afternoon.md:5
-#: src/generics/data-types.md:19 src/generics/methods.md:23 src/traits/trait-objects.md:70
-#: src/traits/default-methods.md:30 src/traits/trait-bounds.md:33 src/traits/impl-trait.md:21
-#: src/traits/iterator.md:30 src/traits/from-iterator.md:15 src/traits/from-into.md:27
-#: src/traits/drop.md:32 src/traits/default.md:38 src/traits/operators.md:24
-#: src/traits/closures.md:23 src/exercises/day-3/morning.md:5 src/error-handling/result.md:25
-#: src/error-handling/try-operator.md:48 src/error-handling/converting-error-types-example.md:48
+#: src/basic-syntax/rustdoc.md:22 src/basic-syntax/methods.md:32
+#: src/basic-syntax/functions-interlude.md:25 src/exercises/day-1/morning.md:9
+#: src/exercises/day-1/for-loops.md:90 src/basic-syntax/variables.md:15
+#: src/basic-syntax/type-inference.md:24 src/basic-syntax/static-and-const.md:46
+#: src/basic-syntax/scopes-shadowing.md:23 src/memory-management/stack.md:26
+#: src/memory-management/rust.md:12 src/ownership/move-semantics.md:20
+#: src/ownership/moves-function-calls.md:18 src/ownership/copy-clone.md:33
+#: src/ownership/borrowing.md:25 src/ownership/shared-unique-borrows.md:23
+#: src/ownership/lifetimes-function-calls.md:27 src/ownership/lifetimes-data-structures.md:23
+#: src/exercises/day-1/afternoon.md:9 src/exercises/day-1/book-library.md:100 src/structs.md:29
+#: src/structs/tuple-structs.md:35 src/structs/field-shorthand.md:25 src/enums.md:32
+#: src/enums/variant-payloads.md:33 src/enums/sizes.md:27 src/methods.md:28
+#: src/methods/receiver.md:22 src/methods/example.md:44 src/pattern-matching.md:23
+#: src/pattern-matching/destructuring-enums.md:33 src/pattern-matching/destructuring-structs.md:21
+#: src/pattern-matching/destructuring-arrays.md:19 src/pattern-matching/match-guards.md:20
+#: src/exercises/day-2/morning.md:9 src/exercises/day-2/points-polygons.md:115
+#: src/control-flow/blocks.md:40 src/control-flow/if-expressions.md:33
+#: src/control-flow/if-let-expressions.md:21 src/control-flow/while-let-expressions.md:24
+#: src/control-flow/for-expressions.md:23 src/control-flow/loop-expressions.md:25
+#: src/control-flow/match-expressions.md:26 src/std.md:23 src/std/option-result.md:16
+#: src/std/string.md:28 src/std/vec.md:35 src/std/hashmap.md:36 src/std/box.md:32
+#: src/std/box-recursive.md:31 src/std/rc.md:29 src/modules.md:26 src/modules/visibility.md:37
+#: src/modules/filesystem.md:42 src/exercises/day-2/afternoon.md:5 src/generics/data-types.md:19
+#: src/generics/methods.md:23 src/traits/trait-objects.md:70 src/traits/default-methods.md:30
+#: src/traits/trait-bounds.md:33 src/traits/impl-trait.md:21 src/traits/iterator.md:30
+#: src/traits/from-iterator.md:15 src/traits/from-into.md:27 src/traits/drop.md:32
+#: src/traits/default.md:38 src/traits/operators.md:24 src/traits/closures.md:23
+#: src/exercises/day-3/morning.md:5 src/error-handling/result.md:25
+#: src/error-handling/try-operator.md:46 src/error-handling/converting-error-types-example.md:48
#: src/error-handling/deriving-error-enums.md:37 src/error-handling/dynamic-errors.md:34
-#: src/error-handling/error-contexts.md:33 src/unsafe.md:26 src/unsafe/raw-pointers.md:24
+#: src/error-handling/error-contexts.md:33 src/unsafe.md:26 src/unsafe/raw-pointers.md:25
#: src/unsafe/mutable-static-variables.md:30 src/unsafe/unions.md:19
#: src/unsafe/writing-unsafe-functions.md:31 src/unsafe/extern-functions.md:19
-#: src/unsafe/unsafe-traits.md:28 src/exercises/day-3/afternoon.md:5 src/welcome-day-4.md:6
-#: src/concurrency/threads.md:28 src/concurrency/scoped-threads.md:35 src/concurrency/channels.md:25
-#: src/concurrency/shared_state/arc.md:27 src/concurrency/shared_state/mutex.md:29
-#: src/concurrency/shared_state/example.md:21 src/concurrency/send-sync.md:18
-#: src/concurrency/send-sync/sync.md:12 src/exercises/day-4/morning.md:10
-#: src/android/interoperability/with-c/rust.md:81 src/exercises/day-4/android.md:10
-#: src/async/async-await.md:23 src/async/futures.md:30 src/async/runtimes.md:18
-#: src/async/runtimes/tokio.md:31 src/async/tasks.md:51 src/async/channels.md:33
-#: src/async/control-flow/join.md:34 src/async/control-flow/select.md:59
-#: src/async/pitfalls/blocking-executor.md:27 src/async/pitfalls/pin.md:66
+#: src/unsafe/unsafe-traits.md:28 src/exercises/day-3/afternoon.md:5
+#: src/android/interoperability/with-c/rust.md:81 src/exercises/android/morning.md:10
#: src/bare-metal/minimal.md:15 src/bare-metal/alloc.md:37 src/bare-metal/microcontrollers.md:23
#: src/bare-metal/microcontrollers/mmio.md:62 src/bare-metal/microcontrollers/pacs.md:47
#: src/bare-metal/microcontrollers/hals.md:37 src/bare-metal/microcontrollers/board-support.md:26
@@ -1202,12 +1195,22 @@ msgstr ""
#: src/bare-metal/aps/uart.md:53 src/bare-metal/aps/uart/traits.md:22
#: src/bare-metal/aps/better-uart.md:24 src/bare-metal/aps/better-uart/bitflags.md:35
#: src/bare-metal/aps/better-uart/registers.md:39 src/bare-metal/aps/better-uart/driver.md:62
-#: src/bare-metal/aps/better-uart/using.md:48 src/bare-metal/aps/logging.md:48
-#: src/bare-metal/aps/logging/using.md:43 src/bare-metal/useful-crates/zerocopy.md:43
+#: src/bare-metal/aps/better-uart/using.md:49 src/bare-metal/aps/logging.md:48
+#: src/bare-metal/aps/logging/using.md:44 src/bare-metal/useful-crates/zerocopy.md:43
#: src/bare-metal/useful-crates/aarch64-paging.md:26
#: src/bare-metal/useful-crates/buddy_system_allocator.md:24
#: src/bare-metal/useful-crates/tinyvec.md:21 src/bare-metal/useful-crates/spin.md:21
#: src/bare-metal/android/vmbase.md:19 src/exercises/bare-metal/afternoon.md:5
+#: src/concurrency/threads.md:28 src/concurrency/scoped-threads.md:35 src/concurrency/channels.md:25
+#: src/concurrency/send-sync.md:18 src/concurrency/send-sync/send.md:11
+#: src/concurrency/send-sync/sync.md:12 src/concurrency/shared_state/arc.md:27
+#: src/concurrency/shared_state/mutex.md:29 src/concurrency/shared_state/example.md:21
+#: src/exercises/concurrency/morning.md:10 src/async/async-await.md:23 src/async/futures.md:30
+#: src/async/runtimes.md:18 src/async/runtimes/tokio.md:31 src/async/tasks.md:51
+#: src/async/channels.md:33 src/async/control-flow/join.md:34 src/async/control-flow/select.md:59
+#: src/async/pitfalls/blocking-executor.md:27 src/async/pitfalls/pin.md:66
+#: src/exercises/concurrency/afternoon.md:11
+#: src/exercises/concurrency/dining-philosophers-async.md:75
msgid ""
msgstr ""
@@ -1226,9 +1229,11 @@ msgstr ""
#: src/cargo/running-locally.md:74 src/welcome-day-1.md:42 src/welcome-day-1/what-is-rust.md:29
#: src/hello-world.md:40 src/hello-world/small-example.md:44 src/why-rust.md:24
#: src/why-rust/compile-time.md:35 src/why-rust/runtime.md:22 src/why-rust/modern.md:66
-#: src/basic-syntax/compound-types.md:62 src/basic-syntax/references.md:28
-#: src/basic-syntax/slices.md:36 src/basic-syntax/string-slices.md:44
-#: src/basic-syntax/functions.md:54 src/basic-syntax/rustdoc.md:33 src/exercises/day-1/morning.md:28
+#: src/basic-syntax/scalar-types.md:43 src/basic-syntax/compound-types.md:62
+#: src/basic-syntax/references.md:29 src/basic-syntax/slices.md:36
+#: src/basic-syntax/string-slices.md:44 src/basic-syntax/functions.md:41
+#: src/basic-syntax/rustdoc.md:33 src/basic-syntax/methods.md:45
+#: src/basic-syntax/functions-interlude.md:30 src/exercises/day-1/morning.md:28
#: src/exercises/day-1/for-loops.md:95 src/basic-syntax/variables.md:20
#: src/basic-syntax/type-inference.md:48 src/basic-syntax/static-and-const.md:52
#: src/basic-syntax/scopes-shadowing.md:39 src/memory-management/stack.md:49
@@ -1236,44 +1241,36 @@ msgstr ""
#: src/ownership/moves-function-calls.md:26 src/ownership/copy-clone.md:51
#: src/ownership/borrowing.md:51 src/ownership/shared-unique-borrows.md:29
#: src/ownership/lifetimes-function-calls.md:60 src/ownership/lifetimes-data-structures.md:30
-#: src/exercises/day-1/afternoon.md:15 src/exercises/day-1/book-library.md:106 src/structs.md:41
-#: src/structs/tuple-structs.md:43 src/structs/field-shorthand.md:72 src/enums.md:41
+#: src/exercises/day-1/afternoon.md:15 src/exercises/day-1/book-library.md:104 src/structs.md:42
+#: src/structs/tuple-structs.md:43 src/structs/field-shorthand.md:72 src/enums.md:42
#: src/enums/variant-payloads.md:45 src/enums/sizes.md:155 src/methods.md:41
-#: src/methods/receiver.md:29 src/methods/example.md:53 src/pattern-matching.md:35
-#: src/pattern-matching/destructuring-enums.md:39 src/pattern-matching/destructuring-structs.md:25
+#: src/methods/receiver.md:28 src/methods/example.md:53 src/pattern-matching.md:35
+#: src/pattern-matching/destructuring-enums.md:39 src/pattern-matching/destructuring-structs.md:29
#: src/pattern-matching/destructuring-arrays.md:46 src/pattern-matching/match-guards.md:28
#: src/exercises/day-2/morning.md:15 src/exercises/day-2/points-polygons.md:125
-#: src/control-flow/blocks.md:46 src/control-flow/if-expressions.md:33
-#: src/control-flow/if-let-expressions.md:39 src/control-flow/while-let-expressions.md:30
-#: src/control-flow/for-expressions.md:29 src/control-flow/loop-expressions.md:27
-#: src/control-flow/match-expressions.md:32 src/std.md:31 src/std/option-result.md:25
-#: src/std/string.md:40 src/std/vec.md:49 src/std/hashmap.md:66 src/std/box.md:39
+#: src/control-flow/blocks.md:46 src/control-flow/if-expressions.md:37
+#: src/control-flow/if-let-expressions.md:41 src/control-flow/while-let-expressions.md:29
+#: src/control-flow/for-expressions.md:30 src/control-flow/loop-expressions.md:32
+#: src/control-flow/match-expressions.md:33 src/std.md:31 src/std/option-result.md:25
+#: src/std/string.md:42 src/std/vec.md:49 src/std/hashmap.md:66 src/std/box.md:39
#: src/std/box-recursive.md:41 src/std/rc.md:69 src/modules.md:32 src/modules/visibility.md:48
-#: src/modules/filesystem.md:67 src/exercises/day-2/afternoon.md:11 src/generics/data-types.md:25
-#: src/generics/methods.md:31 src/traits/trait-objects.md:83 src/traits/default-methods.md:41
+#: src/modules/filesystem.md:71 src/exercises/day-2/afternoon.md:11 src/generics/data-types.md:25
+#: src/generics/methods.md:31 src/traits/trait-objects.md:83 src/traits/default-methods.md:60
#: src/traits/trait-bounds.md:50 src/traits/impl-trait.md:44 src/traits/iterator.md:42
#: src/traits/from-iterator.md:26 src/traits/from-into.md:33 src/traits/drop.md:42
-#: src/traits/default.md:47 src/traits/operators.md:38 src/traits/closures.md:38
+#: src/traits/default.md:47 src/traits/operators.md:40 src/traits/closures.md:38
#: src/exercises/day-3/morning.md:11 src/error-handling/result.md:33
-#: src/error-handling/try-operator.md:55 src/error-handling/converting-error-types-example.md:60
+#: src/error-handling/try-operator.md:53 src/error-handling/converting-error-types-example.md:60
#: src/error-handling/deriving-error-enums.md:45 src/error-handling/dynamic-errors.md:41
-#: src/error-handling/error-contexts.md:42 src/unsafe.md:32 src/unsafe/raw-pointers.md:42
+#: src/error-handling/error-contexts.md:42 src/unsafe.md:32 src/unsafe/raw-pointers.md:43
#: src/unsafe/mutable-static-variables.md:35 src/unsafe/unions.md:28
#: src/unsafe/writing-unsafe-functions.md:38 src/unsafe/extern-functions.md:28
-#: src/unsafe/unsafe-traits.md:37 src/exercises/day-3/afternoon.md:11 src/welcome-day-4.md:11
-#: src/concurrency/threads.md:45 src/concurrency/scoped-threads.md:40 src/concurrency/channels.md:32
-#: src/concurrency/shared_state/arc.md:38 src/concurrency/shared_state/mutex.md:45
-#: src/concurrency/shared_state/example.md:56 src/concurrency/send-sync.md:23
-#: src/concurrency/send-sync/sync.md:18 src/exercises/day-4/morning.md:16
-#: src/android/interoperability/with-c/rust.md:86 src/exercises/day-4/android.md:15
-#: src/async/async-await.md:48 src/async/futures.md:45 src/async/runtimes.md:29
-#: src/async/runtimes/tokio.md:49 src/async/tasks.md:64 src/async/channels.md:49
-#: src/async/control-flow/join.md:50 src/async/control-flow/select.md:77
-#: src/async/pitfalls/blocking-executor.md:50 src/async/pitfalls/pin.md:112
-#: src/async/pitfalls/async-traits.md:65 src/bare-metal/no_std.md:65 src/bare-metal/minimal.md:26
-#: src/bare-metal/alloc.md:49 src/bare-metal/microcontrollers.md:29
-#: src/bare-metal/microcontrollers/mmio.md:72 src/bare-metal/microcontrollers/pacs.md:65
-#: src/bare-metal/microcontrollers/hals.md:49 src/bare-metal/microcontrollers/board-support.md:40
+#: src/unsafe/unsafe-traits.md:37 src/exercises/day-3/afternoon.md:11
+#: src/android/interoperability/with-c/rust.md:86 src/exercises/android/morning.md:15
+#: src/bare-metal/no_std.md:65 src/bare-metal/minimal.md:26 src/bare-metal/alloc.md:49
+#: src/bare-metal/microcontrollers.md:29 src/bare-metal/microcontrollers/mmio.md:72
+#: src/bare-metal/microcontrollers/pacs.md:65 src/bare-metal/microcontrollers/hals.md:49
+#: src/bare-metal/microcontrollers/board-support.md:40
#: src/bare-metal/microcontrollers/type-state.md:43
#: src/bare-metal/microcontrollers/embedded-hal.md:23 src/bare-metal/microcontrollers/probe-rs.md:29
#: src/bare-metal/microcontrollers/debugging.md:38
@@ -1281,12 +1278,22 @@ msgstr ""
#: src/bare-metal/aps.md:15 src/bare-metal/aps/inline-assembly.md:58 src/bare-metal/aps/mmio.md:17
#: src/bare-metal/aps/uart/traits.md:27 src/bare-metal/aps/better-uart.md:28
#: src/bare-metal/aps/better-uart/bitflags.md:40 src/bare-metal/aps/better-uart/registers.md:46
-#: src/bare-metal/aps/better-uart/driver.md:67 src/bare-metal/aps/better-uart/using.md:54
-#: src/bare-metal/aps/logging.md:52 src/bare-metal/aps/logging/using.md:48
+#: src/bare-metal/aps/better-uart/driver.md:67 src/bare-metal/aps/better-uart/using.md:55
+#: src/bare-metal/aps/logging.md:52 src/bare-metal/aps/logging/using.md:49
#: src/bare-metal/useful-crates/zerocopy.md:53 src/bare-metal/useful-crates/aarch64-paging.md:33
#: src/bare-metal/useful-crates/buddy_system_allocator.md:30
#: src/bare-metal/useful-crates/tinyvec.md:26 src/bare-metal/useful-crates/spin.md:30
#: src/bare-metal/android/vmbase.md:25 src/exercises/bare-metal/afternoon.md:11
+#: src/concurrency/threads.md:45 src/concurrency/scoped-threads.md:40 src/concurrency/channels.md:32
+#: src/concurrency/send-sync.md:23 src/concurrency/send-sync/send.md:16
+#: src/concurrency/send-sync/sync.md:18 src/concurrency/shared_state/arc.md:38
+#: src/concurrency/shared_state/mutex.md:45 src/concurrency/shared_state/example.md:56
+#: src/exercises/concurrency/morning.md:16 src/async/async-await.md:48 src/async/futures.md:45
+#: src/async/runtimes.md:29 src/async/runtimes/tokio.md:49 src/async/tasks.md:64
+#: src/async/channels.md:49 src/async/control-flow/join.md:50 src/async/control-flow/select.md:77
+#: src/async/pitfalls/blocking-executor.md:50 src/async/pitfalls/pin.md:112
+#: src/async/pitfalls/async-traits.md:63 src/exercises/concurrency/afternoon.md:17
+#: src/exercises/concurrency/dining-philosophers-async.md:79
msgid " "
msgstr " "
@@ -1295,7 +1302,6 @@ msgid "# Running the Course"
msgstr "# Ablauf des Kurses"
#: src/running-the-course.md:3 src/running-the-course/course-structure.md:3
-#: src/running-the-course/day-4.md:3
msgid "> This page is for the course instructor."
msgstr "> Diese Seite ist für den Kursleiter."
@@ -1312,6 +1318,7 @@ msgid "Before you run the course, you will want to:"
msgstr "Bevor du den Kurs vorstellst solltest du:"
#: src/running-the-course.md:10
+#, fuzzy
msgid ""
"1. Make yourself familiar with the course material. We've included speaker notes\n"
" to help highlight the key points (please help us by contributing more speaker\n"
@@ -1319,16 +1326,13 @@ msgid ""
" popup (click the link with a little arrow next to \"Speaker Notes\"). This way\n"
" you have a clean screen to present to the class.\n"
"\n"
-"1. Select your topic for the afternoon of the fourth day. This may be based on\n"
-" the audience you expect, or on your own expertise.\n"
-"\n"
-"1. Decide on the dates. Since the course is large, we recommend that you\n"
-" schedule the four days over two weeks. Course participants have said that\n"
+"1. Decide on the dates. Since the course takes at least three full days, we recommend that you\n"
+" schedule the days over two weeks. Course participants have said that\n"
" they find it helpful to have a gap in the course since it helps them process\n"
" all the information we give them.\n"
"\n"
"1. Find a room large enough for your in-person participants. We recommend a\n"
-" class size of 15-20 people. That's small enough that people are comfortable\n"
+" class size of 15-25 people. That's small enough that people are comfortable\n"
" asking questions --- it's also small enough that one instructor will have\n"
" time to answer the questions. Make sure the room has _desks_ for yourself and for the\n"
" students: you will all need to be able to sit and work with your laptops.\n"
@@ -1342,13 +1346,14 @@ msgid ""
" Using your laptop will also allow you to fix typos as you or the course\n"
" participants spot them.\n"
"\n"
-"1. Let people solve the exercises by themselves or in small groups. Make sure to\n"
+"1. Let people solve the exercises by themselves or in small groups.\n"
+" We typically spend 30-45 minutes on exercises in the morning and in the afternoon (including "
+"time to review the solutions).\n"
+" Make sure to\n"
" ask people if they're stuck or if there is anything you can help with. When\n"
" you see that several people have the same problem, call it out to the class\n"
" and offer a solution, e.g., by showing people where to find the relevant\n"
-" information in the standard library.\n"
-"\n"
-"1. Prepare anything you need to have available for the afternoon of day 4."
+" information in the standard library."
msgstr ""
"1. Setze dich mit dem Kursmaterial auseinander. Wir haben Sprechernotizen hinzugefügt, um "
"Schlüsselpunkte hervorzuheben (gerne kannst du uns helfen weitere Sprechernotizen hinzuzufügen!). "
@@ -1361,10 +1366,10 @@ msgstr ""
"in einem Zeitraum von zwei Wochen. Kursteilnehmer meinten, dass Pausen zwischen den Tagen sinnvoll "
"seien um die Menge an Informationen zu verarbeiten.\n"
"1. Finde einen Raum der groß genug für alle anwesenden Teilnehmer ist. Wir empfehlen eine "
-"Teilnehmeranzahl von 15 bis 20 Leuten. Das schafft ein gutes Klima, um Fragen zu stellen, und es ist "
-"möglich alle Fragen zeitnah zu beantworten. Stelle auch sicher, dass der Raum _Tische_ mit Stühlen "
-"für die Teilnehmer und dich hat. Ihr werdet nämlich eure Laptops benötigen. Um genau zu sein wirst "
-"du viel vorprogrammieren.\n"
+"Teilnehmeranzahl von 15 bis 20 Leuten. Das schafft ein gutes Klima, um Fragen zu stellen, und es "
+"ist möglich alle Fragen zeitnah zu beantworten. Stelle auch sicher, dass der Raum _Tische_ mit "
+"Stühlen für die Teilnehmer und dich hat. Ihr werdet nämlich eure Laptops benötigen. Um genau zu "
+"sein wirst du viel vorprogrammieren.\n"
"1. Sei schon etwas vor dem ersten Termin da, um alles vorzubereiten. Wir schlagen vor, dass du "
"`mdbook serve` direkt präsentierst (siehe [Installationsanleitung][3]). Somit entstehen keine "
"Störungen oder Unklarheiten bei dem Wechseln von Seiten und falls du oder die Teilnehmer "
@@ -1375,7 +1380,7 @@ msgstr ""
"könntest du zeigen wo man die relevante Information in der Standardbibliothek findet.\n"
"1. Bereite alles vor was du am Nachmittag des vierten Tages behandeln möchtest."
-#: src/running-the-course.md:46
+#: src/running-the-course.md:43
msgid ""
"That is all, good luck running the course! We hope it will be as much fun for\n"
"you as it has been for us!"
@@ -1383,7 +1388,7 @@ msgstr ""
"Das ist alles, viel Glück bei der Durchführung des Kurses! Wir hoffen, dass es dir \n"
"genauso viel Spaß machen wird wie uns!"
-#: src/running-the-course.md:49
+#: src/running-the-course.md:46
msgid ""
"Please [provide feedback][1] afterwards so that we can keep improving the\n"
"course. We would love to hear what worked well for you and what can be made\n"
@@ -1406,63 +1411,45 @@ msgstr "Der Kurs geht in schnellem Tempo voran und deckt viele Themen ab:"
msgid ""
"* Day 1: Basic Rust, ownership and the borrow checker.\n"
"* Day 2: Compound data types, pattern matching, the standard library.\n"
-"* Day 3: Traits and generics, error handling, testing, unsafe Rust.\n"
-"* Day 4: Concurrency in Rust and seeing Rust in action."
+"* Day 3: Traits and generics, error handling, testing, unsafe Rust."
msgstr ""
"* Tag 1: Rust Grundlagen, Eigentümerschaft (ownership) und der Ausleihenprüfer (borrow checker).\n"
"* Tag 2: Zusammengesetzte Datentypen, Musterabgleich, die Standardbibliothek.\n"
-"* Tag 3: Merkmale und Generika, Fehlerbehandlung, Testen, unsicheres Rust.\n"
-"* Tag 4: Parallelität in Rust und Rust in Aktion."
+"* Tag 3: Merkmale und Generika, Fehlerbehandlung, Testen, unsicheres Rust."
-#: src/running-the-course/course-structure.md:12
-msgid "## Format"
-msgstr "## Format"
+#: src/running-the-course/course-structure.md:11
+msgid "## Deep Dives"
+msgstr "## Vertiefungen"
-#: src/running-the-course/course-structure.md:14
+#: src/running-the-course/course-structure.md:13
msgid ""
-"The course is meant to be very interactive and we recommend letting the\n"
-"questions drive the exploration of Rust!"
+"In addition to the 3-day class on Rust Fundamentals, we cover some more\n"
+"specialized topics:"
msgstr ""
-"Der Kurs soll sehr interaktiv ablaufen und wir empfehlen, durch Fragen die \n"
-"Erkundung von Rust voranzutreiben!"
+"Zusätzlich zu den Rust-Grundlagen behandeln wir noch einiges mehr\n"
+"Spezialthemen nach Tag 3:"
-#: src/running-the-course/day-4.md:1
-msgid "# Day 4"
-msgstr "# Tag 4"
+#: src/running-the-course/course-structure.md:16
+msgid "### Android"
+msgstr "### Android"
-#: src/running-the-course/day-4.md:5
+#: src/running-the-course/course-structure.md:18
msgid ""
-"The afternoon of the fourth day should cover a topic of your choice. Include\n"
-"the topic in the announcement of the course, so that participants know what to\n"
-"expect."
+"The [Android Deep Dive](../android.md) is a half-day course on using Rust for\n"
+"Android platform development. This includes interoperability with C, C++, and\n"
+"Java."
msgstr ""
-"Der Nachmittag des vierten Tages sollte ein von dir ausgewähltes Thema behandeln.\n"
-"Erwähne das ausgewählte Thema in der Kursankündigung, sodass Teilnehmer wissen was auf sie zukommt."
+"Der [Android Deep Dive](../android.md) ist ein halbtägiger Kurs zur Verwendung von Rust für\n"
+"Entwicklung der Android-Plattform. Dazu gehört die Interoperabilität mit C, C++ und\n"
+"Java."
-#: src/running-the-course/day-4.md:9
+#: src/running-the-course/course-structure.md:22
+#, fuzzy
msgid ""
-"This phase of the course is a chance for participants to see Rust in action on a\n"
-"codebase they might be familiar with. You can choose from the topics already\n"
-"defined here, or plan your own."
-msgstr ""
-"Dieser Abschnitt des Kurses ermöglicht es Teilnehmern Rust in einer Codebasis zu sehen die sie"
-"möglicherweise schon kennen. Du kannst entweder von den hier vorgeschlagenen Themen wählen, oder "
-"dein eigenes Thema planen."
-
-#: src/running-the-course/day-4.md:13
-msgid "Some topics need additional preparation:"
-msgstr "Manche Themen benötigen eine besondere Vorbereitung:"
-
-#: src/running-the-course/day-4.md:15
-msgid "## Android"
-msgstr "## Android"
-
-#: src/running-the-course/day-4.md:17
-msgid ""
-"If you chose Android for Day 4 afternoon, you will need an [AOSP checkout][1].\n"
-"Make a checkout of the [course repository][2] on the same machine and move the\n"
-"`src/android/` directory into the root of your AOSP checkout. This will ensure\n"
-"that the Android build system sees the `Android.bp` files in `src/android/`."
+"You will need an [AOSP checkout][1]. Make a checkout of the [course\n"
+"repository][2] on the same machine and move the `src/android/` directory into\n"
+"the root of your AOSP checkout. This will ensure that the Android build system\n"
+"sees the `Android.bp` files in `src/android/`."
msgstr ""
"Für die Android-spezifischen Teile an Tag 4 benötigst du eine lokale \n"
" Arbeitskopie von [AOSP][1]. Mache eine Arbeitskopie des [Kurses][2] \n"
@@ -1471,41 +1458,88 @@ msgstr ""
" sichergestellt, dass das Android-Buildsystem die \n"
" `Android.bp`-Dateien in `src/android/` sehen kann."
-#: src/running-the-course/day-4.md:22
+#: src/running-the-course/course-structure.md:27
msgid ""
-"Ensure that `adb sync` works with your emulator or real device and pre-build\n"
-"all Android examples using `src/android/build_all.sh`. Read the script to see\n"
-"the commands it runs and make sure they work when you run them by hand."
+"Ensure that `adb sync` works with your emulator or real device and pre-build all\n"
+"Android examples using `src/android/build_all.sh`. Read the script to see the\n"
+"commands it runs and make sure they work when you run them by hand."
msgstr ""
-" Stelle sicher, dass `adb sync` auf deinem Emulator oder Rechner funktioniert.\n"
-" Erstelle bereits vor dem Kurs alle Android-Beispiele mit `src/android/build_all.sh`. \n"
-" Schaue auch in das Skript rein und probiere aus, ob alle Befehle, die es ausführt\n"
-" auch von Hand ausgeführt funktionieren."
+"Stelle sicher, dass `adb sync` auf deinem Emulator oder Rechner funktioniert.\n"
+"Erstelle bereits vor dem Kurs alle Android-Beispiele mit `src/android/build_all.sh`. \n"
+"Schaue auch in das Skript rein und probiere aus, ob alle Befehle, die es ausführt\n"
+"auch von Hand ausgeführt funktionieren."
-#: src/running-the-course/day-4.md:26
-msgid "## Async"
-msgstr "## Async"
+#: src/running-the-course/course-structure.md:34
+msgid "### Bare-Metal"
+msgstr "### Bare-Metal"
-#: src/running-the-course/day-4.md:28
+#: src/running-the-course/course-structure.md:36
msgid ""
-"If you chose Async for Day 4 afternoon, you will need a fresh crate set up and\n"
-"the dependencies downloaded and ready to go. You can then copy/paste the\n"
-"examples into `src/main.rs` to experiment with them."
+"The [Bare-Metal Deep Dive](../bare-metal.md): a full day class on using Rust for\n"
+"bare-metal (embedded) development. Both microcontrollers and application\n"
+"processors are covered."
msgstr ""
-"Für den Async-spezifischen Teil an Tag 4 benötigst du eine frisch erstellte Kiste (crate). "
-"Ausserdem sollten die Abhängigkeiten (dependencies) bereits heruntergeladen sein. Danach können "
-"die Beispiele in `src/main.rs` eingefügt werden, um mit ihnen zu experimentieren."
+"Der [Bare-Metal Deep Dive](../bare-metal.md): ein ganztägiger Kurs über die Verwendung von Rust "
+"für\n"
+"Bare-Metal-Entwicklung (eingebettet). Sowohl Mikrocontroller als auch Anwendungen\n"
+"Prozessoren sind abgedeckt."
-#: src/running-the-course/day-4.md:32
+#: src/running-the-course/course-structure.md:40
+msgid ""
+"For the microcontroller part, you will need to buy the [BBC\n"
+"micro:bit](https://microbit.org/) v2 development board ahead of time. Everybody\n"
+"will need to install a number of packages as described on the [welcome\n"
+"page](../bare-metal.md)."
+msgstr ""
+"Für den Mikrocontroller-Teil müssen Sie das [BBC\n"
+"micro:bit](https://microbit.org/) v2-Entwicklungsboard im Voraus kaufen. Alle\n"
+"müssen eine Reihe von Paketen installieren, wie auf der [Willkommens \n"
+"Seite](../bare-metal.md) beschrieben."
+
+#: src/running-the-course/course-structure.md:45
+msgid "### Concurrency"
+msgstr "### Nebenläufigkeit"
+
+#: src/running-the-course/course-structure.md:47
+msgid ""
+"The [Concurrency Deep Dive](../concurrency.md) is a full day class on classical\n"
+"as well as `async`/`await` concurrency."
+msgstr ""
+"Der [Nebensläufgkeitsvertiefung](../concurrency.md) ist ein ganztägiger Kurs zur klassischen \n"
+"sowie „async“/„await“-Parallelität."
+
+#: src/running-the-course/course-structure.md:50
+msgid ""
+"You will need a fresh crate set up and the dependencies downloaded and ready to\n"
+"go. You can then copy/paste the examples into `src/main.rs` to experiment with\n"
+"them:"
+msgstr ""
+"Sie sollten eine neue Kiste (Crate) einrichten und die Abhängigkeiten (Dependencies) herunterladen "
+"und einsatzbereit machen. Anschließend können Sie die Beispiele kopieren und in „src/main.rs“ "
+"einfügen, um damit zu experimentieren:"
+
+#: src/running-the-course/course-structure.md:54
msgid ""
"```shell\n"
-"cargo init day4\n"
-"cd day4\n"
+"cargo init concurrency\n"
+"cd concurrency\n"
"cargo add tokio --features full\n"
"cargo run\n"
"```"
msgstr ""
+#: src/running-the-course/course-structure.md:61
+msgid "## Format"
+msgstr "## Format"
+
+#: src/running-the-course/course-structure.md:63
+msgid ""
+"The course is meant to be very interactive and we recommend letting the\n"
+"questions drive the exploration of Rust!"
+msgstr ""
+"Der Kurs soll sehr interaktiv ablaufen und wir empfehlen, durch Fragen die \n"
+"Erkundung von Rust voranzutreiben!"
+
#: src/running-the-course/keyboard-shortcuts.md:1
msgid "# Keyboard Shortcuts"
msgstr "# Tastaturkürzel"
@@ -1549,6 +1583,23 @@ msgid "Use the language picker in the top-right corner to switch between languag
msgstr "Benutze die Sprachenauswahl oben rechts, um die Sprache zu wechseln."
#: src/running-the-course/translations.md:11
+msgid "## Incomplete Translations"
+msgstr "# Angefangene Übersetzungen"
+
+#: src/running-the-course/translations.md:13
+msgid ""
+"There is a large number of in-progress translations. We link to the most\n"
+"recently updated translations:"
+msgstr ""
+
+#: src/running-the-course/translations.md:16
+msgid ""
+"* [French][fr] by [@KookaS] and [@vcaen].\n"
+"* [German][de] by [@Throvn] and [@ronaldfw].\n"
+"* [Japanese][ja] by [@CoinEZ-JPN] and [@momotaro1105]."
+msgstr ""
+
+#: src/running-the-course/translations.md:20
msgid ""
"If you want to help with this effort, please see [our instructions] for how to\n"
"get going. Translations are coordinated on the [issue tracker]."
@@ -1609,9 +1660,8 @@ msgid "#### Debian"
msgstr "#### Debian"
#: src/cargo.md:20
-#, fuzzy
msgid "On Debian/Ubuntu, you can install Cargo, the Rust source and the [Rust formatter][6] with"
-msgstr "Auf Debian/Ubuntu kannst du Cargo und den Rust Quellcode wie folgt installieren:"
+msgstr "Auf Debian/Ubuntu kannst du Cargo und den Rust Quellcode wie folgt installieren"
#: src/cargo.md:22
msgid ""
@@ -1650,7 +1700,6 @@ msgstr ""
"sind:"
#: src/cargo/rust-ecosystem.md:5
-#, fuzzy
msgid ""
"* `rustc`: the Rust compiler which turns `.rs` files into binaries and other\n"
" intermediate formats.\n"
@@ -1666,22 +1715,23 @@ msgid ""
" library. You can have multiple versions of Rust installed at once and `rustup`\n"
" will let you switch between them as needed."
msgstr ""
-"* `rustup`: der Rust Toolchain Installer und Updater. Dieses Werkzeug ist gewöhnungsbedürftig\n"
-" Installieren und aktualisieren Sie `rustc` und `cargo`, wenn neue Versionen von Rust "
-"veröffentlicht werden.\n"
-" Darüber hinaus kann `rustup` auch Dokumentationen für den Standard herunterladen\n"
-" Bibliothek. Sie können mehrere Versionen von Rust gleichzeitig installieren und „rustup“ "
-"ausführen\n"
-" können Sie nach Bedarf zwischen ihnen wechseln."
+"* `rustc`: der Rust-Compiler, der „.rs“-Dateien in Binärdateien und andere Zwischenformate "
+"umwandelt\n"
+"\n"
+"* `cargo`: der Rust-Abhängigkeitsmanager (Dependency manager) und das Bauwerkzeug (Build-Tool). "
+"Cargo weiß, wie die Abhängigkeiten heruntergeladen werden müssen, die auf "
+"gehostet werden, und übergibt Sie sie an\n"
+" `rustc` beim Erstellen Ihres Projekts. Cargo verfügt außerdem über einen integrierten "
+"Testausführer, \n"
+" der zum Ausführen von Unit-Tests verwendet wird."
#: 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/pattern-matching/destructuring-enums.md:35 src/error-handling/try-operator.md:50
-#: src/error-handling/converting-error-types-example.md:50 src/concurrency/threads.md:30
-#: src/async/async-await.md:25
-#, fuzzy
+#: src/basic-syntax/references.md:23 src/pattern-matching/destructuring-enums.md:35
+#: 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
msgid "Key points:"
-msgstr "Kernpunkte:"
+msgstr "Schlüsselpunkte:"
#: src/cargo/rust-ecosystem.md:23
msgid ""
@@ -1719,14 +1769,44 @@ msgid ""
" * It is also extensible with sub command plugins as well (such as [cargo clippy]).\n"
" * Read more from the [official Cargo Book]"
msgstr ""
+"* Rust hat einen schnellen Veröffentlichungsplan. Alle sich Wochen wird eine neue Version "
+"veröffentlicht. Neue Versionen bleiben rückwärtskompatibel mit\n"
+" Älteren Versionen und sie fügen neue Funktionen hinzu.\n"
+"\n"
+"* Es gibt drei Veröffentlichungskanäle: „stable“, „beta“ und „nightly“.\n"
+"\n"
+"* Neue Funktionen werden in „nightly“ getestet. „Beta“ wird\n"
+" alle sechs Wochen „stabil“.\n"
+"\n"
+"* Rust hat auch [Editionen]: Die aktuelle Edition ist Rust 2021. Vorherige\n"
+" Editionen waren Rust 2015 und Rust 2018.\n"
+"\n"
+" * Editionen dürfen rückwärtsinkompatible Änderungen vornehmen.\n"
+"\n"
+" * Um zu verhindern, dass Code nicht kaputt geht, sind Editionen optional: Sie wählen ihre "
+"Edition für ihre Kiste (Crate) in der Datei \"Cargo.toml\"\n"
+"\n"
+" * Um eine Aufspaltung des Ökosystems zu vermeiden, können Rust-Compiler Code der für "
+"verschiedene Editionen geschrieben wurde vermischen.\n"
+"\n"
+" * Erwähnen Sie, dass es ziemlich selten vorkommt, dass der Compiler jemals direkt und nicht "
+"über `cargo` verwendet wird (die meisten Benutzer tun dies nie).\n"
+"\n"
+" * Es könnte erwähnenswert sein, dass Cargo selbst ein äußerst leistungsstarkes und umfassendes "
+"Tool ist. Es verfügt über viele erweiterte Funktionen, einschließlich, aber nicht beschränkt auf:\n"
+" * Projekt-/Paketstruktur\n"
+" * [Arbeitsbereiche]\n"
+" * Verwaltung/Caching von Entwicklungsabhängigkeiten und Laufzeitabhängigkeiten\n"
+" * [Build-Skripting]\n"
+" * [globale Installation]\n"
+" * Es ist auch mit Unterbefehls-Plugins erweiterbar (z. B. [cargo clippy]).\n"
+" * Lesen Sie mehr aus dem [offiziellen Cargo Buch]"
#: src/cargo/code-samples.md:1
-#, fuzzy
msgid "# Code Samples in This Training"
msgstr "# Codebeispiele in diesem Training"
#: src/cargo/code-samples.md:3
-#, fuzzy
msgid ""
"For this training, we will mostly explore the Rust language through examples\n"
"which can be executed through your browser. This makes the setup much easier and\n"
@@ -1734,21 +1814,20 @@ msgid ""
msgstr ""
"In diesem Training werden wir die Rust-Sprache hauptsächlich anhand von Beispielen erkunden\n"
"die über Ihren Browser ausgeführt werden können. Dies erleichtert die Einrichtung erheblich und\n"
-"sorgt für ein konsistentes Erlebnis für alle."
+"sorgt für ein konsistentes Erlebnis."
#: src/cargo/code-samples.md:7
-#, fuzzy
msgid ""
"Installing Cargo is still encouraged: it will make it easier for you to do the\n"
"exercises. On the last day, we will do a larger exercise which shows you how to\n"
"work with dependencies and for that you need Cargo."
msgstr ""
-"Die Installation von Cargo wird dennoch empfohlen: Es wird Ihnen die Arbeit erleichtern\n"
-"Übungen. Am letzten Tag werden wir eine größere Übung machen, die Ihnen zeigt, wie es geht\n"
-"Arbeiten Sie mit Abhängigkeiten und dafür benötigen Sie Cargo."
+"Die Installation von Cargo wird dennoch empfohlen: Es wird Ihnen die Bearbeitung der Übungen "
+"erleichtern.\n"
+"Am letzten Tag werden wir eine größere Übung machen, die Ihnen zeigt, wie\n"
+"Sie mit Abhängigkeiten (Dependencies) arbeiten und dafür benötigen Sie Cargo."
#: src/cargo/code-samples.md:11
-#, fuzzy
msgid "The code blocks in this course are fully interactive:"
msgstr "Die Codeblöcke in diesem Kurs sind vollständig interaktiv:"
@@ -1762,17 +1841,14 @@ msgid ""
msgstr ""
#: src/cargo/code-samples.md:19
-#, fuzzy
msgid ""
"You can use Ctrl + Enter to execute the code when focus is in the\n"
"text box."
msgstr ""
-"Sie können Strg + Eingabe verwenden, um den Code auszuführen, wenn der Fokus auf der "
-"ist\n"
-"Textfeld."
+"Sie können Strg + Eingabe verwenden, um den Code auszuführen, wenn der Fokus auf dem "
+"Textfeld ist."
#: src/cargo/code-samples.md:24
-#, fuzzy
msgid ""
"Most code samples are editable like shown above. A few code samples\n"
"are not editable for various reasons:"
@@ -1781,7 +1857,6 @@ msgstr ""
"sind aus verschiedenen Gründen nicht editierbar:"
#: src/cargo/code-samples.md:27
-#, fuzzy
msgid ""
"* The embedded playgrounds cannot execute unit tests. Copy-paste the\n"
" code and open it in the real Playground to demonstrate unit tests.\n"
@@ -1791,48 +1866,50 @@ msgid ""
" solve the exercises using a local Rust installation or via the\n"
" Playground."
msgstr ""
-"* Die eingebetteten Playgrounds verlieren ihren Zustand, sobald Sie navigieren\n"
-" Weg von der Seite! Aus diesem Grund sollten die Schüler\n"
-" Lösen Sie die Aufgaben mit einer lokalen Rust-Installation oder über die\n"
-" Spielplatz."
+"* Die eingebetteten Testumgebungen (embedded Playgrounds) können keine Unit-Tests durchführen. "
+"Kopieren Sie die Datei und fügen Sie \n"
+" den Code in der echten Testumgebung ein, um Unit-Tests zu demonstrieren.\n"
+"\n"
+"* Die eingebetteten Testumgebungen verlieren ihren Zustand, sobald Sie von der Seite weg "
+"navigieren!\n"
+" Aus diesem Grund sollten die Schüler die Übungen mit einer lokalen Rust-Installation oder in "
+"der\n"
+" lokalen Testumgebung lösen."
#: src/cargo/running-locally.md:1
-#, fuzzy
msgid "# Running Code Locally with Cargo"
msgstr "# Code lokal mit Cargo ausführen"
#: src/cargo/running-locally.md:3
-#, fuzzy
msgid ""
"If you want to experiment with the code on your own system, then you will need\n"
"to first install Rust. Do this by following the [instructions in the Rust\n"
"Book][1]. This should give you a working `rustc` and `cargo`. At the time of\n"
"writing, the latest stable Rust release has these version numbers:"
msgstr ""
-"Wenn Sie mit dem Code auf Ihrem eigenen System experimentieren möchten, benötigen Sie\n"
-"zuerst Rust zu installieren. Befolgen Sie dazu die [Anweisungen in Rust\n"
-"Buch 1]. Dies sollte Ihnen ein funktionierendes `rustc` und `cargo` geben. Zur Zeit von\n"
-"Schreiben hat die neueste stabile Rust-Version diese Versionsnummern:"
+"Wenn Sie mit dem Code auf Ihrem eigenen System experimentieren möchten, sollten Sie\n"
+"zuerst Rust zu installieren. Befolgen Sie dazu die [Anweisungen in dem Rust\n"
+"Buch 1]. Dies sollte Ihnen ein funktionierendes `rustc` und `cargo` geben. Zum "
+"Verfassungszeitpunkt\n"
+"hat die neueste stabile Rust-Version diese Versionsnummer:"
#: src/cargo/running-locally.md:8
msgid ""
"```shell\n"
"% rustc --version\n"
-"rustc 1.61.0 (fe5b13d68 2022-05-18)\n"
+"rustc 1.69.0 (84c898d65 2023-04-16)\n"
"% cargo --version\n"
-"cargo 1.61.0 (a028ae4 2022-04-29)\n"
+"cargo 1.69.0 (6e9a83356 2023-04-12)\n"
"```"
msgstr ""
#: src/cargo/running-locally.md:15
-#, fuzzy
msgid ""
-"With this is in place, then follow these steps to build a Rust binary from one\n"
+"With this in place, follow these steps to build a Rust binary from one\n"
"of the examples in this training:"
msgstr ""
-"Wenn dies vorhanden ist, befolgen Sie diese Schritte, um eine Rust-Binärdatei aus einer zu "
-"erstellen\n"
-"der Beispiele in diesem Training:"
+"Wenn dies vorhanden ist, befolgen Sie diese Schritte, um eine Rust-Binärdatei aus einem Beispiel "
+"zu erstellen:"
#: src/cargo/running-locally.md:18
msgid ""
@@ -1886,29 +1963,24 @@ msgid ""
msgstr ""
#: src/cargo/running-locally.md:70
-#, fuzzy
msgid ""
"Try to encourage the class participants to install Cargo and use a\n"
"local editor. It will make their life easier since they will have a\n"
"normal development environment."
msgstr ""
-"Versuchen Sie, die Kursteilnehmer zu ermutigen, Cargo zu installieren und a\n"
-"lokaler Redakteur. Es wird ihr Leben einfacher machen, da sie a haben werden\n"
-"normale Entwicklungsumgebung."
+"Versuchen Sie, die Kursteilnehmer zu ermutigen, Cargo zu installieren und einen lokalen Texteditor "
+"zu verwenden\n"
+"Es wird ihr Leben einfacher machen, wenn alle eine lokale Entwicklungsumgebung haben."
#: src/welcome-day-1.md:1
-#, fuzzy
msgid "# Welcome to Day 1"
msgstr "# Willkommen zu Tag 1"
#: src/welcome-day-1.md:3
-#, fuzzy
msgid ""
"This is the first day of Comprehensive Rust. We will cover a lot of ground\n"
"today:"
-msgstr ""
-"Dies ist der erste Tag von Comprehensive Rust. Wir werden viel Boden abdecken\n"
-"Heute:"
+msgstr "Dies ist der erste Tag von Comprehensive Rust. Heute werden wir viel behandeln:"
#: src/welcome-day-1.md:6
msgid ""
@@ -1920,62 +1992,66 @@ msgid ""
"\n"
"* Ownership: move semantics, copying and cloning, borrowing, and lifetimes."
msgstr ""
+"* Grundlegende Rust-Syntax: Variablen, Skalar- und zusammengesetzte Typen (scalar-types, union-"
+"types) , Aufzählungen (enums), Strukturen (structs),\n"
+" Referenzen (references), Funktionen (functions) und Methoden (methods).\n"
+"\n"
+"* Speicherverwaltung: Stack vs. Heap, manuelle Speicherverwaltung, bereichsbasierte "
+"Speicherverwaltung und Speicherbereinigung (garbage collection).\n"
+"\n"
+"* Eigentum (ownership): Bewegungssemantik (move semantics), Kopieren und Klonen (copy and "
+"cloning), Ausleihen (borrowing) und Lebensdauer (lifetimes)."
#: src/welcome-day-1.md:16
-#, fuzzy
msgid "Please remind the students that:"
msgstr "Bitte erinnern Sie die Schüler daran:"
#: src/welcome-day-1.md:18
-#, fuzzy
msgid ""
"* They should ask questions when they get them, don't save them to the end.\n"
"* The class is meant to be interactive and discussions are very much encouraged!\n"
" * As an instructor, you should try to keep the discussions relevant, i.e.,\n"
-" keep the related to how Rust does things vs some other language. It can be\n"
-" hard to find the right balance, but err on the side of allowing discussions\n"
-" since they engage people much more than one-way communication.\n"
+" keep the discussions related to how Rust does things vs some other language. \n"
+" It can be hard to find the right balance, but err on the side of allowing \n"
+" discussions since they engage people much more than one-way communication.\n"
"* The questions will likely mean that we talk about things ahead of the slides.\n"
" * This is perfectly okay! Repetition is an important part of learning. Remember\n"
" that the slides are just a support and you are free to skip them as you\n"
" like."
msgstr ""
-"* Sie sollten Fragen stellen, wenn sie sie bekommen, und sie nicht bis zum Ende aufheben.\n"
-"* Der Unterricht soll interaktiv sein und Diskussionen sind sehr erwünscht!\n"
+"* Sie sollten Fragen stellen, sobald ihnen welche einfallen, und nicht bis zum Ende warten.\n"
+"* Der Unterricht soll interaktiv sein und Diskussionen sind erwünscht!\n"
" * Als Dozent sollten Sie versuchen, die Diskussionen relevant zu halten, d. h.\n"
" Behalten Sie den Bezug dazu bei, wie Rust Dinge im Vergleich zu einer anderen Sprache tut. Es "
-"kann sein\n"
-" schwer, die richtige Balance zu finden, aber lieber Diskussionen zulassen\n"
-" da sie Menschen viel mehr einbeziehen als nur eine Einbahnstraße.\n"
-"* Die Fragen werden wahrscheinlich bedeuten, dass wir über die Dinge vor den Folien sprechen.\n"
-" * Das ist vollkommen in Ordnung! Wiederholung ist ein wichtiger Teil des Lernens. Erinnern\n"
-" dass die Folien nur eine Unterstützung sind und Sie sie nach Belieben überspringen können\n"
-" wie."
+"kann schwer sein,\n"
+" die richtige Balance zu finden, aber lassen Sie lieber Diskussionen zu,\n"
+" um Kursteilnehmer einzubeziehen und lange Monologe zu vermeiden.\n"
+"* Bei Fragen wird es wahrscheinlich dazu kommen, dass wir über die Dinge vor den eigentlichen "
+"Folien sprechen.\n"
+" * Das ist vollkommen in Ordnung! Wiederholung ist ein wichtiger Teil des Lernens.\n"
+" Die Folien sind nur eine Unterstützung und Sie können sie nach Belieben überspringen."
#: src/welcome-day-1.md:29
-#, fuzzy
msgid ""
"The idea for the first day is to show _just enough_ of Rust to be able to speak\n"
"about the famous borrow checker. The way Rust handles memory is a major feature\n"
"and we should show students this right away."
msgstr ""
-"Die Idee für den ersten Tag ist, Rust _gerade genug_ zu zeigen, um sprechen zu können\n"
-"über den berühmten Kreditprüfer. Die Art und Weise, wie Rust mit Speicher umgeht, ist ein "
-"wichtiges Merkmal\n"
-"und das sollten wir den Schülern gleich zeigen."
+"Die Idee für den ersten Tag ist, Rust _gerade genug_ zu zeigen, um über den berühmten "
+"Ausleihenprüfer (borrow checker) sprechen zu können.\n"
+"Die Art und Weise, wie Rust mit Speicher umgeht, ist ein wichtiges Merkmal\n"
+"und das sollten Sie den Schülern direkt zeigen."
#: src/welcome-day-1.md:33
-#, fuzzy
msgid ""
"If you're teaching this in a classroom, this is a good place to go over the\n"
"schedule. We suggest splitting the day into two parts (following the slides):"
msgstr ""
-"Wenn Sie dies in einem Klassenzimmer unterrichten, ist dies ein guter Ort, um darüber "
-"nachzudenken\n"
-"Zeitplan. Wir empfehlen, den Tag in zwei Teile aufzuteilen (nach den Folien):"
+"Wenn Sie dies in einem Klassenzimmer unterrichten, ist dies ein guter Ort, um über den Zeitplan zu "
+"gehen.\n"
+"Wir empfehlen, den Tag in zwei Teile aufzuteilen (nach den Folien):"
#: src/welcome-day-1.md:36
-#, fuzzy
msgid ""
"* Morning: 9:00 to 12:00,\n"
"* Afternoon: 13:00 to 16:00."
@@ -1984,7 +2060,6 @@ msgstr ""
"* Nachmittag: 13:00 bis 16:00 Uhr."
#: src/welcome-day-1.md:39
-#, fuzzy
msgid ""
"You can of course adjust this as necessary. Please make sure to include breaks,\n"
"we recommend a break every hour!"
@@ -1993,17 +2068,14 @@ msgstr ""
"Wir empfehlen jede Stunde eine Pause!"
#: src/welcome-day-1/what-is-rust.md:1
-#, fuzzy
msgid "# What is Rust?"
-msgstr "# Was ist Rost?"
+msgstr "# Was ist Rust?"
#: src/welcome-day-1/what-is-rust.md:3
-#, fuzzy
msgid "Rust is a new programming language which had its [1.0 release in 2015][1]:"
msgstr "Rust ist eine neue Programmiersprache, die 2015 ihre Version 1.0 hatte:"
#: src/welcome-day-1/what-is-rust.md:5
-#, fuzzy
msgid ""
"* Rust is a statically compiled language in a similar role as C++\n"
" * `rustc` uses LLVM as its backend.\n"
@@ -2032,12 +2104,10 @@ msgstr ""
" * Server."
#: src/welcome-day-1/what-is-rust.md:21
-#, fuzzy
msgid "Rust fits in the same area as C++:"
msgstr "Rust passt in den gleichen Bereich wie C++:"
#: src/welcome-day-1/what-is-rust.md:23
-#, fuzzy
msgid ""
"* High flexibility.\n"
"* High level of control.\n"
@@ -2048,26 +2118,24 @@ msgstr ""
"* Hohe Flexibilität.\n"
"* Hohes Maß an Kontrolle.\n"
"* Kann auf sehr eingeschränkte Geräte wie Mobiltelefone herunterskaliert werden.\n"
-"* Hat keine Laufzeit oder Garbage Collection.\n"
+"* Hat keine Laufzeit oder Speicherbereinigung (garbage collection).\n"
"* Konzentriert sich auf Zuverlässigkeit und Sicherheit ohne Leistungseinbußen."
#: src/hello-world.md:1
-#, fuzzy
msgid "# Hello World!"
msgstr "# Hallo Welt!"
#: src/hello-world.md:3
-#, fuzzy
msgid ""
"Let us jump into the simplest possible Rust program, a classic Hello World\n"
"program:"
msgstr ""
-"Lassen Sie uns in das einfachste Rust-Programm einsteigen, ein klassisches Hello World\n"
+"Lassen Sie uns in das einfachste Rust-Programm einsteigen, ein klassisches Hallo Welt\n"
"Programm:"
#: src/hello-world.md:6
msgid ""
-"```rust\n"
+"```rust,editable\n"
"fn main() {\n"
" println!(\"Hello 🌍!\");\n"
"}\n"
@@ -2075,12 +2143,10 @@ msgid ""
msgstr ""
#: src/hello-world.md:12
-#, fuzzy
msgid "What you see:"
-msgstr "Was Sie sehen:"
+msgstr "Sie sehen:"
#: src/hello-world.md:14
-#, fuzzy
msgid ""
"* Functions are introduced with `fn`.\n"
"* Blocks are delimited by curly braces like in C and C++.\n"
@@ -2088,20 +2154,19 @@ msgid ""
"* Rust has hygienic macros, `println!` is an example of this.\n"
"* Rust strings are UTF-8 encoded and can contain any Unicode character."
msgstr ""
-"* Funktionen werden mit `fn` eingeleitet.\n"
+"* Funktionen beginnen mit `fn`.\n"
"* Blöcke werden wie in C und C++ durch geschweifte Klammern getrennt.\n"
-"* Die Hauptfunktion ist der Einstiegspunkt des Programms.\n"
-"* Rust hat hygienische Makros, `println!` ist ein Beispiel dafür.\n"
+"* Die `main`-Funktion ist der Einstiegspunkt des Programms.\n"
+"* Rust hat hygienische (hygienic) Makros, `println!` ist ein Beispiel dafür.\n"
"* Rust-Strings sind UTF-8-codiert und können beliebige Unicode-Zeichen enthalten."
#: src/hello-world.md:22
-#, fuzzy
msgid ""
"This slide tries to make the students comfortable with Rust code. They will see\n"
"a ton of it over the next four days so we start small with something familiar."
msgstr ""
-"Diese Folie versucht, die Schüler mit Rust-Code vertraut zu machen. Sie werden sehen\n"
-"eine Tonne davon in den nächsten vier Tagen, also fangen wir klein mit etwas Vertrautem an."
+"Diese Folie versucht, die Schüler mit Rust-Code vertraut zu machen. Sie werden viel\n"
+"davon in den nächsten vier Tagen sehen, also fangen wir klein und mit etwas Vertrautem an."
#: src/hello-world.md:27
msgid ""
@@ -2116,16 +2181,29 @@ msgid ""
"\n"
"* Macros being 'hygienic' means they don't accidentally capture identifiers from\n"
" the scope they are used in. Rust macros are actually only\n"
-" [partially hygenic](https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene.html)."
+" [partially hygienic](https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene.html)."
msgstr ""
+"* Rust ist anderen Sprachen in der C/C++/Java-Tradition sehr ähnlich. Es ist\n"
+" Imperativ (nicht funktional) und es wird nicht versucht, Dinge neu zu erfinden, es sei denn es "
+"ist\n"
+" absolut notwendig.\n"
+"\n"
+"* Rust ist modern und unterstützt Dinge wie Unicode vollständig.\n"
+"\n"
+"* Rust verwendet Makros für Situationen, in denen Sie eine variable Anzahl von Argumenten haben "
+"möchte\n"
+" (keine [Funktionüberladung](basic-syntax/functions-interlude.md)).\n"
+"\n"
+"* Makros sind „hygienisch“, was bedeutet, dass sie nicht versehentlich Identifikatoren in ihrem "
+"Umfang (scope) in dem sie verwendet werden erfassen\n"
+" Rust-Makros sind eigentlich nur\n"
+" [teilweise hygienisch](https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene.html)."
#: src/hello-world/small-example.md:1
-#, fuzzy
msgid "# Small Example"
-msgstr "# Kleines Beispiel"
+msgstr "# Ein kleines Beispiel"
#: src/hello-world/small-example.md:3
-#, fuzzy
msgid "Here is a small example program in Rust:"
msgstr "Hier ein kleines Beispielprogramm in Rust:"
@@ -2149,16 +2227,14 @@ msgid ""
msgstr ""
#: src/hello-world/small-example.md:23
-#, fuzzy
msgid ""
"The code implements the Collatz conjecture: it is believed that the loop will\n"
"always end, but this is not yet proved. Edit the code and play with different\n"
"inputs."
msgstr ""
-"Der Code implementiert die Collatz-Vermutung: Es wird angenommen, dass die Schleife dies tut\n"
-"immer enden, aber das ist noch nicht bewiesen. Bearbeiten Sie den Code und spielen Sie mit "
-"verschiedenen\n"
-"Eingänge."
+"Der Code implementiert die Collatz-Vermutung: Es wird angenommen, dass die Schleife immer enden "
+"wird, allerdings ist das noch nicht bewiesen. Ändern Sie den Code und spielen Sie mit "
+"verschiedenen Eingaben."
#: src/hello-world/small-example.md:29
msgid ""
@@ -2177,39 +2253,51 @@ msgid ""
" which has the rules of the formatting mini-language. It's important that the\n"
" students become familiar with searching in the standard library."
msgstr ""
+"* Erklären Sie, dass alle Variablen statisch typisiert sind. Versuchen Sie, `i32` zu entfernen um "
+"Typinferenz (type inference) auszulösen. Versuchen Sie es stattdessen mit `i8` und lösen Sie einen "
+"Ganzzahlüberlauf zur Laufzeit aus.\n"
+"\n"
+"* Ändern Sie `let mut x` in `let x`, besprechen Sie den Compilerfehler.\n"
+"\n"
+"* Zeigen Sie, wie `print!` einen Kompilierungsfehler ausgibt, wenn die Argumente nicht mit dem "
+"Format-String übereinstimmen.\n"
+"\n"
+"* Zeigen Sie, wie Sie `{}` als Platzhalter verwenden müssen, wenn Sie einen Ausdruck (Expression) "
+"drucken möchten,\n"
+" der komplexer als nur eine einzelne Variable ist.\n"
+"\n"
+"* Zeigen Sie den Schülern die Standardbibliothek (standard library) und zeigen Sie ihnen, wie sie "
+"nach `std::fmt` suchen\n"
+" welches die Regeln der Formatierungs-Minisprache enthält. Es ist wichtig, dass die\n"
+" Kursteilnehmer mit der Suche in der Standardbibliothek vertraut gemacht werden."
#: src/why-rust.md:1
-#, fuzzy
msgid "# Why Rust?"
-msgstr "# Warum Rost?"
+msgstr "# Warum Rust?"
#: src/why-rust.md:3
-#, fuzzy
msgid "Some unique selling points of Rust:"
msgstr "Einige Alleinstellungsmerkmale von Rust:"
#: src/why-rust.md:5
-#, fuzzy
msgid ""
"* Compile time memory safety.\n"
"* Lack of undefined runtime behavior.\n"
"* Modern language features."
msgstr ""
"* Kompilierzeit-Speichersicherheit.\n"
-"* Mangel an undefiniertem Laufzeitverhalten.\n"
+"* Mangel in undefiniertem Laufzeitverhalten.\n"
"* Moderne Sprachfunktionen."
#: src/why-rust.md:11
-#, fuzzy
msgid ""
"Make sure to ask the class which languages they have experience with. Depending\n"
"on the answer you can highlight different features of Rust:"
msgstr ""
-"Fragen Sie die Klasse unbedingt, mit welchen Sprachen sie Erfahrung haben. Abhängig\n"
-"Auf der Antwort können Sie verschiedene Funktionen von Rust hervorheben:"
+"Fragen Sie den Kurs unbedingt, mit welchen Programmiersprachen sie Erfahrung haben. Abhängig\n"
+"von der Antwort können Sie verschiedene Funktionen von Rust hervorheben:"
#: src/why-rust.md:14
-#, fuzzy
msgid ""
"* Experience with C or C++: Rust eliminates a whole class of _runtime errors_\n"
" via the borrow checker. You get performance like in C and C++, but you don't\n"
@@ -2221,23 +2309,30 @@ msgid ""
" you get fast and predictable performance like C and C++ (no garbage collector)\n"
" as well as access to low-level hardware (should you need it)"
msgstr ""
+"* Erfahrung mit C oder C++: Rust eliminiert eine ganze Klasse von _Laufzeitfehlern (runtime "
+"Errors)_\n"
+" über den Ausleihenprüfer (borrow checker). Sie erhalten ähnliche Leistung wie in C und C++, "
+"aber haben\n"
+" keine Probleme mit der Speicherunsicherheit. Darüber hinaus erhalten Sie eine moderne Sprache "
+"mit\n"
+" Konstrukten wie Mustervergleich (Pattern matching) und integriertes Abhängigkeitsmanagement "
+"(dependency management).\n"
+"\n"
"* Erfahrung mit Java, Go, Python, JavaScript...: Sie erhalten die gleiche Speichersicherheit\n"
-" wie in diesen Sprachen, dazu ein ähnliches Hochsprachengefühl. Zusätzlich\n"
-" Sie erhalten eine schnelle und vorhersehbare Leistung wie C und C++ (kein Garbage Collector)\n"
-" sowie Zugriff auf Low-Level-Hardware (falls erforderlich)"
+" wie in diesen Sprachen, dazu ein ähnlich hohes Sprachgefühl. Zusätzlich\n"
+" erhalten Sie eine schnelle und vorhersehbare Leistung wie in C und C++ (keine "
+"Speicherbereinigung (garbage collector))\n"
+" sowie Zugriff auf Low-Level-Hardware (falls Sie diese benötigen)."
#: src/why-rust/compile-time.md:1
-#, fuzzy
msgid "# Compile Time Guarantees"
msgstr "# Kompilierzeitgarantien"
#: src/why-rust/compile-time.md:3
-#, fuzzy
msgid "Static memory management at compile time:"
msgstr "Statische Speicherverwaltung zur Kompilierzeit:"
#: src/why-rust/compile-time.md:5
-#, fuzzy
msgid ""
"* No uninitialized variables.\n"
"* No memory leaks (_mostly_, see notes).\n"
@@ -2248,28 +2343,24 @@ msgid ""
"* No data races between threads.\n"
"* No iterator invalidation."
msgstr ""
-"* Keine nicht initialisierten Variablen.\n"
+"* Keine nicht initialisierten (uninitialized) Variablen.\n"
"* Keine Speicherlecks (_meistens_, siehe Anmerkungen).\n"
-"* Keine Doppelbefreiungen.\n"
-"* Keine Nachnutzung.\n"
-"* Keine `NULL`-Zeiger.\n"
+"* Keine Doppelbefreiungen (double-frees).\n"
+"* Keine Nachnutzung (use-after-free).\n"
+"* Keine `NULL`-Zeiger (null Pointer).\n"
"* Keine vergessenen gesperrten Mutexe.\n"
-"* Keine Datenrennen zwischen Threads.\n"
+"* Keine Datenrennen (data races) zwischen Ausführungssträngen (threads).\n"
"* Keine Invalidierung des Iterators."
#: src/why-rust/compile-time.md:16
-#, fuzzy
msgid ""
"It is possible to produce memory leaks in (safe) Rust. Some examples\n"
"are:"
-msgstr ""
-"Es ist möglich, Speicherlecks in (sicherem) Rust zu erzeugen. Einige Beispiele\n"
-"Sind:"
+msgstr "Es ist möglich, Speicherlecks in (sicherem) Rust zu erzeugen. Einige Beispiele sind:"
#: src/why-rust/compile-time.md:19
-#, fuzzy
msgid ""
-"* You can for use [`Box::leak`] to leak a pointer. A use of this could\n"
+"* You can use [`Box::leak`] to leak a pointer. A use of this could\n"
" be to get runtime-initialized and runtime-sized static variables\n"
"* You can use [`std::mem::forget`] to make the compiler \"forget\" about\n"
" a value (meaning the destructor is never run).\n"
@@ -2280,34 +2371,29 @@ msgid ""
msgstr ""
"* Sie können [`Box::leak`] verwenden, um einen Zeiger zu verlieren. Eine Nutzung dieser könnte\n"
" sein, um zur Laufzeit initialisierte statische Variablen in Laufzeitgröße zu erhalten\n"
-"* Sie können [`std::mem::forget`] verwenden, um den Compiler \"vergessen\" zu lassen\n"
-" ein Wert (was bedeutet, dass der Destruktor niemals ausgeführt wird).\n"
-"* Sie können auch versehentlich einen [Referenzzyklus] mit `Rc` oder erstellen\n"
-" \"Bogen\".\n"
-"* In der Tat werden einige in Betracht ziehen, eine Sammlung unendlich als Erinnerung zu füllen\n"
-" Leck und Rost schützt nicht vor denen."
+"* Sie können [`std::mem::forget`] verwenden, um den Compiler einen Wert \"vergessen\" zu lassen\n"
+" (was bedeutet, dass der Destruktor niemals ausgeführt wird).\n"
+"* Sie können auch versehentlich einen [Referenzzyklus] mit `Rc` oder `Arc` erstellen\n"
+"* In der Tat werden einige in Betracht ziehen, eine Sammlung (Collection) unendlich zu befüllen\n"
+" Rust schützt nicht vor sowelchen Speicherlecks (memory leaks)."
#: src/why-rust/compile-time.md:28
-#, fuzzy
msgid ""
"For the purpose of this course, \"No memory leaks\" should be understood\n"
"as \"Pretty much no *accidental* memory leaks\"."
msgstr ""
-"Für die Zwecke dieses Kurses sollte \"Keine Speicherlecks\" verstanden werden\n"
+"\"Keine Speicherlecks\" sollten somit verstanden werden\n"
"als \"so gut wie keine *versehentlichen* Speicherlecks\"."
#: src/why-rust/runtime.md:1
-#, fuzzy
msgid "# Runtime Guarantees"
msgstr "# Laufzeitgarantien"
#: src/why-rust/runtime.md:3
-#, fuzzy
msgid "No undefined behavior at runtime:"
-msgstr "Kein undefiniertes Verhalten zur Laufzeit:"
+msgstr "Kein undefiniertes Verhalten (undefined behavior) zur Laufzeit:"
#: src/why-rust/runtime.md:5
-#, fuzzy
msgid ""
"* Array access is bounds checked.\n"
"* Integer overflow is defined."
@@ -2316,7 +2402,6 @@ msgstr ""
"* Ganzzahlüberlauf ist definiert."
#: src/why-rust/runtime.md:12
-#, fuzzy
msgid ""
"* Integer overflow is defined via a compile-time flag. The options are\n"
" either a panic (a controlled crash of the program) or wrap-around\n"
@@ -2328,56 +2413,58 @@ msgid ""
" `unsafe` allows you to call functions such as `slice::get_unchecked`\n"
" which does not do bounds checking."
msgstr ""
-"* Ganzzahlüberlauf wird über ein Flag zur Kompilierzeit definiert. Die Optionen sind\n"
-" entweder eine Panik (ein kontrollierter Absturz des Programms) oder ein Wrap-Around\n"
-" Semantik. Standardmäßig erhalten Sie Panik im Debug-Modus (`cargo build`)\n"
-" und Wrap-Around im Release-Modus (`cargo build --release`)."
+"* Ganzzahlüberlauf (integer overflow) wird über ein Flag zur Kompilierzeit definiert. Die Optionen "
+"sind\n"
+" entweder ein kontrollierter Abbruch des Programms (panic) oder eine Wrap-Around\n"
+" Semantik. Standardmäßig erhalten Sie einen Abbruch (panic) im Debug-Modus (`cargo build`)\n"
+" und ein Wrap-Around im Release-Modus (`cargo build --release`).\n"
+"\n"
+"* Die Grenzüberprüfung (bounds checking) kann nicht mit einem Compiler-Flag deaktiviert werden. Es "
+"kann auch\n"
+" nicht direkt mit dem Schlüsselwort „unsafe“ deaktiviert werden. Jedoch können Sie Funktionen "
+"wie\n"
+" `slice::get_unchecked` mit `unsafe` aufrufen\n"
+" was keine Grenzenprüfung durchführt."
#: src/why-rust/modern.md:1
-#, fuzzy
msgid "# Modern Features"
msgstr "# Moderne Funktionen"
#: src/why-rust/modern.md:3
-#, fuzzy
msgid "Rust is built with all the experience gained in the last 40 years."
-msgstr "Rust wird mit all den Erfahrungen der letzten 40 Jahre gebaut."
+msgstr "Rust wurde mit vielen Erfahrungen aus den letzten 40 Jahren gebaut."
#: src/why-rust/modern.md:5
-#, fuzzy
msgid "## Language Features"
msgstr "## Sprachmerkmale"
#: src/why-rust/modern.md:7
-#, fuzzy
msgid ""
"* Enums and pattern matching.\n"
"* Generics.\n"
"* No overhead FFI.\n"
"* Zero-cost abstractions."
msgstr ""
-"* Enums und Musterabgleich.\n"
+"* Enums und Musterabgleich (pattern matching).\n"
"* Generika.\n"
"* Kein Overhead-FFI.\n"
"* Nullkosten-Abstraktionen."
#: src/why-rust/modern.md:12
-#, fuzzy
msgid "## Tooling"
-msgstr "## Werkzeuge"
+msgstr "## Werkzeuge (Tools)"
#: src/why-rust/modern.md:14
-#, fuzzy
msgid ""
"* Great compiler errors.\n"
"* Built-in dependency manager.\n"
"* Built-in support for testing.\n"
"* Excellent Language Server Protocol support."
msgstr ""
-"* Große Compiler-Fehler.\n"
-"* Eingebauter Abhängigkeitsmanager.\n"
-"* Eingebaute Unterstützung zum Testen.\n"
-"* Hervorragende Unterstützung des Language Server Protocol."
+"* Gute Compiler-Fehler.\n"
+"* Eingebauter Paketmanager.\n"
+"* Eingebaute Unterstützung für Tests.\n"
+"* Hervorragende Unterstützung des Language Server Protokolls."
#: src/why-rust/modern.md:23
msgid ""
@@ -2419,19 +2506,52 @@ msgid ""
"* [rust-analyzer] is a well supported LSP implementation used in major\n"
" IDEs and text editors."
msgstr ""
+"* Kostenfreie Abstraktionen, ähnlich wie bei C++, bedeuten, dass Sie für Programmierkonstrukte auf "
+"höherer Ebene nicht mit Speicher oder CPU „bezahlen“ müssen. Beispielsweise sollte das Schreiben "
+"einer Schleife mit `for` ungefähr zu denselben Low-Level-Anweisungen führen wie die Verwendung des "
+"Konstrukts `.iter().fold()`.\n"
+"\n"
+"* Es kann erwähnenswert sein, dass Rust-Enums „algebraische Datentypen“ sind, auch bekannt als "
+"„Summentypen“, die es dem Typsystem ermöglichen, Dinge wie `Option` und `Result` "
+"auszudrücken.\n"
+"\n"
+"* Erinnern Sie die Teilnehmer daran, die Fehler zu lesen – viele Entwickler haben sich daran "
+"gewöhnt, lange Compiler-Ausgaben zu ignorieren. Der Rust-Compiler ist deutlich gesprächiger als "
+"andere Compiler. Es liefert Ihnen oft _umsetzbares_ Feedback, das Sie in Ihren Code einfach "
+"übernehmen können.\n"
+"\n"
+"* Die Rust-Standardbibliothek ist im Vergleich zu Sprachen wie Java, Python und Go klein. Rust "
+"bringt einige Dinge nicht mit, die Sie als normal betrachten könnten:\n"
+"\n"
+" * ein Zufallszahlengenerator, siehe aber [rand].\n"
+" * Unterstützung für SSL oder TLS, siehe jedoch [rusttls].\n"
+" * Unterstützung für JSON, siehe jedoch [serde_json].\n"
+"\n"
+"Der Grund dafür ist, dass die Funktionalität in der Standardbibliothek nicht herausgenommen werden "
+"dürfen und daher sehr stabil sein muss. Für die obigen Beispiele arbeitet die Rust-Gemeinschaft "
+"immer noch daran, die beste Lösung zu finden – und vielleicht gibt es für einige dieser Dinge "
+"keine einzige „beste Lösung“.\n"
+"\n"
+" Rust verfügt über einen integrierten Paketmanager in Form von Cargo, der das Herunterladen und "
+"Kompilieren von Crates von Drittanbietern vereinfacht. Dies hat zur Folge, dass die "
+"Standardbibliothek kleiner sein kann.\n"
+"\n"
+" Das Auffinden guter Kisten von Drittanbietern kann ein Problem sein. Websites wie\n"
+" hilft Ihnen dabei, indem es Ihnen ermöglicht, Gesundheitsmetriken für Kisten "
+"zu vergleichen, um eine gute und vertrauenswürdige zu finden.\n"
+" \n"
+"* [rust-analyzer] ist eine gut unterstützte LSP-Implementierung, die in wichtigen IDEs und "
+"Texteditoren verwendet wird."
#: src/basic-syntax.md:1
-#, fuzzy
msgid "# Basic Syntax"
msgstr "# Grundlegende Syntax"
#: src/basic-syntax.md:3
-#, fuzzy
msgid "Much of the Rust syntax will be familiar to you from C, C++ or Java:"
-msgstr "Ein Großteil der Rust-Syntax wird Ihnen aus C oder C++ vertraut sein:"
+msgstr "Ein Großteil der Rust-Syntax wird Ihnen aus C oder C++ bekannt sein:"
#: src/basic-syntax.md:5
-#, fuzzy
msgid ""
"* Blocks and scopes are delimited by curly braces.\n"
"* Line comments are started with `//`, block comments are delimited by `/* ...\n"
@@ -2439,19 +2559,16 @@ msgid ""
"* Keywords like `if` and `while` work the same.\n"
"* Variable assignment is done with `=`, comparison is done with `==`."
msgstr ""
-"* Blöcke und Bereiche werden durch geschweifte Klammern getrennt.\n"
-"* Zeilenkommentare beginnen mit `//`, Blockkommentare werden mit `/* begrenzt ...\n"
-" */`.\n"
-"* Schlüsselwörter wie „if“ und „while“ funktionieren gleich.\n"
+"* Blöcke und Bereiche (scopes) werden durch geschweifte Klammern getrennt.\n"
+"* Zeilenkommentare beginnen mit `//`, Blockkommentare werden mit `/* ... */` begrenzt\n"
+"* Schlüsselwörter (keywords) wie `if` und `while` funktionieren gleich.\n"
"* Variablenzuweisung erfolgt mit `=`, Vergleich erfolgt mit `==`."
#: src/basic-syntax/scalar-types.md:1
-#, fuzzy
msgid "# Scalar Types"
msgstr "# Skalare Typen"
#: src/basic-syntax/scalar-types.md:3
-#, fuzzy
msgid ""
"| | Types | "
"Literals |\n"
@@ -2462,34 +2579,32 @@ msgid ""
"`10u16` |\n"
"| Floating point numbers | `f32`, `f64` | `3.14`, `-10.0e20`, "
"`2f32` |\n"
-"| Strings | `&str` | `\"foo\"`, `r#\"\\\\"
-"\"#` |\n"
+"| Strings | `&str` | `\"foo\"`, "
+"`\"two\\nlines\"` |\n"
"| Unicode scalar values | `char` | `'a'`, `'α'`, "
"`'∞'` |\n"
-"| Byte strings | `&[u8]` | `b\"abc\"`, `br#\" \" "
-"\"#` |\n"
"| Booleans | `bool` | `true`, "
"`false` |"
msgstr ""
"| | Typen | Literale |\n"
-"|------------------------|------------------------ "
-"--------------------|------------------------------------- --|\n"
-"| Ganzzahlen mit Vorzeichen | „i8“, „i16“, „i32“, „i64“, „i128“, „Größe“ | „-10“, „0“, „1_000“, "
-"„123i64“ |\n"
-"| Ganzzahlen ohne Vorzeichen | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, `10u16` |\n"
-"| Fließkommazahlen | „f32“, „f64“ | `3.14`, `-10.0e20`, `2f32` |\n"
-"| Saiten | `&str` | `\"foo\"`, `r#\"\\\\\"#` |\n"
-"| Unicode-Skalarwerte | \"char\" | `'a'`, `'α'`, `'∞'` |\n"
-"| Byte-Strings | `&[u8]` | `b\"abc\"`, `br#\" \" \"#` |\n"
-"| Boolesche Werte | „Bool“ | „wahr“, „falsch“ |"
+"|------------------------|--------------------------------------------|---------------------------------------|\n"
+"| Ganzzahlen mit Vorzeichen | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `-10`, `0`, `1_000`, "
+"`123i64` |\n"
+"| Ganzzahlen ohne Vorzeichen `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, "
+"`10u16` |\n"
+"| Fließkommazahlen | `f32`, `f64` | `3.14`, `-10.0e20`, `2f32` |\n"
+"| Zeichenketten (Strings) | `&str` | `\"foo\"`, "
+"`\"two\\nlines\"` |\n"
+"| Unicode-Skalarwerte | `char` | `'a'`, `'α'`, "
+"`'∞'` \n"
+"| Wahrheitswerte (booleans) | `bool` | `true`, "
+"`false` |"
-#: src/basic-syntax/scalar-types.md:13
-#, fuzzy
+#: src/basic-syntax/scalar-types.md:12
msgid "The types have widths as follows:"
msgstr "Die Typen haben folgende Breiten:"
-#: src/basic-syntax/scalar-types.md:15
-#, fuzzy
+#: src/basic-syntax/scalar-types.md:14
msgid ""
"* `iN`, `uN`, and `fN` are _N_ bits wide,\n"
"* `isize` and `usize` are the width of a pointer,\n"
@@ -2501,8 +2616,53 @@ msgstr ""
"* `char` ist 32 Bit breit,\n"
"* `bool` ist 8 Bit breit."
+#: src/basic-syntax/scalar-types.md:21
+msgid "There are a few syntaxes which are not shown above:"
+msgstr "Es gibt einige Syntaxen, die oben nicht aufgeführt sind:"
+
+#: src/basic-syntax/scalar-types.md:23
+msgid ""
+"- Raw strings allow you to create a `&str` value with escapes disabled: `r\"\\n\"\n"
+" == \"\\\\\\\\n\"`. You can embed double-quotes by using an equal amount of `#` on\n"
+" either side of the quotes:\n"
+"\n"
+" ```rust,editable\n"
+" fn main() {\n"
+" println!(r#\"link\"#);\n"
+" println!(\"link\");\n"
+" }\n"
+" ```\n"
+"\n"
+"- Byte strings allow you to create a `&[u8]` value directly:\n"
+"\n"
+" ```rust,editable\n"
+" fn main() {\n"
+" println!(\"{:?}\", b\"abc\");\n"
+" println!(\"{:?}\", &[97, 98, 99]);\n"
+" }\n"
+" ```"
+msgstr ""
+"- Mit puren Zeichenketten (raw strings) können Sie einen `&str`-Wert mit deaktivierten Escape-"
+"Zeichen erstellen: `r\"\\n\" == \"\\\\\\\\n\"`. Sie können doppelte Anführungszeichen einbetten, "
+"indem Sie auf beiden Seiten der Anführungszeichen die gleiche Anzahl von `#` verwenden:\n"
+"\n"
+" ```rust,editable\n"
+" fn main() {\n"
+" println!(r#\"link\"#);\n"
+" println!(\"link\");\n"
+" }\n"
+" ```\n"
+"\n"
+"- Mit Byte-Strings können Sie direkt einen „&[u8]“-Wert erstellen:\n"
+"\n"
+" ```rust,editable\n"
+" fn main() {\n"
+" println!(\"{:?}\", b\"abc\");\n"
+" println!(\"{:?}\", &[97, 98, 99]);\n"
+" }\n"
+" ```"
+
#: src/basic-syntax/compound-types.md:1
-#, fuzzy
msgid "# Compound Types"
msgstr "# Verbundtypen"
@@ -2513,9 +2673,12 @@ msgid ""
"| Arrays | `[T; N]` | `[20, 30, 40]`, `[0; 3]` |\n"
"| Tuples | `()`, `(T,)`, `(T1, T2)`, ... | `()`, `('x',)`, `('x', 1.2)`, ... |"
msgstr ""
+"| | Typen | Literale |\n"
+"|--------|-------------------------------|-----------------------------------|\n"
+"| Arrays | `[T; N]` | `[20, 30, 40]`, `[0; 3]` |\n"
+"| Tupel | `()`, `(T,)`, `(T1, T2)`, ... | `()`, `('x',)`, `('x', 1.2)`, ... |"
#: src/basic-syntax/compound-types.md:8
-#, fuzzy
msgid "Array assignment and access:"
msgstr "Array-Zuordnung und Zugriff:"
@@ -2531,9 +2694,8 @@ msgid ""
msgstr ""
#: src/basic-syntax/compound-types.md:18
-#, fuzzy
msgid "Tuple assignment and access:"
-msgstr "Tupelzuweisung und Zugriff:"
+msgstr "Tupel-Zuweisung und Zugriff:"
#: src/basic-syntax/compound-types.md:20
msgid ""
@@ -2547,7 +2709,6 @@ msgid ""
msgstr ""
#: src/basic-syntax/compound-types.md:32
-#, fuzzy
msgid "Arrays:"
msgstr "Arrays:"
@@ -2566,14 +2727,24 @@ msgid ""
"\n"
"* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read."
msgstr ""
+"* Arrays haben Elemente desselben Typs `T` und der Länge `N`, was eine Konstante zur "
+"Kompilierungszeit ist. Beachten Sie, dass die Länge des Arrays *Teil seines Typs* ist, was "
+"bedeutet, dass `[u8; 3]` und `[u8; 4]` als zwei verschiedene Typen betrachtet werden.\n"
+"\n"
+"* Wir können Literale verwenden, um Arrays Werte zuzuweisen.\n"
+"\n"
+"* In der `main`-Funktion fragt die print-Anweisung mit dem Formatparameter `?` nach der Debug-"
+"Implementierung: `{}` gibt die Standardausgabe aus, „{:?}“ gibt die Debug-Ausgabe aus. Wir hätten "
+"auch `{a}` und `{a:?}` verwenden können, ohne den Wert nach der Formatzeichenfolge anzugeben.\n"
+"\n"
+"* Das Hinzufügen von `#`, z. B. `{a:#?}`, ruft ein „hübsches Druckformat“ (pretty print) auf, das "
+"einfacher zu lesen ist."
#: src/basic-syntax/compound-types.md:47
-#, fuzzy
msgid "Tuples:"
msgstr "Tupel:"
#: src/basic-syntax/compound-types.md:49
-#, fuzzy
msgid ""
"* Like arrays, tuples have a fixed length.\n"
"\n"
@@ -2588,21 +2759,25 @@ msgid ""
" * You can think of it as `void` that can be familiar to you from other \n"
" programming languages."
msgstr ""
-"* Das leere Tupel `()` ist auch als \"Einheitstyp\" bekannt. Es ist sowohl ein Typ als auch\n"
-" der einzig gültige Wert dieses Typs - also sowohl der Typ als auch sein Wert\n"
-" werden als `()` ausgedrückt. Es wird zum Beispiel verwendet, um anzuzeigen, dass eine Funktion "
-"oder\n"
-" Ausdruck hat keinen Rückgabewert, wie wir auf einer zukünftigen Folie sehen werden.\n"
-" * Sie können es sich als „Leere“ vorstellen, die Ihnen von anderen bekannt sein kann\n"
-" Programmiersprachen."
+"* Wie Arrays haben Tupel eine feste Länge.\n"
+"\n"
+"* Tupel gruppieren Werte unterschiedlicher Typen zu einem zusammengesetzten Typ.\n"
+"\n"
+"* Auf Felder eines Tupels kann durch einen Punkt gefolgt von dem Index des Werts zugegriffen "
+"werden, z. B. „t.0“, „t.1“.\n"
+"\n"
+"* Das leere Tupel „()“ wird auch als „Einheitstyp“ (unit type) bezeichnet. Es ist sowohl ein Typ "
+"als auch der einzige gültige Wert dieses Typs – das heißt, sowohl der Typ als auch sein Wert "
+"werden als `()` ausgedrückt. Es wird beispielsweise verwendet, um anzuzeigen, dass eine Funktion "
+"oder ein Ausdruck keinen Rückgabewert hat, wie wir auf einer zukünftigen Folie sehen werden.\n"
+" * Sie können es sich als `void` vorstellen, das Ihnen aus anderen Programmiersprachen bekannt "
+"sein kann."
#: src/basic-syntax/references.md:1
-#, fuzzy
msgid "# References"
msgstr "# Verweise"
#: src/basic-syntax/references.md:3
-#, fuzzy
msgid "Like C++, Rust has references:"
msgstr "Wie C++ hat Rust Referenzen:"
@@ -2619,51 +2794,40 @@ msgid ""
msgstr ""
#: src/basic-syntax/references.md:14
-#, fuzzy
msgid "Some notes:"
msgstr "Einige Notizen:"
#: src/basic-syntax/references.md:16
-#, fuzzy
msgid ""
"* We must dereference `ref_x` when assigning to it, similar to C and C++ pointers.\n"
"* Rust will auto-dereference in some cases, in particular when invoking\n"
" methods (try `ref_x.count_ones()`).\n"
"* References that are declared as `mut` can be bound to different values over their lifetime."
msgstr ""
-"* Wir müssen `ref_x` beim Zuweisen dereferenzieren, ähnlich wie bei C- und C++-Zeigern.\n"
-"* Rust wird in einigen Fällen automatisch dereferenzieren, insbesondere beim Aufrufen\n"
-" Methoden (probieren Sie `ref_x.count_ones()`).\n"
+"* Wir müssen `ref_x` beim Zuweisen dereferenzieren, ähnlich wie bei C und C++-Zeigern.\n"
+"* Rust wird in einigen Fällen automatisch dereferenzieren, insbesondere beim Aufrufen von Methoden "
+"(probieren Sie `ref_x.count_ones()`).\n"
"* Referenzen, die als `mut` deklariert sind, können über ihre Lebensdauer an unterschiedliche "
"Werte gebunden werden."
-#: src/basic-syntax/references.md:21
-#, fuzzy
-msgid ""
-"\n"
-"Key points:"
-msgstr "Kernpunkte:"
-
-#: src/basic-syntax/references.md:24
-#, fuzzy
+#: src/basic-syntax/references.md:25
msgid ""
"* Be sure to note the difference between `let mut ref_x: &i32` and `let ref_x:\n"
" &mut i32`. The first one represents a mutable reference which can be bound to\n"
" different values, while the second represents a reference to a mutable value."
msgstr ""
"* Beachten Sie unbedingt den Unterschied zwischen `let mut ref_x: &i32` und `let ref_x:\n"
-" &mut i32`. Der erste stellt eine veränderliche Referenz dar, an die gebunden werden kann\n"
-" unterschiedliche Werte, während der zweite einen Verweis auf einen veränderlichen Wert darstellt."
+" &mut i32`. Das erste stellt eine veränderliche Referenz (mutable reference) dar, an die "
+"unterschiedliche Werte gebunden werden können,\n"
+" während das zweite Beispiel einen Verweis auf einen veränderlichen Wert darstellt."
#: src/basic-syntax/references-dangling.md:1
-#, fuzzy
msgid "# Dangling References"
-msgstr "# Dangling-Referenzen"
+msgstr "# Hängende-Referenzen (dangling references)"
#: src/basic-syntax/references-dangling.md:3
-#, fuzzy
msgid "Rust will statically forbid dangling references:"
-msgstr "Rust wird baumelnde Referenzen statisch verbieten:"
+msgstr "Rust verbietet hängende Referenzen statisch:"
#: src/basic-syntax/references-dangling.md:5
msgid ""
@@ -2680,27 +2844,24 @@ msgid ""
msgstr ""
#: src/basic-syntax/references-dangling.md:16
-#, fuzzy
msgid ""
"* A reference is said to \"borrow\" the value it refers to.\n"
"* Rust is tracking the lifetimes of all references to ensure they live long\n"
" enough.\n"
"* We will talk more about borrowing when we get to ownership."
msgstr ""
-"* Eine Referenz soll den Wert, auf den sie sich bezieht, \"leihen\".\n"
-"* Rust verfolgt die Lebensdauer aller Referenzen, um sicherzustellen, dass sie lange leben\n"
-" genug.\n"
-"* Wir werden mehr über das Ausleihen sprechen, wenn wir zum Eigentum kommen."
+"* Eine Referenz \"leiht\" (borrows) sich den Wert, auf den sie sich bezieht, .\n"
+"* Rust verfolgt die Lebensdauer aller Referenzen, um sicherzustellen, dass sie lange genug leben\n"
+"* Wir werden mehr über das Ausleihen (borrowing) sprechen, wenn wir zum Eigentum (ownership) "
+"kommen."
#: src/basic-syntax/slices.md:1
-#, fuzzy
msgid "# Slices"
-msgstr "# Scheiben"
+msgstr "# Anteilstypen (Slices)"
#: src/basic-syntax/slices.md:3
-#, fuzzy
msgid "A slice gives you a view into a larger collection:"
-msgstr "Ein Slice gibt Ihnen einen Einblick in eine größere Sammlung:"
+msgstr "Ein Anteilstyp (slice) gibt Ihnen einen Einblick in eine größere Sammlung (collection):"
#: src/basic-syntax/slices.md:5
msgid ""
@@ -2716,16 +2877,14 @@ msgid ""
msgstr ""
#: src/basic-syntax/slices.md:15
-#, fuzzy
msgid ""
"* Slices borrow data from the sliced type.\n"
"* Question: What happens if you modify `a[3]`?"
msgstr ""
-"* Slices borgen Daten vom Sliced-Typ.\n"
+"* Anteilstypen (slices) borgen (borrow) Daten vom Sliced-Typ.\n"
"* Frage: Was passiert, wenn Sie `a[3]` ändern?"
#: src/basic-syntax/slices.md:20
-#, fuzzy
msgid ""
"* We create a slice by borrowing `a` and specifying the starting and ending indexes in brackets.\n"
"\n"
@@ -2748,23 +2907,34 @@ msgid ""
"and `s` safely. \n"
" More details will be explained in the borrow checker section."
msgstr ""
-"* `s` ist ein Verweis auf einen Slice von `i32`s. Beachten Sie, dass der Typ von `s` (`&[i32]`) "
-"die Array-Länge nicht mehr erwähnt. Dies ermöglicht es uns, Berechnungen für Scheiben "
-"unterschiedlicher Größe durchzuführen.\n"
-" \n"
-"* Slices leihen sich immer von einem anderen Objekt. In diesem Beispiel muss „a“ mindestens so "
-"lange „lebendig“ (im Geltungsbereich) bleiben wie unser Slice.\n"
+"* Wir erstellen ein Anteilstyp, indem wir `a` ausleihen (borrow) und den Start- und Endindex in "
+"Klammern angeben.\n"
+"\n"
+"* Wenn der Anteilstyp bei Index 0 beginnt, erlaubt uns die Range-Syntax von Rust, den Startindex "
+"wegzulassen, was bedeutet, dass `&a[0..a.len()]` und `&a[..a.len()]` identisch sind.\n"
" \n"
-"* Die Frage nach dem Modifizieren von `a[3]` kann eine interessante Diskussion auslösen, aber die "
-"Antwort ist aus Gründen der Speichersicherheit\n"
-" Sie können dies nicht über `a` tun, nachdem Sie einen Slice erstellt haben, aber Sie können die "
-"Daten sowohl von `a` als auch von `s` sicher lesen.\n"
-" Weitere Details werden im Abschnitt zum Ausleihen von Prüfern erklärt."
+"* Das Gleiche gilt für den letzten Index, daher sind `&a[2..a.len()]` und `&a[2..]` identisch.\n"
+"\n"
+"* Um einfach einen Anteilstyp des gesamten Arrays zu erstellen, können wir daher „&a[..]“ "
+"verwenden.\n"
+"\n"
+"* `s` ist ein Verweis (reference) auf einen Teil von `i32`. Beachten Sie, dass der Typ `s` "
+"(`&[i32]`) die Array-Länge nicht mehr erwähnt. Dadurch können wir Berechnungen für Anteilstypen "
+"unterschiedlicher Größe durchführen.\n"
+" \n"
+"* Anteilstypen (slices) leihen (borrow) sich immer etwas von einem anderen Objekt aus. In diesem "
+"Beispiel muss `a` mindestens so lange (im Gültigkeitsbereich (scope)) „lebendig“ bleiben wie unser "
+"Anteilstyp.\n"
+" \n"
+"* Die Frage nach einer Werteänderung durch `a[3]` kann eine interessante Diskussion auslösen, aber "
+"die Antwort lautet: aus Gründen der Speichersicherheit können Sie dies nicht über `a` tun, nachdem "
+"Sie ein Slice erstellt haben. Allerdings können Sie die Werte sowohl von `a` als auch von `s` "
+"sicher lesen.\n"
+" Weitere Einzelheiten werden im Abschnitt „Ausleihenprüfer“ (borrow checken) erläutert."
#: src/basic-syntax/string-slices.md:1
-#, fuzzy
msgid "# `String` vs `str`"
-msgstr "# `String` gegen `str`"
+msgstr "# `String` vs `str`"
#: src/basic-syntax/string-slices.md:3
#, fuzzy
@@ -2856,44 +3026,35 @@ msgstr ""
"Eine Rust-Version der berühmten [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz) Interviewfrage:"
#: src/basic-syntax/functions.md:5
-#, fuzzy
msgid ""
"```rust,editable\n"
"fn main() {\n"
-" fizzbuzz_to(20); // Defined below, no forward declaration needed\n"
+" print_fizzbuzz_to(20);\n"
"}\n"
"\n"
-"fn is_divisible_by(lhs: u32, rhs: u32) -> bool {\n"
-" if rhs == 0 {\n"
-" return false; // Corner case, early return\n"
+"fn is_divisible(n: u32, divisor: u32) -> bool {\n"
+" if divisor == 0 {\n"
+" return false;\n"
" }\n"
-" lhs % rhs == 0 // The last expression in a block is the return value\n"
+" n % divisor == 0\n"
"}\n"
"\n"
-"fn fizzbuzz(n: u32) -> () { // No return value means returning the unit type `()`\n"
-" match (is_divisible_by(n, 3), is_divisible_by(n, 5)) {\n"
-" (true, true) => println!(\"fizzbuzz\"),\n"
-" (true, false) => println!(\"fizz\"),\n"
-" (false, true) => println!(\"buzz\"),\n"
-" (false, false) => println!(\"{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 fizzbuzz_to(n: u32) { // `-> ()` is normally omitted\n"
+"fn print_fizzbuzz_to(n: u32) {\n"
" for i in 1..=n {\n"
-" fizzbuzz(i);\n"
+" println!(\"{}\", fizzbuzz(i));\n"
" }\n"
"}\n"
"```"
msgstr ""
-"fn fizzbuzz(n: u32) -> () { // Kein Rückgabewert bedeutet Rückgabe des Einheitentyps `()`\n"
-" Übereinstimmung (ist_teilbar_durch(n, 3), ist_teilbar_durch(n, 5)) {\n"
-" (true, true) => println!(\"fizzbuzz\"),\n"
-" (wahr, falsch) => println!(\"fizz\"),\n"
-" (falsch, wahr) => println!(\"summen\"),\n"
-" (falsch, falsch) => println!(\"{n}\"),\n"
-" }\n"
-"}"
#: src/basic-syntax/functions.md:35
msgid ""
@@ -2905,22 +3066,8 @@ msgid ""
"`;` at the end of the expression.\n"
"* Some functions have no return value, and return the 'unit type', `()`. The compiler will infer "
"this if the `-> ()` return type is omitted.\n"
-"* The range expression in the `for` loop in `fizzbuzz_to()` contains `=n`, which causes it to "
-"include the upper bound.\n"
-"* The `match` expression in `fizzbuzz()` is doing a lot of work. It is expanded below to show what "
-"is happening.\n"
-"\n"
-" (Type annotations added for clarity, but they can be elided.)\n"
-"\n"
-" ```rust,ignore\n"
-" let by_3: bool = is_divisible_by(n, 3);\n"
-" let by_5: bool = is_divisible_by(n, 5);\n"
-" let by_35: (bool, bool) = (by_3, by_5);\n"
-" match by_35 {\n"
-" // ...\n"
-" ```\n"
-"\n"
-" "
+"* The range expression in the `for` loop in `print_fizzbuzz_to()` contains `=n`, which causes it "
+"to include the upper bound."
msgstr ""
#: src/basic-syntax/rustdoc.md:1
@@ -2975,8 +3122,8 @@ msgstr "# Methoden"
#: src/basic-syntax/methods.md:3
#, fuzzy
msgid ""
-"Rust has methods, they are simply functions that are associated with a particular type. The\n"
-"first argument of a method is an instance of the type it is associated with:"
+"Methods are functions associated with a type. The `self` argument of a method is\n"
+"an instance of the type it is associated with:"
msgstr ""
"Rust hat Methoden, das sind einfach Funktionen, die einem bestimmten Typ zugeordnet sind. Der\n"
"Das erste Argument einer Methode ist eine Instanz des Typs, dem sie zugeordnet ist:"
@@ -3014,6 +3161,20 @@ msgid "* We will look much more at methods in today's exercise and in tomorrow's
msgstr ""
"* Wir werden uns in der heutigen Übung und im morgigen Unterricht viel mehr mit Methoden befassen."
+#: src/basic-syntax/methods.md:34
+msgid ""
+"- Add a `Rectangle::new` constructor and call this from `main`:\n"
+"\n"
+" ```rust,editable,compile_fail\n"
+" fn new(width: u32, height: u32) -> Rectangle {\n"
+" Rectangle { width, height }\n"
+" }\n"
+" ```\n"
+"\n"
+"- Add a `Rectangle::new_square(width: u32)` constructor to illustrate that\n"
+" constructors can take arbitrary parameters."
+msgstr ""
+
#: src/basic-syntax/functions-interlude.md:1
#, fuzzy
msgid "# Function Overloading"
@@ -3070,11 +3231,6 @@ msgstr ""
"bieten\n"
" Polymorphismus auf Argumenttypen. Wir werden mehr Details in einem späteren Abschnitt sehen."
-#: src/basic-syntax/functions-interlude.md:30
-#, fuzzy
-msgid ""
-msgstr ""
-
#: src/exercises/day-1/morning.md:1
#, fuzzy
msgid "# Day 1: Morning Exercises"
@@ -3124,8 +3280,9 @@ 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/day-4/morning.md:12
-#: src/exercises/bare-metal/morning.md:7 src/exercises/bare-metal/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/concurrency/morning.md:12
+#: src/exercises/concurrency/afternoon.md:13
#, fuzzy
msgid "After looking at the exercises, you can look at the [solutions] provided."
msgstr ""
@@ -3555,7 +3712,7 @@ msgstr ""
#: src/basic-syntax/static-and-const.md:27
#, fuzzy
-msgid "According the the [Rust RFC Book][1] these are inlined upon use."
+msgid "According to the [Rust RFC Book][1] these are inlined upon use."
msgstr "Gemäß dem [Rust RFC Book][1] werden diese bei der Verwendung eingefügt."
#: src/basic-syntax/static-and-const.md:29
@@ -4663,14 +4820,17 @@ msgstr "Ein geliehener Wert hat eine _Lebensdauer_:"
#: src/ownership/lifetimes.md:5
msgid ""
-"* The lifetime can be elided: `add(p1: &Point, p2: &Point) -> Point`.\n"
+"* The lifetime can be implicit: `add(p1: &Point, p2: &Point) -> Point`.\n"
"* Lifetimes can also be explicit: `&'a Point`, `&'document str`.\n"
"* Read `&'a Point` as \"a borrowed `Point` which is valid for at least the\n"
" lifetime `a`\".\n"
"* Lifetimes are always inferred by the compiler: you cannot assign a lifetime\n"
" yourself.\n"
" * Lifetime annotations create constraints; the compiler verifies that there is\n"
-" a valid solution."
+" a valid solution.\n"
+"* Lifetimes for function arguments and return values must be fully specified,\n"
+" but Rust allows these to be elided in most cases with [a few simple\n"
+" rules](https://doc.rust-lang.org/nomicon/lifetime-elision.html)."
msgstr ""
#: src/ownership/lifetimes-function-calls.md:1
@@ -4722,7 +4882,7 @@ msgstr ""
#: src/ownership/lifetimes-function-calls.md:31
#, fuzzy
msgid ""
-"* Move the declaration of `p2` and `p3` into a a new scope (`{ ... }`), resulting in the following "
+"* Move the declaration of `p2` and `p3` into a new scope (`{ ... }`), resulting in the following "
"code:\n"
" ```rust,ignore\n"
" #[derive(Debug)]\n"
@@ -4751,8 +4911,8 @@ msgid ""
" * Two references to two values are borrowed by a function and the function returns\n"
" another reference.\n"
" * It must have come from one of those two inputs (or from a global variable).\n"
-" * Which one is it? The compiler needs to to know, so at the call site the returned reference is "
-"not used\n"
+" * Which one is it? The compiler needs to know, so at the call site the returned reference is not "
+"used\n"
" for longer than a variable from where the reference came from."
msgstr ""
"* Setzen Sie den Arbeitsbereich zurück und ändern Sie die Funktionssignatur zu `fn left_most<'a, "
@@ -4865,15 +5025,16 @@ msgid ""
"fn main() {\n"
" let mut vec = vec![10, 20];\n"
" vec.push(30);\n"
-" println!(\"middle value: {}\", vec[vec.len() / 2]);\n"
-" for item in vec.iter() {\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:17
+#: src/exercises/day-1/book-library.md:18
#, fuzzy
msgid ""
"Use this to create a library application. Copy the code below to\n"
@@ -4883,10 +5044,9 @@ msgstr ""
"nach\n"
" und aktualisieren Sie die Typen, damit es kompiliert wird:"
-#: src/exercises/day-1/book-library.md:20
+#: src/exercises/day-1/book-library.md:21
msgid ""
"```rust,should_panic\n"
-"\n"
"struct Library {\n"
" books: Vec,\n"
"}\n"
@@ -4906,36 +5066,35 @@ msgid ""
" }\n"
"}\n"
"\n"
-"// This makes it possible to print Book values with {}.\n"
-"impl std::fmt::Display for Book {\n"
-" fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n"
-" write!(f, \"{} ({})\", self.title, self.year)\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"
-" unimplemented!()\n"
+" todo!(\"Initialize and return a `Library` value\")\n"
" }\n"
"\n"
" //fn len(self) -> usize {\n"
-" // unimplemented!()\n"
+" // todo!(\"Return the length of `self.books`\")\n"
" //}\n"
"\n"
" //fn is_empty(self) -> bool {\n"
-" // unimplemented!()\n"
+" // todo!(\"Return `true` if `self.books` is empty\")\n"
" //}\n"
"\n"
" //fn add_book(self, book: Book) {\n"
-" // unimplemented!()\n"
+" // todo!(\"Add a new book to `self.books`\")\n"
" //}\n"
"\n"
" //fn print_books(self) {\n"
-" // unimplemented!()\n"
+" // todo!(\"Iterate over `self.books` and each book's title and year\")\n"
" //}\n"
"\n"
" //fn oldest_book(self) -> Option<&Book> {\n"
-" // unimplemented!()\n"
+" // todo!(\"Return a reference to the oldest book (if any)\")\n"
" //}\n"
"}\n"
"\n"
@@ -4946,29 +5105,28 @@ msgid ""
"fn main() {\n"
" let library = Library::new();\n"
"\n"
-" //println!(\"Our library is empty: {}\", library.is_empty());\n"
-"\n"
-" let favorite_book = Book::new(\"Lord of the Rings\", 1954);\n"
-" println!(\"Our favorite book {favorite_book} should go in the library\");\n"
-" //library.add_book(favorite_book);\n"
+" //println!(\"The 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());\n"
+" //\n"
+" //\n"
" //library.print_books();\n"
" //\n"
" //match library.oldest_book() {\n"
-" // Some(book) => println!(\"My oldest book is {book}\"),\n"
-" // None => println!(\"My library is empty!\"),\n"
+" // Some(book) => println!(\"The oldest book is {}\", book.title),\n"
+" // None => println!(\"The library is empty!\"),\n"
" //}\n"
" //\n"
-" //println!(\"Our library has {} books\", library.len());\n"
-" for book in library.books {\n"
-" println!(\"{book}\");\n"
-" }\n"
+" //println!(\"The library has {} books\", library.len());\n"
+" //library.print_books();\n"
"}\n"
"```"
msgstr ""
-#: src/exercises/day-1/book-library.md:104
+#: src/exercises/day-1/book-library.md:102
#, fuzzy
msgid "[Solution](solutions-afternoon.md#designing-a-library)"
msgstr "[Lösung](solutions-afternoon.md#designing-a-library)"
@@ -5251,14 +5409,14 @@ msgid ""
"```"
msgstr ""
-#: src/structs.md:29
+#: src/structs.md:31 src/enums.md:34 src/enums/sizes.md:29 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:42
#, fuzzy
-msgid ""
-"\n"
-"Key Points: "
+msgid "Key Points:"
msgstr "Wichtige Punkte:"
-#: src/structs.md:32
+#: src/structs.md:33
msgid ""
"* Structs work like in C or C++.\n"
" * Like in C++, and unlike in C, no typedef is needed to define a type.\n"
@@ -5302,10 +5460,10 @@ msgstr "Dies wird häufig für Einzelfeld-Wrapper (genannt Newtypes) verwendet:"
#: src/structs/tuple-structs.md:16
msgid ""
"```rust,editable,compile_fail\n"
-"struct PoundOfForce(f64);\n"
+"struct PoundsOfForce(f64);\n"
"struct Newtons(f64);\n"
"\n"
-"fn compute_thruster_force() -> PoundOfForce {\n"
+"fn compute_thruster_force() -> PoundsOfForce {\n"
" todo!(\"Ask a rocket scientist at NASA\")\n"
"}\n"
"\n"
@@ -5440,6 +5598,7 @@ msgstr ""
msgid ""
"```rust,editable\n"
"fn generate_random_number() -> i32 {\n"
+" // Implementation based on https://xkcd.com/221/\n"
" 4 // Chosen by fair dice roll. Guaranteed to be random.\n"
"}\n"
"\n"
@@ -5464,13 +5623,7 @@ msgid ""
"```"
msgstr ""
-#: src/enums.md:33 src/enums/sizes.md:29 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:42
-#, fuzzy
-msgid "Key Points:"
-msgstr "Wichtige Punkte:"
-
-#: src/enums.md:35
+#: src/enums.md:36
#, fuzzy
msgid ""
"* Enumerations allow you to collect a set of values under one type\n"
@@ -5829,9 +5982,8 @@ msgid ""
"* `self`: takes ownership of the object and moves it away from the caller. The\n"
" method becomes the owner of the object. The object will be dropped (deallocated)\n"
" when the method returns, unless its ownership is explicitly\n"
-" transmitted.\n"
-"* `mut self`: same as above, but while the method owns the object, it can\n"
-" mutate it too. Complete ownership does not automatically mean mutability.\n"
+" transmitted. Complete ownership does not automatically mean mutability.\n"
+"* `mut self`: same as above, but the method can mutate the object. \n"
"* No receiver: this becomes a static method on the struct. Typically used to\n"
" create constructors which are called `new` by convention."
msgstr ""
@@ -5848,7 +6000,7 @@ msgstr ""
"* Kein Empfänger: Dies wird zu einer statischen Methode für die Struktur. Typischerweise gewohnt\n"
" Erstellen Sie Konstruktoren, die per Konvention \"neu\" genannt werden."
-#: src/methods/receiver.md:19
+#: src/methods/receiver.md:18
#, fuzzy
msgid ""
"Beyond variants on `self`, there are also\n"
@@ -5859,7 +6011,7 @@ msgstr ""
"[spezielle Wrapper-Typen](https://doc.rust-lang.org/reference/special-types-and-traits.html)\n"
"dürfen Empfängertypen sein, wie z. B. `Box`."
-#: src/methods/receiver.md:25
+#: src/methods/receiver.md:24
#, fuzzy
msgid ""
"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". These constraints always "
@@ -6117,7 +6269,10 @@ msgstr ""
#: src/pattern-matching/destructuring-structs.md:23
msgid ""
"* Change the literal values in `foo` to match with the other patterns.\n"
-"* Add a new field to `Foo` and make changes to the pattern as needed."
+"* Add a new field to `Foo` and make changes to the pattern as needed.\n"
+"* The distinction between a capture and a constant expression can be hard to\n"
+" spot. Try changing the `2` in the second arm to a variable, and see that it subtly\n"
+" doesn't work. Change it to a `const` and see it working again."
msgstr ""
#: src/pattern-matching/destructuring-arrays.md:1
@@ -6596,11 +6751,13 @@ msgid "# `if` expressions"
msgstr "# `if`-Ausdrücke"
#: src/control-flow/if-expressions.md:3
-#, fuzzy
-msgid "You use `if` very similarly to how you would in other languages:"
-msgstr "Sie verwenden \"if\" sehr ähnlich wie in anderen Sprachen:"
+msgid ""
+"You use [`if`\n"
+"expressions](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-expressions)\n"
+"exactly like `if` statements in other languages:"
+msgstr ""
-#: src/control-flow/if-expressions.md:5
+#: src/control-flow/if-expressions.md:7
msgid ""
"```rust,editable\n"
"fn main() {\n"
@@ -6614,12 +6771,14 @@ msgid ""
"```"
msgstr ""
-#: src/control-flow/if-expressions.md:16
+#: src/control-flow/if-expressions.md:18
#, fuzzy
-msgid "In addition, you can use it as an expression. This does the same as above:"
+msgid ""
+"In addition, you can use `if` as an expression. The last expression of each\n"
+"block becomes the value of the `if` expression:"
msgstr "Darüber hinaus können Sie es als Ausdruck verwenden. Das macht dasselbe wie oben:"
-#: src/control-flow/if-expressions.md:18
+#: src/control-flow/if-expressions.md:22
msgid ""
"```rust,editable\n"
"fn main() {\n"
@@ -6633,7 +6792,7 @@ msgid ""
"```"
msgstr ""
-#: src/control-flow/if-expressions.md:31
+#: 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."
@@ -6645,11 +6804,13 @@ msgid "# `if let` expressions"
msgstr "# `if let`-Ausdrücke"
#: src/control-flow/if-let-expressions.md:3
-#, fuzzy
-msgid "If you want to match a value against a pattern, you can use `if let`:"
-msgstr "Wenn Sie einen Wert mit einem Muster abgleichen möchten, können Sie `if let` verwenden:"
+msgid ""
+"The [`if let`\n"
+"expression](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-let-expressions)\n"
+"lets you execute different code depending on whether a value matches a pattern:"
+msgstr ""
-#: src/control-flow/if-let-expressions.md:5
+#: src/control-flow/if-let-expressions.md:7
msgid ""
"```rust,editable\n"
"fn main() {\n"
@@ -6663,8 +6824,8 @@ msgid ""
"```"
msgstr ""
-#: src/control-flow/if-let-expressions.md:16 src/control-flow/while-let-expressions.md:21
-#: src/control-flow/match-expressions.md:22
+#: src/control-flow/if-let-expressions.md:18 src/control-flow/while-let-expressions.md:21
+#: src/control-flow/match-expressions.md:23
#, fuzzy
msgid ""
"See [pattern matching](../pattern-matching.md) for more details on patterns in\n"
@@ -6673,7 +6834,7 @@ msgstr ""
"Siehe [pattern matching](../pattern-matching.md) für weitere Details zu Mustern in\n"
"Rost."
-#: src/control-flow/if-let-expressions.md:21
+#: src/control-flow/if-let-expressions.md:23
msgid ""
"* `if let` can be more concise than `match`, e.g., when only one case is interesting. In contrast, "
"`match` requires all branches to be covered.\n"
@@ -6699,15 +6860,17 @@ msgstr ""
#: src/control-flow/while-expressions.md:1
#, fuzzy
-msgid "# `while` expressions"
+msgid "# `while` loops"
msgstr "# `while`-Ausdrücke"
#: src/control-flow/while-expressions.md:3
-#, fuzzy
-msgid "The `while` keyword works very similar to other languages:"
-msgstr "Das Schlüsselwort „while“ funktioniert sehr ähnlich wie in anderen Sprachen:"
+msgid ""
+"The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-"
+"loops)\n"
+"works very similar to other languages:"
+msgstr ""
-#: src/control-flow/while-expressions.md:5
+#: src/control-flow/while-expressions.md:6
msgid ""
"```rust,editable\n"
"fn main() {\n"
@@ -6726,14 +6889,15 @@ msgstr ""
#: src/control-flow/while-let-expressions.md:1
#, fuzzy
-msgid "# `while let` expressions"
+msgid "# `while let` loops"
msgstr "# `while let`-Ausdrücke"
#: src/control-flow/while-let-expressions.md:3
#, fuzzy
msgid ""
-"Like with `if`, there is a `while let` variant which repeatedly tests a value\n"
-"against a pattern:"
+"Like with `if let`, there is a [`while let`](https://doc.rust-lang.org/reference/expressions/loop-"
+"expr.html#predicate-pattern-loops)\n"
+"variant which repeatedly tests a value against a pattern:"
msgstr ""
"Wie bei `if` gibt es eine `while let`-Variante, die einen Wert wiederholt testet\n"
"gegen ein Muster:"
@@ -6763,7 +6927,7 @@ msgstr ""
"Aufruf von `next()`. Es gibt `Some(x)` zurück, bis es fertig ist, danach wird es\n"
"gibt \"Keine\" zurück. Das `while let` lässt uns alle Elemente durchlaufen."
-#: src/control-flow/while-let-expressions.md:27
+#: src/control-flow/while-let-expressions.md:26
#, fuzzy
msgid ""
"* Point out that the `while let` loop will keep going as long as the value matches the pattern.\n"
@@ -6782,19 +6946,20 @@ msgstr ""
#: src/control-flow/for-expressions.md:1
#, fuzzy
-msgid "# `for` expressions"
-msgstr "# `for`-Ausdrücke"
+msgid "# `for` loops"
+msgstr "## `for`-Schleifen"
#: src/control-flow/for-expressions.md:3
#, fuzzy
msgid ""
-"The `for` expression is closely related to the `while let` expression. It will\n"
+"The [`for` loop](https://doc.rust-lang.org/std/keyword.for.html) is closely\n"
+"related to the [`while let` loop](while-let-expression.md). It will\n"
"automatically call `into_iter()` on the expression and then iterate over it:"
msgstr ""
"Der „for“-Ausdruck ist eng verwandt mit dem „while let“-Ausdruck. Es wird\n"
"Rufen Sie automatisch `into_iter()` für den Ausdruck auf und iterieren Sie dann darüber:"
-#: src/control-flow/for-expressions.md:6
+#: src/control-flow/for-expressions.md:7
msgid ""
"```rust,editable\n"
"fn main() {\n"
@@ -6811,12 +6976,12 @@ msgid ""
"```"
msgstr ""
-#: src/control-flow/for-expressions.md:20
+#: src/control-flow/for-expressions.md:21
#, fuzzy
msgid "You can use `break` and `continue` here as usual."
msgstr "Sie können hier wie gewohnt `break` und `continue` verwenden."
-#: src/control-flow/for-expressions.md:24
+#: src/control-flow/for-expressions.md:25
#, fuzzy
msgid ""
"* Index iteration is not a special syntax in Rust for just that case.\n"
@@ -6838,16 +7003,21 @@ msgid "# `loop` expressions"
msgstr "# `loop`-Ausdrücke"
#: src/control-flow/loop-expressions.md:3
-#, fuzzy
msgid ""
-"Finally, there is a `loop` keyword which creates an endless loop. Here you must\n"
-"either `break` or `return` to stop the loop:"
+"Finally, there is a [`loop` keyword](https://doc.rust-lang.org/reference/expressions/loop-expr."
+"html#infinite-loops)\n"
+"which creates an endless loop."
+msgstr ""
+
+#: src/control-flow/loop-expressions.md:6
+#, fuzzy
+msgid "Here you must either `break` or `return` to stop the loop:"
msgstr ""
"Schließlich gibt es noch ein „loop“-Schlüsselwort, das eine Endlosschleife erzeugt. Hier müssen "
"Sie\n"
"entweder `break` oder `return`, um die Schleife zu stoppen:"
-#: src/control-flow/loop-expressions.md:6
+#: src/control-flow/loop-expressions.md:8
msgid ""
"```rust,editable\n"
"fn main() {\n"
@@ -6867,8 +7037,12 @@ msgid ""
"```"
msgstr ""
-#: src/control-flow/loop-expressions.md:25
-msgid "* Break the `loop` with a value (e.g. `break 8`) and print it out."
+#: src/control-flow/loop-expressions.md:27
+msgid ""
+"* Break the `loop` with a value (e.g. `break 8`) and print it out.\n"
+"* Note that `loop` is the only looping construct which returns a non-trivial\n"
+" value. This is because it's guaranteed to be entered at least once (unlike\n"
+" `while` and `for` loops)."
msgstr ""
#: src/control-flow/match-expressions.md:1
@@ -6879,14 +7053,15 @@ msgstr "# `Match`-Ausdrücke"
#: src/control-flow/match-expressions.md:3
#, fuzzy
msgid ""
-"The `match` keyword is used to match a value against one or more patterns. In\n"
-"that sense, it works like a series of `if let` expressions:"
+"The [`match` keyword](https://doc.rust-lang.org/reference/expressions/match-expr.html)\n"
+"is used to match a value against one or more patterns. In that sense, it works\n"
+"like a series of `if let` expressions:"
msgstr ""
"Das Schlüsselwort „match“ wird verwendet, um einen Wert mit einem oder mehreren Mustern "
"abzugleichen. In\n"
"In diesem Sinne funktioniert es wie eine Reihe von `if let`-Ausdrücken:"
-#: src/control-flow/match-expressions.md:6
+#: src/control-flow/match-expressions.md:7
msgid ""
"```rust,editable\n"
"fn main() {\n"
@@ -6902,7 +7077,7 @@ msgid ""
"```"
msgstr ""
-#: src/control-flow/match-expressions.md:19
+#: src/control-flow/match-expressions.md:20
#, fuzzy
msgid ""
"Like `if let`, each match arm must have the same type. The type is the last\n"
@@ -6911,7 +7086,7 @@ msgstr ""
"Wie bei „if let“ muss jeder Match-Arm denselben Typ haben. Der Typ ist der letzte\n"
"Ausdruck des Blocks, falls vorhanden. Im obigen Beispiel ist der Typ `()`."
-#: src/control-flow/match-expressions.md:27
+#: src/control-flow/match-expressions.md:28
msgid ""
"* Save the match expression to a variable and print it out.\n"
"* Remove `.as_deref()` and explain the error.\n"
@@ -6928,11 +7103,19 @@ msgid "# `break` and `continue`"
msgstr "# `break` und `continue`"
#: 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),\n"
+"- If you want to immediately start\n"
+"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
#, fuzzy
msgid ""
-"If you want to exit a loop early, use `break`, if you want to immediately start\n"
-"the next iteration use `continue`. Both `continue` and `break` can optionally\n"
-"take a label argument which is used to break out of nested loops:"
+"Both `continue` and `break` can optionally take a label argument which is used\n"
+"to break out of nested loops:"
msgstr ""
"Wenn Sie eine Schleife vorzeitig verlassen möchten, verwenden Sie `break`, wenn Sie sofort "
"beginnen möchten\n"
@@ -6940,7 +7123,7 @@ msgstr ""
"optional verwendet werden\n"
"Nehmen Sie ein Label-Argument, das zum Ausbrechen aus verschachtelten Schleifen verwendet wird:"
-#: src/control-flow/break-continue.md:7
+#: src/control-flow/break-continue.md:10
msgid ""
"```rust,editable\n"
"fn main() {\n"
@@ -6961,7 +7144,7 @@ msgid ""
"```"
msgstr ""
-#: src/control-flow/break-continue.md:25
+#: src/control-flow/break-continue.md:28
#, fuzzy
msgid "In this case we break the outer loop after 3 iterations of the inner loop."
msgstr "In diesem Fall brechen wir die äußere Schleife nach 3 Iterationen der inneren Schleife."
@@ -7121,8 +7304,9 @@ msgid ""
" * Write and compare `let s3 = s1.deref();` and `let s3 = &*s1`;.\n"
"* `String` is implemented as a wrapper around a vector of bytes, many of the operations you see "
"supported on vectors are also supported on `String`, but with some extra guarantees.\n"
-"* Compare the different ways to index a `String` by using `s3[i]` and `s3.chars().nth(i).unwrap()` "
-"where `i` is in-bound, out-of-bounds, and \"on\" the flag Unicode character."
+"* Compare the different ways to index a `String`:\n"
+" * To a character by using `s3.chars().nth(i).unwrap()` where `i` is in-bound, out-of-bounds.\n"
+" * To a substring by using `s3[0..4]`, where that slice is on character boundaries or not."
msgstr ""
#: src/std/vec.md:1
@@ -7433,7 +7617,7 @@ msgid ""
"\n"
"fn main() {\n"
" let mut a = Rc::new(10);\n"
-" let mut b = a.clone();\n"
+" let mut b = Rc::clone(&a);\n"
"\n"
" println!(\"a: {a}\");\n"
" println!(\"b: {b}\");\n"
@@ -7457,18 +7641,18 @@ msgstr ""
#: src/std/rc.md:31
msgid ""
-"* `Rc`'s Count ensures that its contained value is valid for as long as there are references.\n"
+"* `Rc`'s count ensures that its contained value is valid for as long as there are references.\n"
"* Like C++'s `std::shared_ptr`.\n"
-"* `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.\n"
+"* `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.\n"
"* `make_mut` actually clones the inner value if necessary (\"clone-on-write\") and returns a "
"mutable reference.\n"
"* Use `Rc::strong_count` to check the reference count.\n"
"* 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.\n"
-"* You can `downgrade()` a `Rc` into a *weakly reference-counted* object to\n"
+"* `Rc::downgrade` gives you a *weakly reference-counted* object to\n"
" create cycles that will be dropped properly (likely in combination with\n"
" `RefCell`)."
msgstr ""
@@ -7644,6 +7828,20 @@ msgstr ""
" * `crate::foo` bezieht sich auf `foo` im Stammverzeichnis der aktuellen Kiste,\n"
" * `bar::foo` bezieht sich auf `foo` in der `bar`-Crate."
+#: src/modules/paths.md:13
+msgid ""
+"A module can bring symbols from another module into scope with `use`.\n"
+"You 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:1
#, fuzzy
msgid "# Filesystem Hierarchy"
@@ -7715,15 +7913,19 @@ msgid ""
"//! This module implements the garden, including a highly performant germination\n"
"//! implementation.\n"
"\n"
-"/// Sow the given seed packets.\n"
-"fn sow(seeds: Vec) { todo!() }\n"
+"// Re-export types from this module.\n"
+"pub use seeds::SeedPacket;\n"
+"pub use garden::Garden;\n"
"\n"
-"// Harvest the produce in the garden that is ready.\n"
-"fn harvest(garden: &mut Garden) { todo!() }\n"
+"/// Sow the given seed packets.\n"
+"pub fn sow(seeds: Vec) { todo!() }\n"
+"\n"
+"/// Harvest the produce in the garden that is ready.\n"
+"pub fn harvest(garden: &mut Garden) { todo!() }\n"
"```"
msgstr ""
-#: src/modules/filesystem.md:40
+#: src/modules/filesystem.md:44
msgid ""
"* The change from `module/mod.rs` to `module.rs` doesn't preclude the use of submodules in Rust "
"2018.\n"
@@ -8168,7 +8370,7 @@ msgstr ""
#: src/traits/trait-objects.md:5
msgid ""
-"```rust\n"
+"```rust,editable\n"
"trait Pet {\n"
" fn name(&self) -> String;\n"
"}\n"
@@ -8193,8 +8395,8 @@ msgid ""
"\n"
"fn main() {\n"
" let pets: Vec> = vec![\n"
-" Box::new(Dog { name: String::from(\"Fido\") }),\n"
" Box::new(Cat),\n"
+" Box::new(Dog { name: String::from(\"Fido\") }),\n"
" ];\n"
" for pet in pets {\n"
" println!(\"Hello {}!\", pet.name());\n"
@@ -8342,9 +8544,28 @@ msgid ""
"* Move method `not_equal` to a new trait `NotEqual`.\n"
"\n"
"* Make `NotEqual` a super trait for `Equal`.\n"
+" ```rust,editable,compile_fail\n"
+" trait NotEqual: Equals {\n"
+" fn not_equal(&self, other: &Self) -> bool {\n"
+" !self.equal(other)\n"
+" }\n"
+" }\n"
+" ```\n"
"\n"
"* Provide a blanket implementation of `NotEqual` for `Equal`.\n"
-" * With the blanket implementation, you no longer need `NotEqual` as a super trait for `Equal`."
+" ```rust,editable,compile_fail\n"
+" trait NotEqual {\n"
+" fn not_equal(&self, other: &Self) -> bool;\n"
+" }\n"
+"\n"
+" impl NotEqual for T where T: Equals {\n"
+" fn not_equal(&self, other: &Self) -> bool {\n"
+" !self.equal(other)\n"
+" }\n"
+" }\n"
+" ```\n"
+" * With the blanket implementation, you no longer need `NotEqual` as a super trait for `Equal`.\n"
+" "
msgstr ""
#: src/traits/trait-bounds.md:1
@@ -8828,7 +9049,7 @@ msgid "# The `Default` Trait"
msgstr "# Die `Drop`-Eigenschaft"
#: src/traits/default.md:3
-msgid "[`Default`][1] trait provides a default implementation of a trait."
+msgid "[`Default`][1] trait produces a default value for a type."
msgstr ""
#: src/traits/default.md:5
@@ -8919,10 +9140,12 @@ msgid ""
" overloading the operator is not `Copy`, you should consider overloading\n"
" the operator for `&T` as well. This avoids unnecessary cloning on the\n"
" call site.\n"
-"* Why is `Output` an associated type? Could it be made a type parameter?\n"
-" * Short answer: Type parameters are controlled by the caller, but\n"
+"* Why is `Output` an associated type? Could it be made a type parameter of the method?\n"
+" * Short answer: Function type parameters are controlled by the caller, but\n"
" associated types (like `Output`) are controlled by the implementor of a\n"
-" trait."
+" trait.\n"
+"* You could implement `Add` for two different types, e.g.\n"
+" `impl Add<(i32, i32)> for Point` would add a tuple to a `Point`."
msgstr ""
"* Sie könnten `Add` für `&Point` implementieren. In welchen Situationen ist das sinnvoll?\n"
" * Antwort: `Add:add` verbraucht `self`. Geben Sie \"T\" ein, für das Sie sind\n"
@@ -9313,7 +9536,7 @@ msgstr ""
#: src/error-handling/panic-unwind.md:5
msgid ""
-"```rust\n"
+"```rust,editable\n"
"use std::panic;\n"
"\n"
"let result = panic::catch_unwind(|| {\n"
@@ -9356,7 +9579,7 @@ msgstr ""
#: src/error-handling/result.md:6
msgid ""
-"```rust\n"
+"```rust,editable\n"
"use std::fs::File;\n"
"use std::io::Read;\n"
"\n"
@@ -9452,17 +9675,15 @@ msgid ""
"\n"
"fn read_username(path: &str) -> Result {\n"
" let username_file_result = fs::File::open(path);\n"
-"\n"
" let mut username_file = match username_file_result {\n"
" Ok(file) => file,\n"
-" Err(e) => return Err(e),\n"
+" Err(err) => return Err(err),\n"
" };\n"
"\n"
" let mut username = String::new();\n"
-"\n"
" match username_file.read_to_string(&mut username) {\n"
" Ok(_) => Ok(username),\n"
-" Err(e) => Err(e),\n"
+" Err(err) => Err(err),\n"
" }\n"
"}\n"
"\n"
@@ -9474,7 +9695,7 @@ msgid ""
"```"
msgstr ""
-#: src/error-handling/try-operator.md:52 src/error-handling/converting-error-types-example.md:52
+#: src/error-handling/try-operator.md:50 src/error-handling/converting-error-types-example.md:52
#, fuzzy
msgid ""
"* The `username` variable can be either `Ok(string)` or `Err(error)`.\n"
@@ -9821,7 +10042,7 @@ msgstr "Unit-Tests mit `#[test]` markieren:"
#: src/testing/unit-tests.md:5
msgid ""
-"```rust,ignore\n"
+"```rust,editable,ignore\n"
"fn first_word(text: &str) -> &str {\n"
" match text.find(' ') {\n"
" Some(idx) => &text[..idx],\n"
@@ -9968,6 +10189,27 @@ msgstr ""
msgid "These tests only have access to the public API of your crate."
msgstr "Diese Tests haben nur Zugriff auf die öffentliche API Ihrer Crate."
+#: src/testing/useful-crates.md:1
+msgid "## Useful crates for writing tests"
+msgstr ""
+
+#: src/testing/useful-crates.md:3
+#, fuzzy
+msgid "Rust comes with only basic support for writing tests."
+msgstr "Rust hat eine eingebaute Unterstützung für Dokumentationstests:"
+
+#: src/testing/useful-crates.md:5
+msgid "Here are some additional crates which we recommend for writing tests:"
+msgstr ""
+
+#: src/testing/useful-crates.md:7
+msgid ""
+"* [googletest](https://docs.rs/googletest): Comprehensive test assertion library in the tradition "
+"of GoogleTest for C++.\n"
+"* [proptest](https://docs.rs/proptest): Property-based testing for Rust.\n"
+"* [rstest](https://docs.rs/rstest): Support for fixtures and parameterised tests."
+msgstr ""
+
#: src/unsafe.md:1
#, fuzzy
msgid "# Unsafe Rust"
@@ -10068,10 +10310,10 @@ msgid ""
" let r1 = &mut num as *mut i32;\n"
" let r2 = r1 as *const i32;\n"
"\n"
-" // Safe because r1 and r2 were obtained from references and so are guaranteed to be non-null "
-"and\n"
-" // properly aligned, the objects underlying the references from which they were obtained are\n"
-" // live throughout the whole unsafe block, and they are not accessed either through the\n"
+" // Safe because r1 and r2 were obtained from references and so are\n"
+" // guaranteed to be non-null and properly aligned, the objects underlying\n"
+" // the references from which they were obtained are live throughout the\n"
+" // whole unsafe block, and they are not accessed either through the\n"
" // references or concurrently through any other pointers.\n"
" unsafe {\n"
" println!(\"r1 is: {}\", *r1);\n"
@@ -10082,7 +10324,7 @@ msgid ""
"```"
msgstr ""
-#: src/unsafe/raw-pointers.md:26
+#: src/unsafe/raw-pointers.md:27
#, fuzzy
msgid ""
"It is good practice (and required by the Android Rust style guide) to write a comment for each\n"
@@ -10095,7 +10337,7 @@ msgstr ""
"unsicheren Codes erfüllt\n"
"Operationen, die es tut."
-#: src/unsafe/raw-pointers.md:30
+#: src/unsafe/raw-pointers.md:31
#, fuzzy
msgid ""
"In the case of pointer dereferences, this means that the pointers must be\n"
@@ -10104,7 +10346,7 @@ msgstr ""
"Im Fall von Zeigerdereferenzen bedeutet dies, dass die Zeiger sein müssen\n"
"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), also:"
-#: src/unsafe/raw-pointers.md:33
+#: src/unsafe/raw-pointers.md:34
#, fuzzy
msgid ""
" * The pointer must be non-null.\n"
@@ -10123,7 +10365,7 @@ msgstr ""
"live sein und nein\n"
" Referenz kann verwendet werden, um auf den Speicher zuzugreifen."
-#: src/unsafe/raw-pointers.md:40
+#: src/unsafe/raw-pointers.md:41
#, fuzzy
msgid "In most cases the pointer must also be properly aligned."
msgstr "In den meisten Fällen muss auch der Zeiger richtig ausgerichtet werden."
@@ -10518,18 +10760,42 @@ msgstr ""
"* [`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)"
#: src/exercises/day-3/safe-ffi-wrapper.md:13
-#, fuzzy
msgid ""
-"You will also want to browse the [`std::ffi`] module, particular for [`CStr`]\n"
-"and [`CString`] types which are used to hold NUL-terminated strings coming from\n"
-"C. The [Nomicon] also has a very useful chapter about FFI."
+"You will also want to browse the [`std::ffi`] module. There you find a number of\n"
+"string types which you need for the exercise:"
+msgstr ""
+
+#: src/exercises/day-3/safe-ffi-wrapper.md:16
+msgid ""
+"| Types | Encoding | Use |\n"
+"|----------------------------|----------------|--------------------------------|\n"
+"| [`str`] and [`String`] | UTF-8 | Text processing in Rust |\n"
+"| [`CStr`] and [`CString`] | NUL-terminated | Communicating with C functions |\n"
+"| [`OsStr`] and [`OsString`] | OS-specific | Communicating with the OS |"
msgstr ""
-"Sie sollten auch das Modul [`std::ffi`] durchsuchen, insbesondere nach [`CStr`]\n"
-"und [`CString`]-Typen, die verwendet werden, um NUL-terminierte Zeichenfolgen zu halten, die von "
-"kommen\n"
-"C. Das [Nomicon] hat auch ein sehr nützliches Kapitel über FFI."
#: src/exercises/day-3/safe-ffi-wrapper.md:22
+msgid "You will convert between all these types:"
+msgstr ""
+
+#: src/exercises/day-3/safe-ffi-wrapper.md:24
+msgid ""
+"- `&str` to `CString`: you need to allocate space for a trailing `\\0` character,\n"
+"- `CString` to `*const i8`: you need a pointer to call C functions,\n"
+"- `*const i8` to `&CStr`: you need something which can find the trailing `\\0` character,\n"
+"- `&CStr` to `&[u8]`: a slice of bytes is the universal interface for \"some unknow data\",\n"
+"- `&[u8]` to `&OsStr`: `&OsStr` is a step towards `OsString`, use\n"
+" [`OsStrExt`](https://doc.rust-lang.org/std/os/unix/ffi/trait.OsStrExt.html)\n"
+" to create it,\n"
+"- `&OsStr` to `OsString`: you need to clone the data in `&OsStr` to be able to return it and call\n"
+" `readdir` again."
+msgstr ""
+
+#: src/exercises/day-3/safe-ffi-wrapper.md:34
+msgid "The [Nomicon] also has a very useful chapter about FFI."
+msgstr ""
+
+#: src/exercises/day-3/safe-ffi-wrapper.md:45
#, fuzzy
msgid ""
"Copy the code below to and fill in the missing\n"
@@ -10539,7 +10805,7 @@ msgstr ""
"aus\n"
"Funktionen und Methoden:"
-#: src/exercises/day-3/safe-ffi-wrapper.md:25
+#: src/exercises/day-3/safe-ffi-wrapper.md:48
msgid ""
"```rust,should_panic\n"
"// TODO: remove this when you're done with your implementation.\n"
@@ -10627,1098 +10893,10 @@ msgid ""
"```"
msgstr ""
-#: src/welcome-day-4.md:1
+#: src/android.md:1
#, fuzzy
-msgid "# Welcome to Day 4"
-msgstr "# Willkommen zu Tag 4"
-
-#: src/welcome-day-4.md:3
-msgid ""
-"This morning, we will focus on Concurrency: threads, channels, shared state, `Send` and `Sync`.\n"
-"In the afternoon, we will have a chance to see Rust in action."
-msgstr ""
-
-#: src/welcome-day-4.md:8
-msgid ""
-"This is a good time to give an outline of what you will cover in the afternoon\n"
-"section, as announced in the course offering."
-msgstr ""
-
-#: src/concurrency.md:1
-#, fuzzy
-msgid "# Fearless Concurrency"
-msgstr "# Furchtlose Parallelität"
-
-#: src/concurrency.md:3
-#, fuzzy
-msgid ""
-"Rust has full support for concurrency using OS threads with mutexes and\n"
-"channels."
-msgstr ""
-"Rust bietet volle Unterstützung für Parallelität unter Verwendung von Betriebssystem-Threads mit "
-"Mutexes und\n"
-"Kanäle."
-
-#: src/concurrency.md:6
-#, fuzzy
-msgid ""
-"The Rust type system plays an important role in making many concurrency bugs\n"
-"compile time bugs. This is often referred to as _fearless concurrency_ since you\n"
-"can rely on the compiler to ensure correctness at runtime."
-msgstr ""
-"Das Rust-Typsystem spielt eine wichtige Rolle bei der Entstehung vieler Nebenläufigkeitsfehler\n"
-"Kompilierzeitfehler. Dies wird seit Ihnen oft als _furchtlose Parallelität_ bezeichnet\n"
-"kann sich auf den Compiler verlassen, um die Korrektheit zur Laufzeit sicherzustellen."
-
-#: src/concurrency/threads.md:1
-#, fuzzy
-msgid "# Threads"
-msgstr "# Threads"
-
-#: src/concurrency/threads.md:3
-#, fuzzy
-msgid "Rust threads work similarly to threads in other languages:"
-msgstr "Rust-Threads funktionieren ähnlich wie Threads in anderen Sprachen:"
-
-#: src/concurrency/threads.md:5
-msgid ""
-"```rust,editable\n"
-"use std::thread;\n"
-"use std::time::Duration;\n"
-"\n"
-"fn main() {\n"
-" thread::spawn(|| {\n"
-" for i in 1..10 {\n"
-" println!(\"Count in thread: {i}!\");\n"
-" thread::sleep(Duration::from_millis(5));\n"
-" }\n"
-" });\n"
-"\n"
-" for i in 1..5 {\n"
-" println!(\"Main thread: {i}\");\n"
-" thread::sleep(Duration::from_millis(5));\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/threads.md:24
-#, fuzzy
-msgid ""
-"* Threads are all daemon threads, the main thread does not wait for them.\n"
-"* Thread panics are independent of each other.\n"
-" * Panics can carry a payload, which can be unpacked with `downcast_ref`."
-msgstr ""
-"* Threads sind alle Daemon-Threads, der Haupt-Thread wartet nicht auf sie.\n"
-"* Thread-Panics sind voneinander unabhängig.\n"
-" * Paniken können eine Nutzlast tragen, die mit `downcast_ref` entpackt werden kann."
-
-#: src/concurrency/threads.md:32
-msgid ""
-"* Notice that the thread is stopped before it reaches 10 — the main thread is\n"
-" not waiting.\n"
-"\n"
-"* Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for\n"
-" the thread to finish.\n"
-"\n"
-"* Trigger a panic in the thread, notice how this doesn't affect `main`.\n"
-"\n"
-"* Use the `Result` return value from `handle.join()` to get access to the panic\n"
-" payload. This is a good time to talk about [`Any`]."
-msgstr ""
-
-#: src/concurrency/scoped-threads.md:1
-#, fuzzy
-msgid "# Scoped Threads"
-msgstr "# Bereichsbezogene Threads"
-
-#: src/concurrency/scoped-threads.md:3
-#, fuzzy
-msgid "Normal threads cannot borrow from their environment:"
-msgstr "Normale Threads können nicht von ihrer Umgebung ausleihen:"
-
-#: src/concurrency/scoped-threads.md:5
-msgid ""
-"```rust,editable,compile_fail\n"
-"use std::thread;\n"
-"\n"
-"fn main() {\n"
-" let s = String::from(\"Hello\");\n"
-"\n"
-" thread::spawn(|| {\n"
-" println!(\"Length: {}\", s.len());\n"
-" });\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/scoped-threads.md:17
-#, fuzzy
-msgid "However, you can use a [scoped thread][1] for this:"
-msgstr "Sie können dafür jedoch einen [Scoped Thread][1] verwenden:"
-
-#: src/concurrency/scoped-threads.md:19
-msgid ""
-"```rust,editable\n"
-"use std::thread;\n"
-"\n"
-"fn main() {\n"
-" let s = String::from(\"Hello\");\n"
-"\n"
-" thread::scope(|scope| {\n"
-" scope.spawn(|| {\n"
-" println!(\"Length: {}\", s.len());\n"
-" });\n"
-" });\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/scoped-threads.md:37
-#, fuzzy
-msgid ""
-"* The reason for that is that when the `thread::scope` function completes, all the threads are "
-"guaranteed to be joined, so they can return borrowed data.\n"
-"* Normal Rust borrowing rules apply: you can either borrow mutably by one thread, or immutably by "
-"any number of threads.\n"
-" "
-msgstr ""
-"* Der Grund dafür ist, dass nach Abschluss der `thread::scope`-Funktion garantiert alle Threads "
-"verbunden sind, sodass sie geliehene Daten zurückgeben können.\n"
-"* Es gelten die normalen Rust-Ausleihregeln: Sie können entweder veränderlich von einem Thread "
-"ausleihen oder unveränderlich von einer beliebigen Anzahl von Threads.\n"
-" \n"
-" "
-
-#: src/concurrency/channels.md:1
-#, fuzzy
-msgid "# Channels"
-msgstr "# Kanäle"
-
-#: src/concurrency/channels.md:3
-#, fuzzy
-msgid ""
-"Rust channels have two parts: a `Sender` and a `Receiver`. The two parts\n"
-"are connected via the channel, but you only see the end-points."
-msgstr ""
-"Rust-Kanäle bestehen aus zwei Teilen: einem `Sender` und einem `Receiver`. Die zwei Teile\n"
-"über den Kanal verbunden sind, aber Sie sehen nur die Endpunkte."
-
-#: src/concurrency/channels.md:6
-msgid ""
-"```rust,editable\n"
-"use std::sync::mpsc;\n"
-"use std::thread;\n"
-"\n"
-"fn main() {\n"
-" let (tx, rx) = mpsc::channel();\n"
-"\n"
-" tx.send(10).unwrap();\n"
-" tx.send(20).unwrap();\n"
-"\n"
-" println!(\"Received: {:?}\", rx.recv());\n"
-" println!(\"Received: {:?}\", rx.recv());\n"
-"\n"
-" let tx2 = tx.clone();\n"
-" tx2.send(30).unwrap();\n"
-" println!(\"Received: {:?}\", rx.recv());\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/channels.md:27
-#, fuzzy
-msgid ""
-"* `mpsc` stands for Multi-Producer, Single-Consumer. `Sender` and `SyncSender` implement `Clone` "
-"(so\n"
-" you can make multiple producers) but `Receiver` does not.\n"
-"* `send()` and `recv()` return `Result`. If they return `Err`, it means the counterpart `Sender` "
-"or\n"
-" `Receiver` is dropped and the channel is closed."
-msgstr ""
-"* „mpsc“ steht für Multi-Producer, Single-Consumer. `Sender` und `SyncSender` implementieren "
-"`Clone` (also\n"
-" Sie können mehrere Producer erstellen), aber 'Receiver' nicht.\n"
-"* `send()` und `recv()` geben `Result` zurück. Wenn sie `Err` zurückgeben, bedeutet dies das "
-"Gegenstück `Sender` bzw\n"
-" „Receiver“ wird fallen gelassen und der Kanal wird geschlossen."
-
-#: src/concurrency/channels/unbounded.md:1
-#, fuzzy
-msgid "# Unbounded Channels"
-msgstr "# Unbegrenzte Kanäle"
-
-#: src/concurrency/channels/unbounded.md:3
-#, fuzzy
-msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:"
-msgstr "Einen unbegrenzten und asynchronen Kanal erhält man mit `mpsc::channel()`:"
-
-#: src/concurrency/channels/unbounded.md:5
-msgid ""
-"```rust,editable\n"
-"use std::sync::mpsc;\n"
-"use std::thread;\n"
-"use std::time::Duration;\n"
-"\n"
-"fn main() {\n"
-" let (tx, rx) = mpsc::channel();\n"
-"\n"
-" thread::spawn(move || {\n"
-" let thread_id = thread::current().id();\n"
-" for i in 1..10 {\n"
-" tx.send(format!(\"Message {i}\")).unwrap();\n"
-" println!(\"{thread_id:?}: sent Message {i}\");\n"
-" }\n"
-" println!(\"{thread_id:?}: done\");\n"
-" });\n"
-" thread::sleep(Duration::from_millis(100));\n"
-"\n"
-" for msg in rx.iter() {\n"
-" println!(\"Main: got {}\", msg);\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/channels/bounded.md:1
-#, fuzzy
-msgid "# Bounded Channels"
-msgstr "# Gebundene Kanäle"
-
-#: src/concurrency/channels/bounded.md:3
-#, fuzzy
-msgid "Bounded and synchronous channels make `send` block the current thread:"
-msgstr ""
-"Gebundene und synchrone Kanäle sorgen dafür, dass der aktuelle Thread durch „Senden“ blockiert "
-"wird:"
-
-#: src/concurrency/channels/bounded.md:5
-msgid ""
-"```rust,editable\n"
-"use std::sync::mpsc;\n"
-"use std::thread;\n"
-"use std::time::Duration;\n"
-"\n"
-"fn main() {\n"
-" let (tx, rx) = mpsc::sync_channel(3);\n"
-"\n"
-" thread::spawn(move || {\n"
-" let thread_id = thread::current().id();\n"
-" for i in 1..10 {\n"
-" tx.send(format!(\"Message {i}\")).unwrap();\n"
-" println!(\"{thread_id:?}: sent Message {i}\");\n"
-" }\n"
-" println!(\"{thread_id:?}: done\");\n"
-" });\n"
-" thread::sleep(Duration::from_millis(100));\n"
-"\n"
-" for msg in rx.iter() {\n"
-" println!(\"Main: got {msg}\");\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/shared_state.md:1
-#, fuzzy
-msgid "# Shared State"
-msgstr "# Geteilter Zustand"
-
-#: src/concurrency/shared_state.md:3
-#, fuzzy
-msgid ""
-"Rust uses the type system to enforce synchronization of shared data. This is\n"
-"primarily done via two types:"
-msgstr ""
-"Rust verwendet das Typsystem, um die Synchronisierung gemeinsam genutzter Daten zu erzwingen. Das "
-"ist\n"
-"hauptsächlich über zwei Arten:"
-
-#: src/concurrency/shared_state.md:6
-#, fuzzy
-msgid ""
-"* [`Arc`][1], atomic reference counted `T`: handles sharing between threads and\n"
-" takes care to deallocate `T` when the last reference is dropped,\n"
-"* [`Mutex`][2]: ensures mutually exclusive access to the `T` value."
-msgstr ""
-"* [`Arc`][1], Atomic Reference Counted `T`: handhabt die gemeinsame Nutzung zwischen Threads "
-"und\n"
-" sorgt dafür, dass `T` freigegeben wird, wenn die letzte Referenz gelöscht wird,\n"
-"* [`Mutex`][2]: sorgt für den sich gegenseitig ausschließenden Zugriff auf den `T`-Wert."
-
-#: src/concurrency/shared_state/arc.md:1
-#, fuzzy
-msgid "# `Arc`"
-msgstr "# `Bogen`"
-
-#: src/concurrency/shared_state/arc.md:3
-#, fuzzy
-msgid "[`Arc`][1] allows shared read-only access via its `clone` method:"
-msgstr "[`Arc`][1] ermöglicht den gemeinsamen Nur-Lese-Zugriff über seine `clone`-Methode:"
-
-#: src/concurrency/shared_state/arc.md:5
-msgid ""
-"```rust,editable\n"
-"use std::thread;\n"
-"use std::sync::Arc;\n"
-"\n"
-"fn main() {\n"
-" let v = Arc::new(vec![10, 20, 30]);\n"
-" let mut handles = Vec::new();\n"
-" for _ in 1..5 {\n"
-" let v = v.clone();\n"
-" handles.push(thread::spawn(move || {\n"
-" let thread_id = thread::current().id();\n"
-" println!(\"{thread_id:?}: {v:?}\");\n"
-" }));\n"
-" }\n"
-"\n"
-" handles.into_iter().for_each(|h| h.join().unwrap());\n"
-" println!(\"v: {v:?}\");\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/shared_state/arc.md:29
-#, fuzzy
-msgid ""
-"* `Arc` stands for \"Atomic Reference Counted\", a thread safe version of `Rc` that uses atomic\n"
-" operations.\n"
-"* `Arc` implements `Clone` whether or not `T` does. It implements `Send` and `Sync` iff `T`\n"
-" implements them both.\n"
-"* `Arc::clone()` has the cost of atomic operations that get executed, but after that the use of "
-"the\n"
-" `T` is free.\n"
-"* Beware of reference cycles, `Arc` does not use a garbage collector to detect them.\n"
-" * `std::sync::Weak` can help."
-msgstr ""
-"* `Arc` steht für \"Atomic Reference Counted\", eine Thread-sichere Version von `Rc`, die atomar "
-"verwendet\n"
-" Operationen.\n"
-"* `Arc` implementiert `Clone` unabhängig davon, ob `T` dies tut oder nicht. Es implementiert "
-"`Send` und `Sync` iff `T`\n"
-" setzt sie beide um.\n"
-"* `Arc::clone()` hat die Kosten für atomare Operationen, die ausgeführt werden, aber danach die "
-"Verwendung der\n"
-" „T“ ist frei.\n"
-"* Hüten Sie sich vor Referenzzyklen, `Arc` verwendet keinen Garbage Collector, um sie zu "
-"erkennen.\n"
-" * `std::sync::Weak` kann helfen."
-
-#: src/concurrency/shared_state/mutex.md:1
-#, fuzzy
-msgid "# `Mutex`"
-msgstr "# `Mutex`"
-
-#: src/concurrency/shared_state/mutex.md:3
-#, fuzzy
-msgid ""
-"[`Mutex`][1] ensures mutual exclusion _and_ allows mutable access to `T`\n"
-"behind a read-only interface:"
-msgstr ""
-"[`Mutex`][1] sorgt für gegenseitigen Ausschluss _und_ erlaubt veränderlichen Zugriff auf `T`\n"
-"hinter einer Nur-Lese-Schnittstelle:"
-
-#: src/concurrency/shared_state/mutex.md:6
-msgid ""
-"```rust,editable\n"
-"use std::sync::Mutex;\n"
-"\n"
-"fn main() {\n"
-" let v = Mutex::new(vec![10, 20, 30]);\n"
-" println!(\"v: {:?}\", v.lock().unwrap());\n"
-"\n"
-" {\n"
-" let mut guard = v.lock().unwrap();\n"
-" guard.push(40);\n"
-" }\n"
-"\n"
-" println!(\"v: {:?}\", v.lock().unwrap());\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/shared_state/mutex.md:22
-#, fuzzy
-msgid ""
-"Notice how we have a [`impl Sync for Mutex`][2] blanket\n"
-"implementation."
-msgstr ""
-"Beachten Sie, wie wir eine [`impl Sync for Mutex`][2] Blanket haben\n"
-"Implementierung."
-
-#: src/concurrency/shared_state/mutex.md:31
-#, fuzzy
-msgid ""
-"* `Mutex` in Rust looks like a collection with just one element - the protected data.\n"
-" * It is not possible to forget to acquire the mutex before accessing the protected data.\n"
-"* You can get an `&mut T` from an `&Mutex` by taking the lock. The `MutexGuard` ensures that "
-"the\n"
-" `&mut T` doesn't outlive the lock being held.\n"
-"* `Mutex` implements both `Send` and `Sync` iff `T` implements `Send`.\n"
-"* A read-write lock counterpart - `RwLock`.\n"
-"* Why does `lock()` return a `Result`? \n"
-" * If the thread that held the `Mutex` panicked, the `Mutex` becomes \"poisoned\" to signal "
-"that\n"
-" the data it protected might be in an inconsistent state. Calling `lock()` on a poisoned "
-"mutex\n"
-" fails with a [`PoisonError`]. You can call `into_inner()` on the error to recover the data\n"
-" regardless."
-msgstr ""
-"* `Mutex` in Rust sieht aus wie eine Sammlung mit nur einem Element - den geschützten Daten.\n"
-" * Es ist nicht möglich, das Abrufen des Mutex zu vergessen, bevor auf die geschützten Daten "
-"zugegriffen wird.\n"
-"* Sie können ein `&mut T` von einem `&Mutex` erhalten, indem Sie die Sperre nehmen. Der "
-"`MutexGuard` sorgt dafür, dass die\n"
-" `&mut T` überlebt die gehaltene Sperre nicht.\n"
-"* `Mutex` implementiert sowohl `Send` als auch `Sync`, wenn `T` `Send` implementiert.\n"
-"* Ein Gegenstück zur Lese-Schreib-Sperre - `RwLock`.\n"
-"* Warum gibt `lock()` ein `Result` zurück?\n"
-" * Wenn der Thread, der den `Mutex` enthielt, in Panik geriet, wird der `Mutex` \"vergiftet\", "
-"um dies zu signalisieren\n"
-" Die geschützten Daten befinden sich möglicherweise in einem inkonsistenten Zustand. Aufruf "
-"von `lock()` auf einem vergifteten Mutex\n"
-" schlägt mit einem [`PoisonError`] fehl. Sie können `into_inner()` für den Fehler aufrufen, "
-"um die Daten wiederherzustellen\n"
-" trotzdem."
-
-#: src/concurrency/shared_state/example.md:3
-#, fuzzy
-msgid "Let us see `Arc` and `Mutex` in action:"
-msgstr "Sehen wir uns `Arc` und `Mutex` in Aktion an:"
-
-#: src/concurrency/shared_state/example.md:5
-msgid ""
-"```rust,editable,compile_fail\n"
-"use std::thread;\n"
-"// use std::sync::{Arc, Mutex};\n"
-"\n"
-"fn main() {\n"
-" let mut v = vec![10, 20, 30];\n"
-" let handle = thread::spawn(|| {\n"
-" v.push(10);\n"
-" });\n"
-" v.push(1000);\n"
-"\n"
-" handle.join().unwrap();\n"
-" println!(\"v: {v:?}\");\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/shared_state/example.md:23
-msgid "Possible solution:"
-msgstr ""
-
-#: src/concurrency/shared_state/example.md:25
-msgid ""
-"```rust,editable\n"
-"use std::sync::{Arc, Mutex};\n"
-"use std::thread;\n"
-"\n"
-"fn main() {\n"
-" let v = Arc::new(Mutex::new(vec![10, 20, 30]));\n"
-"\n"
-" let v2 = v.clone();\n"
-" let handle = thread::spawn(move || {\n"
-" let mut v2 = v2.lock().unwrap();\n"
-" v2.push(10);\n"
-" });\n"
-"\n"
-" {\n"
-" let mut v = v.lock().unwrap();\n"
-" v.push(1000);\n"
-" }\n"
-"\n"
-" handle.join().unwrap();\n"
-"\n"
-" println!(\"v: {v:?}\");\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/concurrency/shared_state/example.md:49
-msgid "Notable parts:"
-msgstr ""
-
-#: src/concurrency/shared_state/example.md:51
-#, fuzzy
-msgid ""
-"* `v` is wrapped in both `Arc` and `Mutex`, because their concerns are orthogonal.\n"
-" * Wrapping a `Mutex` in an `Arc` is a common pattern to share mutable state between threads.\n"
-"* `v: Arc<_>` needs to be cloned as `v2` before it can be moved into another thread. Note `move` "
-"was added to the lambda signature.\n"
-"* Blocks are introduced to narrow the scope of the `LockGuard` as much as possible."
-msgstr ""
-"* `v` ist sowohl in `Arc` als auch in `Mutex` eingeschlossen, weil ihre Anliegen orthogonal sind.\n"
-" * Das Umhüllen eines `Mutex` in einen `Arc` ist ein gängiges Muster, um einen veränderlichen "
-"Zustand zwischen Threads zu teilen.\n"
-"* „v: Arc<_>“ muss als „v2“ geklont werden, bevor es in einen anderen Thread verschoben werden "
-"kann. Der Lambda-Signatur wurde der Hinweis „move“ hinzugefügt.\n"
-"* Blöcke werden eingeführt, um den Anwendungsbereich von `LockGuard` so weit wie möglich "
-"einzuschränken.\n"
-"* Wir müssen noch den `Mutex` erwerben, um unseren `Vec` zu drucken."
-
-#: src/concurrency/send-sync.md:1
-#, fuzzy
-msgid "# `Send` and `Sync`"
-msgstr "# `Senden` und `Synchronisieren`"
-
-#: src/concurrency/send-sync.md:3
-#, fuzzy
-msgid "How does Rust know to forbid shared access across thread? The answer is in two traits:"
-msgstr ""
-"Woher weiß Rust, dass es den gemeinsamen Zugriff über Threads verbieten soll? Die Antwort liegt in "
-"zwei Merkmalen:"
-
-#: src/concurrency/send-sync.md:5
-#, fuzzy
-msgid ""
-"* [`Send`][1]: a type `T` is `Send` if it is safe to move a `T` across a thread\n"
-" boundary.\n"
-"* [`Sync`][2]: a type `T` is `Sync` if it is safe to move a `&T` across a thread\n"
-" boundary."
-msgstr ""
-"* [`Send`][1]: ein Typ `T` ist `Send`, wenn es sicher ist, ein `T` über einen Thread zu bewegen\n"
-" Grenze.\n"
-"* [`Sync`][2]: ein Typ `T` ist `Sync`, wenn es sicher ist, ein `&T` über einen Thread zu "
-"verschieben\n"
-" Grenze."
-
-#: src/concurrency/send-sync.md:10
-#, fuzzy
-msgid ""
-"`Send` and `Sync` are [unsafe traits][3]. The compiler will automatically derive them for your "
-"types\n"
-"as long as they only contain `Send` and `Sync` types. You can also implement them manually when "
-"you\n"
-"know it is valid."
-msgstr ""
-"„Senden“ und „Synchronisieren“ sind [unsichere Eigenschaften][3]. Der Compiler leitet sie "
-"automatisch für Ihre Typen ab\n"
-"solange sie nur die Typen `Send` und `Sync` enthalten. Sie können sie auch manuell implementieren, "
-"wenn Sie\n"
-"wissen, dass es gültig ist."
-
-#: src/concurrency/send-sync.md:20
-#, fuzzy
-msgid ""
-"* One can think of these traits as markers that the type has certain thread-safety properties.\n"
-"* They can be used in the generic constraints as normal traits.\n"
-" "
-msgstr ""
-"* Man kann sich diese Eigenschaften als Markierungen dafür vorstellen, dass der Typ bestimmte "
-"Thread-Sicherheitseigenschaften hat.\n"
-"* Sie können in den generischen Einschränkungen als normale Merkmale verwendet werden.\n"
-" \n"
-" "
-
-#: src/concurrency/send-sync/send.md:1
-#, fuzzy
-msgid "# `Send`"
-msgstr "# `Senden`"
-
-#: src/concurrency/send-sync/send.md:3
-#, fuzzy
-msgid "> A type `T` is [`Send`][1] if it is safe to move a `T` value to another thread."
-msgstr ""
-"> Ein Typ `T` ist [`Send`][1], wenn es sicher ist, einen `T`-Wert in einen anderen Thread zu "
-"verschieben."
-
-#: src/concurrency/send-sync/send.md:5
-#, fuzzy
-msgid ""
-"The effect of moving ownership to another thread is that _destructors_ will run\n"
-"in that thread. So the question is when you can allocate a value in one thread\n"
-"and deallocate it in another."
-msgstr ""
-"Das Verschieben der Eigentümerschaft auf einen anderen Thread hat zur Folge, dass _destructors_ "
-"ausgeführt wird\n"
-"in diesem Thread. Die Frage ist also, wann Sie einen Wert in einem Thread zuweisen können\n"
-"und es in einem anderen freigeben."
-
-#: src/concurrency/send-sync/sync.md:1
-#, fuzzy
-msgid "# `Sync`"
-msgstr "# `Synchronisieren`"
-
-#: src/concurrency/send-sync/sync.md:3
-#, fuzzy
-msgid ""
-"> A type `T` is [`Sync`][1] if it is safe to access a `T` value from multiple\n"
-"> threads at the same time."
-msgstr ""
-"> Ein Typ `T` ist [`Sync`][1], wenn es sicher ist, von mehreren auf einen `T`-Wert zuzugreifen\n"
-"> Threads gleichzeitig."
-
-#: src/concurrency/send-sync/sync.md:6
-#, fuzzy
-msgid "More precisely, the definition is:"
-msgstr "Genauer gesagt lautet die Definition:"
-
-#: src/concurrency/send-sync/sync.md:8
-#, fuzzy
-msgid "> `T` is `Sync` if and only if `&T` is `Send`"
-msgstr "> `T` ist `Sync` genau dann, wenn `&T` `Send` ist"
-
-#: src/concurrency/send-sync/sync.md:14
-#, fuzzy
-msgid ""
-"This statement is essentially a shorthand way of saying that if a type is thread-safe for shared "
-"use, it is also thread-safe to pass references of it across threads."
-msgstr ""
-"Diese Anweisung ist im Wesentlichen eine Kurzform dafür, dass ein Typ, der für die gemeinsame "
-"Verwendung Thread-sicher ist, auch Thread-sicher ist, Verweise auf ihn über Threads hinweg zu "
-"übergeben."
-
-#: src/concurrency/send-sync/sync.md:16
-#, fuzzy
-msgid ""
-"This is because if a type is Sync it means that it can be shared across multiple threads without "
-"the risk of data races or other synchronization issues, so it is safe to move it to another "
-"thread. A reference to the type is also safe to move to another thread, because the data it "
-"references can be accessed from any thread safely."
-msgstr ""
-"Denn wenn ein Typ Sync ist, bedeutet dies, dass er von mehreren Threads gemeinsam genutzt werden "
-"kann, ohne das Risiko von Datenrennen oder anderen Synchronisierungsproblemen, sodass es sicher "
-"ist, ihn in einen anderen Thread zu verschieben. Ein Verweis auf den Typ kann auch sicher in einen "
-"anderen Thread verschoben werden, da auf die Daten, auf die er verweist, von jedem Thread aus "
-"sicher zugegriffen werden kann."
-
-#: src/concurrency/send-sync/examples.md:1
-#, fuzzy
-msgid "# Examples"
-msgstr "# Beispiele"
-
-#: src/concurrency/send-sync/examples.md:3
-#, fuzzy
-msgid "## `Send + Sync`"
-msgstr "## `Senden + Synchronisieren`"
-
-#: src/concurrency/send-sync/examples.md:5
-#, fuzzy
-msgid "Most types you come across are `Send + Sync`:"
-msgstr "Die meisten Typen, auf die Sie stoßen, sind „Send + Sync“:"
-
-#: src/concurrency/send-sync/examples.md:7
-msgid ""
-"* `i8`, `f32`, `bool`, `char`, `&str`, ...\n"
-"* `(T1, T2)`, `[T; N]`, `&[T]`, `struct { x: T }`, ...\n"
-"* `String`, `Option`, `Vec`, `Box`, ...\n"
-"* `Arc`: Explicitly thread-safe via atomic reference count.\n"
-"* `Mutex`: Explicitly thread-safe via internal locking.\n"
-"* `AtomicBool`, `AtomicU8`, ...: Uses special atomic instructions."
-msgstr ""
-
-#: src/concurrency/send-sync/examples.md:14
-#, fuzzy
-msgid ""
-"The generic types are typically `Send + Sync` when the type parameters are\n"
-"`Send + Sync`."
-msgstr ""
-"Die generischen Typen sind typischerweise `Send + Sync`, wenn es die Typparameter sind\n"
-"„Senden + Synchronisieren“."
-
-#: src/concurrency/send-sync/examples.md:17
-#, fuzzy
-msgid "## `Send + !Sync`"
-msgstr "## `Senden + !Sync`"
-
-#: src/concurrency/send-sync/examples.md:19
-#, fuzzy
-msgid ""
-"These types can be moved to other threads, but they're not thread-safe.\n"
-"Typically because of interior mutability:"
-msgstr ""
-"Diese Typen können in andere Threads verschoben werden, sind aber nicht Thread-sicher.\n"
-"Typischerweise wegen innerer Mutabilität:"
-
-#: src/concurrency/send-sync/examples.md:22
-#, fuzzy
-msgid ""
-"* `mpsc::Sender`\n"
-"* `mpsc::Receiver`\n"
-"* `Cell`\n"
-"* `RefCell`"
-msgstr ""
-"* `mpsc::Sender`\n"
-"* `mpsc::Receiver`\n"
-"* `Zelle`\n"
-"* `RefCell`"
-
-#: src/concurrency/send-sync/examples.md:27
-#, fuzzy
-msgid "## `!Send + Sync`"
-msgstr "## `!Senden + Synchronisieren`"
-
-#: src/concurrency/send-sync/examples.md:29
-#, fuzzy
-msgid "These types are thread-safe, but they cannot be moved to another thread:"
-msgstr "Diese Typen sind Thread-sicher, können aber nicht in einen anderen Thread verschoben werden:"
-
-#: src/concurrency/send-sync/examples.md:31
-#, fuzzy
-msgid ""
-"* `MutexGuard`: Uses OS level primitives which must be deallocated on the\n"
-" thread which created them."
-msgstr ""
-"* `MutexGuard`: Verwendet Primitive auf Betriebssystemebene, die auf dem freigegeben werden "
-"müssen\n"
-" Thread, der sie erstellt hat."
-
-#: src/concurrency/send-sync/examples.md:34
-#, fuzzy
-msgid "## `!Send + !Sync`"
-msgstr "## `!Senden + !Sync`"
-
-#: src/concurrency/send-sync/examples.md:36
-#, fuzzy
-msgid "These types are not thread-safe and cannot be moved to other threads:"
-msgstr "Diese Typen sind nicht Thread-sicher und können nicht in andere Threads verschoben werden:"
-
-#: src/concurrency/send-sync/examples.md:38
-#, fuzzy
-msgid ""
-"* `Rc`: each `Rc` has a reference to an `RcBox`, which contains a\n"
-" non-atomic reference count.\n"
-"* `*const T`, `*mut T`: Rust assumes raw pointers may have special\n"
-" concurrency considerations."
-msgstr ""
-"* `Rc`: Jedes `Rc` hat eine Referenz auf eine `RcBox`, die eine enthält\n"
-" nicht-atomarer Referenzzähler.\n"
-"* `*const T`, `*mut T`: Rust geht davon aus, dass Rohzeiger möglicherweise etwas Besonderes haben\n"
-" Parallelitätsüberlegungen."
-
-#: src/exercises/day-4/morning.md:1 src/exercises/day-4/android.md:1
-#: src/exercises/bare-metal/morning.md:1 src/exercises/bare-metal/afternoon.md:1
-#, fuzzy
-msgid "# Exercises"
-msgstr "# Übungen"
-
-#: src/exercises/day-4/morning.md:3
-#, fuzzy
-msgid "Let us practice our new concurrency skills with"
-msgstr "Lassen Sie uns unsere neuen Nebenläufigkeitsfähigkeiten mit üben"
-
-#: src/exercises/day-4/morning.md:5
-#, fuzzy
-msgid ""
-"* Dining philosophers: a classic problem in concurrency.\n"
-"\n"
-"* Multi-threaded link checker: a larger project where you'll use Cargo to\n"
-" download dependencies and then check links in parallel."
-msgstr ""
-"* Multithreaded Link Checker: ein größeres Projekt, für das Sie Cargo verwenden werden\n"
-" Abhängigkeiten herunterladen und dann parallel Links prüfen."
-
-#: src/exercises/day-4/dining-philosophers.md:1
-#, fuzzy
-msgid "# Dining Philosophers"
-msgstr "# Speisende Philosophen"
-
-#: src/exercises/day-4/dining-philosophers.md:3
-#, fuzzy
-msgid "The dining philosophers problem is a classic problem in concurrency:"
-msgstr "Das Dining-Philosophen-Problem ist ein klassisches Nebenläufigkeitsproblem:"
-
-#: src/exercises/day-4/dining-philosophers.md:5
-#, fuzzy
-msgid ""
-"> Five philosophers dine together at the same table. Each philosopher has their\n"
-"> own place at the table. There is a fork between each plate. The dish served is\n"
-"> a kind of spaghetti which has to be eaten with two forks. Each philosopher can\n"
-"> only alternately think and eat. Moreover, a philosopher can only eat their\n"
-"> spaghetti when they have both a left and right fork. Thus two forks will only\n"
-"> be available when their two nearest neighbors are thinking, not eating. After\n"
-"> an individual philosopher finishes eating, they will put down both forks."
-msgstr ""
-"> Fünf Philosophen speisen gemeinsam am selben Tisch. Jeder Philosoph hat seine\n"
-"> eigener Platz am Tisch. Zwischen jedem Teller befindet sich eine Gabel. Das servierte Gericht "
-"ist\n"
-"> eine Art Spaghetti, die mit zwei Gabeln gegessen werden muss. Jeder Philosoph kann\n"
-"> nur abwechselnd denken und essen. Außerdem kann ein Philosoph nur ihre essen\n"
-"> Spaghetti, wenn sie sowohl eine linke als auch eine rechte Gabel haben. Also zwei Gabeln werden "
-"nur\n"
-"> verfügbar sein, wenn ihre beiden nächsten Nachbarn nachdenken, nicht essen. Nach\n"
-"> ein einzelner Philosoph mit dem Essen fertig ist, legen sie beide Gabeln weg."
-
-#: src/exercises/day-4/dining-philosophers.md:13
-#, fuzzy
-msgid ""
-"You will need a local [Cargo installation](../../cargo/running-locally.md) for\n"
-"this exercise. Copy the code below to a file called `src/main.rs`, fill out the\n"
-"blanks, and test that `cargo run` does not deadlock:"
-msgstr ""
-"Dazu benötigen Sie eine lokale [Cargo-Installation](../../cargo/running-locally.md).\n"
-"diese Übung. Kopieren Sie den folgenden Code in die Datei `src/main.rs`, füllen Sie die Lücken "
-"aus,\n"
-"und teste, dass `cargo run` keinen Deadlock verursacht:"
-
-#: src/exercises/day-4/dining-philosophers.md:17 src/exercises/day-4/link-checker.md:55
-#: src/exercises/day-4/elevator.md:19 src/exercises/bare-metal/compass.md:28
-#: src/exercises/bare-metal/rtc.md:18
-msgid ""
-msgstr ""
-
-#: src/exercises/day-4/dining-philosophers.md:19
-msgid ""
-"```rust,compile_fail\n"
-"use std::sync::{mpsc, Arc, Mutex};\n"
-"use std::thread;\n"
-"use std::time::Duration;\n"
-"\n"
-"struct Fork;\n"
-"\n"
-"struct Philosopher {\n"
-" name: String,\n"
-" // left_fork: ...\n"
-" // right_fork: ...\n"
-" // thoughts: ...\n"
-"}\n"
-"\n"
-"impl Philosopher {\n"
-" fn think(&self) {\n"
-" self.thoughts\n"
-" .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n"
-" .unwrap();\n"
-" }\n"
-"\n"
-" fn eat(&self) {\n"
-" // Pick up forks...\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"
-"\n"
-"fn main() {\n"
-" // Create forks\n"
-"\n"
-" // Create philosophers\n"
-"\n"
-" // Make them think and eat\n"
-"\n"
-" // Output their thoughts\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/dining-philosophers.md:61
-msgid "You can use the following `Cargo.toml`:"
-msgstr ""
-
-#: src/exercises/day-4/dining-philosophers.md:63 src/exercises/day-4/link-checker.md:35
-#: src/exercises/day-4/elevator.md:367 src/exercises/bare-metal/compass.md:66
-#: src/exercises/bare-metal/rtc.md:382
-msgid ""
-msgstr ""
-
-#: src/exercises/day-4/dining-philosophers.md:65
-msgid ""
-"```toml\n"
-"[package]\n"
-"name = \"dining-philosophers\"\n"
-"version = \"0.1.0\"\n"
-"edition = \"2021\"\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/link-checker.md:1
-#, fuzzy
-msgid "# Multi-threaded Link Checker"
-msgstr "# Multithreaded Link Checker"
-
-#: src/exercises/day-4/link-checker.md:3
-#, fuzzy
-msgid ""
-"Let us use our new knowledge to create a multi-threaded link checker. It should\n"
-"start at a webpage and check that links on the page are valid. It should\n"
-"recursively check other pages on the same domain and keep doing this until all\n"
-"pages have been validated."
-msgstr ""
-"Lassen Sie uns unser neues Wissen nutzen, um einen Multithread-Link-Checker zu erstellen. Es "
-"sollte\n"
-"Starten Sie auf einer Webseite und prüfen Sie, ob die Links auf der Seite gültig sind. Es sollte\n"
-"Überprüfen Sie rekursiv andere Seiten auf derselben Domain und tun Sie dies so lange, bis alle\n"
-"Seiten wurden validiert."
-
-#: src/exercises/day-4/link-checker.md:8
-#, fuzzy
-msgid ""
-"For this, you will need an HTTP client such as [`reqwest`][1]. Create a new\n"
-"Cargo project and `reqwest` it as a dependency with:"
-msgstr ""
-"Dazu benötigen Sie einen HTTP-Client wie [`reqwest`][1]. Erstelle eine neue\n"
-"Frachtprojekt und `reqwest` es als Abhängigkeit mit:"
-
-#: src/exercises/day-4/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/day-4/link-checker.md:17
-#, fuzzy
-msgid ""
-"> If `cargo add` fails with `error: no such subcommand`, then please edit the\n"
-"> `Cargo.toml` file by hand. Add the dependencies listed below."
-msgstr ""
-"> Wenn `cargo add` mit `error: no such subcommand` fehlschlägt, dann bearbeiten Sie bitte die\n"
-"> `Cargo.toml`-Datei von Hand. Fügen Sie die unten aufgeführten Abhängigkeiten hinzu."
-
-#: src/exercises/day-4/link-checker.md:20
-#, fuzzy
-msgid "You will also need a way to find links. We can use [`scraper`][2] for that:"
-msgstr ""
-"Sie benötigen auch eine Möglichkeit, Links zu finden. Dafür können wir [`scraper`][2] verwenden:"
-
-#: src/exercises/day-4/link-checker.md:22
-msgid ""
-"```shell\n"
-"$ cargo add scraper\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/link-checker.md:26
-#, fuzzy
-msgid ""
-"Finally, we'll need some way of handling errors. We use [`thiserror`][3] for\n"
-"that:"
-msgstr ""
-"Schließlich brauchen wir eine Möglichkeit, mit Fehlern umzugehen. Wir verwenden [`thiserror`][3] "
-"für\n"
-"Das:"
-
-#: src/exercises/day-4/link-checker.md:29
-msgid ""
-"```shell\n"
-"$ cargo add thiserror\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/link-checker.md:33
-#, fuzzy
-msgid "The `cargo add` calls will update the `Cargo.toml` file to look like this:"
-msgstr ""
-"Die `cargo add`-Aufrufe aktualisieren die `Cargo.toml`-Datei so, dass sie wie folgt aussieht:"
-
-#: src/exercises/day-4/link-checker.md:37
-msgid ""
-"```toml\n"
-"[package]\n"
-"name = \"link-checker\"\n"
-"version = \"0.1.0\"\n"
-"edition = \"2021\"\n"
-"publish = false\n"
-"\n"
-"[dependencies]\n"
-"reqwest = { version = \"0.11.12\", features = [\"blocking\", \"rustls-tls\"] }\n"
-"scraper = \"0.13.0\"\n"
-"thiserror = \"1.0.37\"\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/link-checker.md:50
-#, fuzzy
-msgid ""
-"You can now download the start page. Try with a small site such as\n"
-"`https://www.google.org/`."
-msgstr ""
-"Sie können nun die Startseite herunterladen. Versuchen Sie es mit einer kleinen Website wie z\n"
-"`https://www.google.org/`."
-
-#: src/exercises/day-4/link-checker.md:53
-#, fuzzy
-msgid "Your `src/main.rs` file should look something like this:"
-msgstr "Ihre `src/main.rs`-Datei sollte in etwa so aussehen:"
-
-#: src/exercises/day-4/link-checker.md:57
-msgid ""
-"```rust,compile_fail\n"
-"use reqwest::blocking::{get, Response};\n"
-"use reqwest::Url;\n"
-"use scraper::{Html, Selector};\n"
-"use thiserror::Error;\n"
-"\n"
-"#[derive(Error, Debug)]\n"
-"enum Error {\n"
-" #[error(\"request error: {0}\")]\n"
-" ReqwestError(#[from] reqwest::Error),\n"
-"}\n"
-"\n"
-"fn extract_links(response: Response) -> Result, Error> {\n"
-" let base_url = response.url().to_owned();\n"
-" let document = response.text()?;\n"
-" let html = Html::parse_document(&document);\n"
-" let selector = Selector::parse(\"a\").unwrap();\n"
-"\n"
-" let mut valid_urls = Vec::new();\n"
-" for element in html.select(&selector) {\n"
-" if let Some(href) = element.value().attr(\"href\") {\n"
-" match base_url.join(href) {\n"
-" Ok(url) => valid_urls.push(url),\n"
-" Err(err) => {\n"
-" println!(\"On {base_url}: could not parse {href:?}: {err} (ignored)\",);\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-"\n"
-" Ok(valid_urls)\n"
-"}\n"
-"\n"
-"fn main() {\n"
-" let start_url = Url::parse(\"https://www.google.org\").unwrap();\n"
-" let response = get(start_url).unwrap();\n"
-" match extract_links(response) {\n"
-" Ok(links) => println!(\"Links: {links:#?}\"),\n"
-" Err(err) => println!(\"Could not extract links: {err:#}\"),\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/link-checker.md:100
-#, fuzzy
-msgid "Run the code in `src/main.rs` with"
-msgstr "Führen Sie den Code in `src/main.rs` mit aus"
-
-#: src/exercises/day-4/link-checker.md:102
-msgid ""
-"```shell\n"
-"$ cargo run\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/link-checker.md:106
-#, fuzzy
-msgid "## Tasks"
-msgstr "## Aufgaben"
-
-#: src/exercises/day-4/link-checker.md:108
-#, fuzzy
-msgid ""
-"* Use threads to check the links in parallel: send the URLs to be checked to a\n"
-" channel and let a few threads check the URLs in parallel.\n"
-"* Extend this to recursively extract links from all pages on the\n"
-" `www.google.org` domain. Put an upper limit of 100 pages or so so that you\n"
-" don't end up being blocked by the site."
-msgstr ""
-"* Verwenden Sie Threads, um die Links parallel zu prüfen: Senden Sie die zu prüfenden URLs an a\n"
-" Channel und lass ein paar Threads parallel die URLs prüfen.\n"
-"* Erweitern Sie dies, um Links von allen Seiten rekursiv zu extrahieren\n"
-" `www.google.org`-Domain. Setzen Sie eine Obergrenze von 100 Seiten oder so, dass Sie\n"
-" am Ende nicht von der Seite blockiert werden."
-
-#: src/android.md:1 src/bare-metal/android.md:1
-#, fuzzy
-msgid "# Android"
-msgstr "# Android"
+msgid "# Welcome to Rust in Android"
+msgstr "# Willkommen zu Tag 1"
#: src/android.md:3
#, fuzzy
@@ -11892,7 +11070,7 @@ msgstr "Sie können die Binärdatei jetzt erstellen, pushen und ausführen:"
msgid ""
"```shell\n"
"$ m hello_rust\n"
-"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\n"
+"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\"\n"
"$ adb shell /data/local/tmp/hello_rust\n"
"Hello from Rust!\n"
"```"
@@ -11987,7 +11165,7 @@ msgstr "Sie erstellen, pushen und führen die Binärdatei wie zuvor aus:"
msgid ""
"```shell\n"
"$ m hello_rust_with_dep\n"
-"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/tmp\n"
+"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/tmp\"\n"
"$ adb shell /data/local/tmp/hello_rust_with_dep\n"
"Hello Bob, it is very\n"
"nice to meet you!\n"
@@ -12205,7 +11383,7 @@ msgstr "Wir können den Dienst jetzt erstellen, pushen und starten:"
msgid ""
"```shell\n"
"$ m birthday_server\n"
-"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp\n"
+"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp\"\n"
"$ adb shell /data/local/tmp/birthday_server\n"
"```"
msgstr ""
@@ -12323,7 +11501,7 @@ msgstr "Erstellen, pushen und führen Sie den Client auf Ihrem Gerät aus:"
msgid ""
"```shell\n"
"$ m birthday_client\n"
-"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp\n"
+"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp\"\n"
"$ adb shell /data/local/tmp/birthday_client Charlie 60\n"
"Happy Birthday Charlie, congratulations with the 60 years!\n"
"```"
@@ -12429,7 +11607,7 @@ msgstr "Erstellen, übertragen und führen Sie die Binärdatei auf Ihrem Gerät
msgid ""
"```shell\n"
"$ m hello_rust_logs\n"
-"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/tmp\n"
+"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/tmp\"\n"
"$ adb shell /data/local/tmp/hello_rust_logs\n"
"```"
msgstr ""
@@ -12702,7 +11880,7 @@ msgstr ""
msgid ""
"```shell\n"
"$ m print_birthday_card\n"
-"$ adb push $ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/tmp\n"
+"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/tmp\"\n"
"$ adb shell /data/local/tmp/print_birthday_card\n"
"```"
msgstr ""
@@ -12850,7 +12028,7 @@ msgstr ""
msgid ""
"```shell\n"
"$ m analyze_numbers\n"
-"$ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp\n"
+"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp\"\n"
"$ adb shell /data/local/tmp/analyze_numbers\n"
"```"
msgstr ""
@@ -13017,17 +12195,24 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/day-4/android.md:3
+#: 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
+#: src/exercises/concurrency/afternoon.md:1
+#, fuzzy
+msgid "# Exercises"
+msgstr "# Übungen"
+
+#: src/exercises/android/morning.md:3
#, fuzzy
msgid ""
-"For the last exercise, we will look at one of the projects you work with. Let us\n"
-"group up and do this together. Some suggestions:"
+"This is a group exercise: We will look at one of the projects you work with and\n"
+"try to integrate some Rust into it. Some suggestions:"
msgstr ""
"Für die letzte Übung schauen wir uns eines der Projekte an, mit denen Sie arbeiten. Lassen Sie "
"uns\n"
"gruppiert euch und macht das gemeinsam. Einige Vorschläge:"
-#: src/exercises/day-4/android.md:6
+#: src/exercises/android/morning.md:6
#, fuzzy
msgid ""
"* Call your AIDL service with a client written in Rust.\n"
@@ -13035,7 +12220,7 @@ msgid ""
"* Move a function from your project to Rust and call it."
msgstr "* Verschieben Sie eine Funktion aus Ihrem Projekt nach Rust und rufen Sie sie auf."
-#: src/exercises/day-4/android.md:12
+#: src/exercises/android/morning.md:12
#, fuzzy
msgid ""
"No solution is provided here since this is open-ended: it relies on someone in\n"
@@ -13044,1591 +12229,12 @@ msgstr ""
"Hier wird keine Lösung bereitgestellt, da dies offen ist: Es hängt von jemandem ab\n"
"Die Klasse hat einen Code, den Sie spontan an Rust übergeben können."
-#: src/async.md:1
-#, fuzzy
-msgid "# Async Rust"
-msgstr "# Warum Rost?"
-
-#: src/async.md:3
-msgid ""
-"\"Async\" is a concurrency model where multiple tasks are executed concurrently by\n"
-"executing each task until it would block, then switching to another task that is\n"
-"ready to make progress. The model allows running a larger number of tasks on a\n"
-"limited number of threads. This is because the per-task overhead is typically\n"
-"very low and operating systems provide primitives for efficiently identifying\n"
-"I/O that is able to proceed."
-msgstr ""
-
-#: src/async.md:10
-msgid ""
-"Rust's asynchronous operation is based on \"futures\", which represent work that\n"
-"may be completed in the future. Futures are \"polled\" until they signal that\n"
-"they are complete."
-msgstr ""
-
-#: src/async.md:14
-msgid ""
-"Futures are polled by an async runtime, and several different runtimes are\n"
-"available."
-msgstr ""
-
-#: src/async.md:17
-#, fuzzy
-msgid "## Comparisons"
-msgstr "# Vergleich"
-
-#: src/async.md:19
-msgid ""
-" * Python has a similar model in its `asyncio`. However, its `Future` type is\n"
-" callback-based, and not polled. Async Python programs require a \"loop\",\n"
-" similar to a runtime in Rust.\n"
-"\n"
-" * JavaScript's `Promise` is similar, but again callback-based. The language\n"
-" runtime implements the event loop, so many of the details of Promise\n"
-" resolution are hidden."
-msgstr ""
-
-#: src/async/async-await.md:1
-msgid "# `async`/`await`"
-msgstr ""
-
-#: src/async/async-await.md:3
-msgid "At a high level, async Rust code looks very much like \"normal\" sequential code:"
-msgstr ""
-
-#: src/async/async-await.md:5
-msgid ""
-"```rust,editable,compile_fail\n"
-"use futures::executor::block_on;\n"
-"\n"
-"async fn count_to(count: i32) {\n"
-" for i in 1..=count {\n"
-" println!(\"Count is: {i}!\");\n"
-" }\n"
-"}\n"
-"\n"
-"async fn async_main(count: i32) {\n"
-" count_to(count).await;\n"
-"}\n"
-"\n"
-"fn main() {\n"
-" block_on(async_main(10));\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/async/async-await.md:27
-msgid ""
-"* Note that this is a simplified example to show the syntax. There is no long\n"
-" running operation or any real concurrency in it!\n"
-"\n"
-"* What is the return type of an async call?\n"
-" * Use `let future: () = async_main(10);` in `main` to see the type.\n"
-"\n"
-"* The \"async\" keyword is syntactic sugar. The compiler replaces the return type\n"
-" with a future. \n"
-"\n"
-"* You cannot make `main` async, without additional instructions to the compiler\n"
-" on how to use the returned future.\n"
-"\n"
-"* You need an executor to run async code. `block_on` blocks the current thread\n"
-" until the provided future has run to completion. \n"
-"\n"
-"* `.await` asynchronously waits for the completion of another operation. Unlike\n"
-" `block_on`, `.await` doesn't block the current thread.\n"
-"\n"
-"* `.await` can only be used inside an `async` function (or block; these are\n"
-" introduced later). "
-msgstr ""
-
-#: src/async/futures.md:1
-#, fuzzy
-msgid "# Futures"
-msgstr "# Schließungen"
-
-#: src/async/futures.md:3
-msgid ""
-"[`Future`](https://doc.rust-lang.org/std/future/trait.Future.html)\n"
-"is a trait, implemented by objects that represent an operation that may not be\n"
-"complete yet. A future can be polled, and `poll` returns a\n"
-"[`Poll`](https://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 uncommon) to\n"
-"implement `Future` for your own types. For example, the `JoinHandle` returned\n"
-"from `tokio::spawn` implements `Future` to allow joining to it."
-msgstr ""
-
-#: src/async/futures.md:27
-msgid ""
-"The `.await` keyword, applied to a Future, causes the current async function to\n"
-"pause until that Future is ready, and then evaluates to its output."
-msgstr ""
-
-#: src/async/futures.md:32
-msgid ""
-"* The `Future` and `Poll` types are implemented exactly as shown; click the\n"
-" links to show the implementations in the docs.\n"
-"\n"
-"* We will not get to `Pin` and `Context`, as we will focus on writing async\n"
-" code, rather than building new async primitives. Briefly:\n"
-"\n"
-" * `Context` allows a Future to schedule itself to be polled again when an\n"
-" event occurs.\n"
-"\n"
-" * `Pin` ensures that the Future isn't moved in memory, so that pointers into\n"
-" that future remain valid. This is required to allow references to remain\n"
-" valid after an `.await`."
-msgstr ""
-
-#: src/async/runtimes.md:1
-#, fuzzy
-msgid "# Runtimes and Tasks"
-msgstr "# Laufzeitgarantien"
-
-#: src/async/runtimes.md:3
-msgid ""
-"A *runtime* provides support for performing operations asynchronously (a\n"
-"*reactor*) and is responsible for executing futures (an *executor*). Rust does not have a\n"
-"\"built-in\" runtime, but several options are available:"
-msgstr ""
-
-#: src/async/runtimes.md:7
-msgid ""
-" * [Tokio](https://tokio.rs/) - performant, with a well-developed ecosystem of\n"
-" functionality like [Hyper](https://hyper.rs/) for HTTP or\n"
-" [Tonic](https://github.com/hyperium/tonic) for gRPC.\n"
-" * [async-std](https://async.rs/) - aims to be a \"std for async\", and includes a\n"
-" basic runtime in `async::task`.\n"
-" * [smol](https://docs.rs/smol/latest/smol/) - simple and lightweight"
-msgstr ""
-
-#: src/async/runtimes.md:14
-msgid ""
-"Several larger applications have their own runtimes. For example,\n"
-"[Fuchsia](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/lib/fuchsia-async/src/lib."
-"rs)\n"
-"already has one."
-msgstr ""
-
-#: src/async/runtimes.md:20
-msgid ""
-"* Note that of the listed runtimes, only Tokio is supported in the Rust\n"
-" playground. The playground also does not permit any I/O, so most interesting\n"
-" async things can't run in the playground.\n"
-"\n"
-"* Futures are \"inert\" in that they do not do anything (not even start an I/O\n"
-" operation) unless there is an executor polling them. This differs from JS\n"
-" Promises, for example, which will run to completion even if they are never\n"
-" used."
-msgstr ""
-
-#: src/async/runtimes/tokio.md:1
-msgid "# Tokio"
-msgstr ""
-
-#: src/async/runtimes/tokio.md:4
-msgid "Tokio provides: "
-msgstr ""
-
-#: src/async/runtimes/tokio.md:6
-msgid ""
-"* A multi-threaded runtime for executing asynchronous code.\n"
-"* An asynchronous version of the standard library.\n"
-"* A large ecosystem of libraries."
-msgstr ""
-
-#: src/async/runtimes/tokio.md:10
-msgid ""
-"```rust,editable,compile_fail\n"
-"use tokio::time;\n"
-"\n"
-"async fn count_to(count: i32) {\n"
-" for i in 1..=count {\n"
-" println!(\"Count in task: {i}!\");\n"
-" time::sleep(time::Duration::from_millis(5)).await;\n"
-" }\n"
-"}\n"
-"\n"
-"#[tokio::main]\n"
-"async fn main() {\n"
-" tokio::spawn(count_to(10));\n"
-"\n"
-" for i in 1..5 {\n"
-" println!(\"Main task: {i}\");\n"
-" time::sleep(time::Duration::from_millis(5)).await;\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/async/runtimes/tokio.md:33
-msgid ""
-"* With the `tokio::main` macro we can now make `main` async.\n"
-"\n"
-"* The `spawn` function creates a new, concurrent \"task\".\n"
-"\n"
-"* Note: `spawn` takes a `Future`, you don't call `.await` on `count_to`."
-msgstr ""
-
-#: src/async/runtimes/tokio.md:39
-msgid "**Further exploration:**"
-msgstr ""
-
-#: src/async/runtimes/tokio.md:41
-msgid ""
-"* Why does `count_to` not (usually) get to 10? This is an example of async\n"
-" cancellation. `tokio::spawn` returns a handle which can be awaited to wait\n"
-" until it finishes.\n"
-"\n"
-"* Try `count_to(10).await` instead of spawning.\n"
-"\n"
-"* Try awaiting the task returned from `tokio::spawn`."
-msgstr ""
-
-#: src/async/tasks.md:1
-#, fuzzy
-msgid "# Tasks"
-msgstr "## Aufgaben"
-
-#: src/async/tasks.md:3
-msgid ""
-"Runtimes have the concept of a \"task\", similar to a thread but much\n"
-"less resource-intensive."
-msgstr ""
-
-#: src/async/tasks.md:6
-msgid ""
-"A task has a single top-level future which the executor polls to make progress.\n"
-"That future may have one or more nested futures that its `poll` method polls,\n"
-"corresponding loosely to a call stack. Concurrency within a task is possible by\n"
-"polling multiple child futures, such as racing a timer and an I/O operation."
-msgstr ""
-
-#: src/async/tasks.md:11
-msgid ""
-"```rust,compile_fail\n"
-"use tokio::io::{self, AsyncReadExt, AsyncWriteExt};\n"
-"use tokio::net::TcpListener;\n"
-"\n"
-"#[tokio::main]\n"
-"async fn main() -> io::Result<()> {\n"
-" let listener = TcpListener::bind(\"127.0.0.1:6142\").await?;\n"
-"\tprintln!(\"listening on port 6142\");\n"
-"\n"
-" loop {\n"
-" let (mut socket, addr) = listener.accept().await?;\n"
-"\n"
-" println!(\"connection from {addr:?}\");\n"
-"\n"
-" tokio::spawn(async move {\n"
-" if let Err(e) = socket.write_all(b\"Who are you?\\n\").await {\n"
-" println!(\"socket error: {e:?}\");\n"
-" return;\n"
-" }\n"
-"\n"
-" let mut buf = vec![0; 1024];\n"
-" let reply = match socket.read(&mut buf).await {\n"
-" Ok(n) => {\n"
-" let name = std::str::from_utf8(&buf[..n]).unwrap().trim();\n"
-" format!(\"Thanks for dialing in, {name}!\\n\")\n"
-" }\n"
-" Err(e) => {\n"
-" println!(\"socket error: {e:?}\");\n"
-" return;\n"
-" }\n"
-" };\n"
-"\n"
-" if let Err(e) = socket.write_all(reply.as_bytes()).await {\n"
-" println!(\"socket error: {e:?}\");\n"
-" }\n"
-" });\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/async/tasks.md:53 src/async/control-flow/join.md:36
-msgid "Copy this example into your prepared `src/main.rs` and run it from there."
-msgstr ""
-
-#: src/async/tasks.md:55
-msgid ""
-"* Ask students to visualize what the state of the example server would be with a\n"
-" few connected clients. What tasks exist? What are their Futures?\n"
-"\n"
-"* This is the first time we've seen an `async` block. This is similar to a\n"
-" closure, but does not take any arguments. Its return value is a Future,\n"
-" similar to an `async fn`. \n"
-"\n"
-"* Refactor the async block into a function, and improve the error handling using `?`."
-msgstr ""
-
-#: src/async/channels.md:1
-#, fuzzy
-msgid "# Async Channels"
-msgstr "# Kanäle"
-
-#: src/async/channels.md:3
-msgid "Several crates have support for `async`/`await`. For instance `tokio` channels:"
-msgstr ""
-
-#: src/async/channels.md:5
-msgid ""
-"```rust,editable,compile_fail\n"
-"use tokio::sync::mpsc::{self, Receiver};\n"
-"\n"
-"async fn ping_handler(mut input: Receiver<()>) {\n"
-" let mut count: usize = 0;\n"
-"\n"
-" while let Some(_) = input.recv().await {\n"
-" count += 1;\n"
-" println!(\"Received {count} pings so far.\");\n"
-" }\n"
-"\n"
-" println!(\"ping_handler complete\");\n"
-"}\n"
-"\n"
-"#[tokio::main]\n"
-"async fn main() {\n"
-" let (sender, receiver) = mpsc::channel(32);\n"
-" let ping_handler_task = tokio::spawn(ping_handler(receiver));\n"
-" for i in 0..10 {\n"
-" sender.send(()).await.expect(\"Failed to send ping.\");\n"
-" println!(\"Sent {} pings so far.\", i + 1);\n"
-" }\n"
-"\n"
-" std::mem::drop(sender);\n"
-" ping_handler_task.await.expect(\"Something went wrong in ping handler task.\");\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/async/channels.md:35
-msgid ""
-"* Change the channel size to `3` and see how it affects the execution.\n"
-"\n"
-"* Overall, the interface is similar to the `sync` channels as seen in the\n"
-" [morning class](concurrency/channels.md).\n"
-"\n"
-"* Try removing the `std::mem::drop` call. What happens? Why?\n"
-"\n"
-"* The [Flume](https://docs.rs/flume/latest/flume/) crate has channels that\n"
-" implement both `sync` and `async` `send` and `recv`. This can be convenient\n"
-" for complex applications with both IO and heavy CPU processing tasks.\n"
-"\n"
-"* What makes working with `async` channels preferable is the ability to combine\n"
-" them with other `future`s to combine them and create complex control flow."
-msgstr ""
-
-#: src/async/control-flow.md:1
-#, fuzzy
-msgid "# Futures Control Flow"
-msgstr "# Kontrollfluss"
-
-#: src/async/control-flow.md:3
-msgid ""
-"Futures can be combined together to produce concurrent compute flow graphs. We\n"
-"have already seen tasks, that function as independent threads of execution."
-msgstr ""
-
-#: src/async/control-flow.md:6
-msgid ""
-"- [Join](control-flow/join.md)\n"
-"- [Select](control-flow/select.md)"
-msgstr ""
-
-#: src/async/control-flow/join.md:1
-msgid "# Join"
-msgstr ""
-
-#: src/async/control-flow/join.md:3
-msgid ""
-"A join operation waits until all of a set of futures are ready, and\n"
-"returns a collection of their results. This is similar to `Promise.all` in\n"
-"JavaScript or `asyncio.gather` in Python."
-msgstr ""
-
-#: src/async/control-flow/join.md:7
-msgid ""
-"```rust,editable,compile_fail\n"
-"use anyhow::Result;\n"
-"use futures::future;\n"
-"use reqwest;\n"
-"use std::collections::HashMap;\n"
-"\n"
-"async fn size_of_page(url: &str) -> Result {\n"
-" let resp = reqwest::get(url).await?;\n"
-" Ok(resp.text().await?.len())\n"
-"}\n"
-"\n"
-"#[tokio::main]\n"
-"async fn main() {\n"
-" let urls: [&str; 4] = [\n"
-" \"https://google.com\",\n"
-" \"https://httpbin.org/ip\",\n"
-" \"https://play.rust-lang.org/\",\n"
-" \"BAD_URL\",\n"
-" ];\n"
-" let futures_iter = urls.into_iter().map(size_of_page);\n"
-" let results = future::join_all(futures_iter).await;\n"
-" let page_sizes_dict: HashMap<&str, Result> =\n"
-" urls.into_iter().zip(results.into_iter()).collect();\n"
-" println!(\"{:?}\", page_sizes_dict);\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/async/control-flow/join.md:38
-msgid ""
-"* For multiple futures of disjoint types, you can use `std::future::join!` but\n"
-" you must know how many futures you will have at compile time. This is\n"
-" currently in the `futures` crate, soon to be stabilised in `std::future`.\n"
-"\n"
-"* The risk of `join` is that one of the futures may never resolve, this would\n"
-" cause your program to stall. \n"
-"\n"
-"* You can also combine `join_all` with `join!` for instance to join all requests\n"
-" to an http service as well as a database query.\n"
-"\n"
-"* Try adding a timeout to the future, using `futures::join!`."
-msgstr ""
-
-#: src/async/control-flow/select.md:1
-#, fuzzy
-msgid "# Select"
-msgstr "# Aufstellen"
-
-#: src/async/control-flow/select.md:3
-msgid ""
-"A select operation waits until any of a set of futures is ready, and responds to\n"
-"that future's result. In JavaScript, this is similar to `Promise.race`. In\n"
-"Python, it compares to `asyncio.wait(task_set,\n"
-"return_when=asyncio.FIRST_COMPLETED)`."
-msgstr ""
-
-#: src/async/control-flow/select.md:8
-msgid ""
-"This is usually a macro, similar to match, with each arm of the form `pattern =\n"
-"future => statement`. When the future is ready, the statement is executed with the\n"
-"variable bound to the future's result."
-msgstr ""
-
-#: src/async/control-flow/select.md:12
-msgid ""
-"```rust,editable,compile_fail\n"
-"use tokio::sync::mpsc::{self, Receiver};\n"
-"use tokio::time::{sleep, Duration};\n"
-"\n"
-"#[derive(Debug, PartialEq)]\n"
-"enum Animal {\n"
-" Cat { name: String },\n"
-" Dog { name: String },\n"
-"}\n"
-"\n"
-"async fn first_animal_to_finish_race(\n"
-" mut cat_rcv: Receiver,\n"
-" mut dog_rcv: Receiver,\n"
-") -> Option {\n"
-" tokio::select! {\n"
-" cat_name = cat_rcv.recv() => Some(Animal::Cat { name: cat_name? }),\n"
-" dog_name = dog_rcv.recv() => Some(Animal::Dog { name: dog_name? })\n"
-" }\n"
-"}\n"
-"\n"
-"#[tokio::main]\n"
-"async fn main() {\n"
-" let (cat_sender, cat_receiver) = mpsc::channel(32);\n"
-" let (dog_sender, dog_receiver) = mpsc::channel(32);\n"
-" tokio::spawn(async move {\n"
-" sleep(Duration::from_millis(500)).await;\n"
-" cat_sender\n"
-" .send(String::from(\"Felix\"))\n"
-" .await\n"
-" .expect(\"Failed to send cat.\");\n"
-" });\n"
-" tokio::spawn(async move {\n"
-" sleep(Duration::from_millis(50)).await;\n"
-" dog_sender\n"
-" .send(String::from(\"Rex\"))\n"
-" .await\n"
-" .expect(\"Failed to send dog.\");\n"
-" });\n"
-"\n"
-" let winner = first_animal_to_finish_race(cat_receiver, dog_receiver)\n"
-" .await\n"
-" .expect(\"Failed to receive winner\");\n"
-"\n"
-" println!(\"Winner is {winner:?}\");\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/async/control-flow/select.md:61
-msgid ""
-"* In this example, we have a race between a cat and a dog.\n"
-" `first_animal_to_finish_race` listens to both channels and will pick whichever\n"
-" arrives first. Since the dog takes 50ms, it wins against the cat that\n"
-" take 500ms seconds.\n"
-"\n"
-"* You can use `oneshot` channels in this example as the channels are supposed to\n"
-" receive only one `send`.\n"
-"\n"
-"* Try adding a deadline to the race, demonstrating selecting different sorts of\n"
-" futures.\n"
-"\n"
-"* Note that `select!` moves the values it is given. It is easiest to use\n"
-" when every execution of `select!` creates new futures. An alternative is to\n"
-" pass `&mut future` instead of the future itself, but this can lead to\n"
-" issues, further discussed in the pinning slide."
-msgstr ""
-
-#: src/async/pitfalls.md:1
-msgid "# Pitfalls of async/await"
-msgstr ""
-
-#: src/async/pitfalls.md:3
-msgid ""
-"Async / await provides convenient and efficient abstraction for concurrent asynchronous "
-"programming. However, the async/await model in Rust also comes with its share of pitfalls and "
-"footguns. We illustrate some of them in this chapter:"
-msgstr ""
-
-#: src/async/pitfalls.md:5
-msgid ""
-"- [Blocking the Executor](pitfalls/blocking-executor.md)\n"
-"- [Pin](pitfalls/pin.md)\n"
-"- [Async Traits](pitfall/async-traits.md)"
-msgstr ""
-
-#: src/async/pitfalls/blocking-executor.md:1
-msgid "# Blocking the executor"
-msgstr ""
-
-#: src/async/pitfalls/blocking-executor.md:3
-msgid ""
-"Most async runtimes only allow IO tasks to run concurrently.\n"
-"This means that CPU blocking tasks will block the executor and prevent other tasks from being "
-"executed.\n"
-"An easy workaround is to use async equivalent methods where possible."
-msgstr ""
-
-#: src/async/pitfalls/blocking-executor.md:7
-msgid ""
-"```rust,editable,compile_fail\n"
-"use futures::future::join_all;\n"
-"use std::time::Instant;\n"
-"\n"
-"async fn sleep_ms(start: &Instant, id: u64, duration_ms: u64) {\n"
-" std::thread::sleep(std::time::Duration::from_millis(duration_ms));\n"
-" println!(\n"
-" \"future {id} slept for {duration_ms}ms, finished after {}ms\",\n"
-" start.elapsed().as_millis()\n"
-" );\n"
-"}\n"
-"\n"
-"#[tokio::main(flavor = \"current_thread\")]\n"
-"async fn main() {\n"
-" let start = Instant::now();\n"
-" let sleep_futures = (1..=10).map(|t| sleep_ms(&start, t, t * 10));\n"
-" join_all(sleep_futures).await;\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/async/pitfalls/blocking-executor.md:29
-msgid ""
-"* Run the code and see that the sleeps happen consecutively rather than\n"
-" concurrently.\n"
-"\n"
-"* The `\"current_thread\"` flavor puts all tasks on a single thread. This makes the\n"
-" effect more obvious, but the bug is still present in the multi-threaded\n"
-" flavor.\n"
-"\n"
-"* Switch the `std::thread::sleep` to `tokio::time::sleep` and await its result.\n"
-"\n"
-"* Another fix would be to `tokio::task::spawn_blocking` which spawns an actual\n"
-" thread and transforms its handle into a future without blocking the executor.\n"
-"\n"
-"* You should not think of tasks as OS threads. They do not map 1 to 1 and most\n"
-" executors will allow many tasks to run on a single OS thread. This is\n"
-" particularly problematic when interacting with other libraries via FFI, where\n"
-" that library might depend on thread-local storage or map to specific OS\n"
-" threads (e.g., CUDA). Prefer `tokio::task::spawn_blocking` in such situations.\n"
-"\n"
-"* Use sync mutexes with care. Holding a mutex over an `.await` may cause another\n"
-" task to block, and that task may be running on the same thread."
-msgstr ""
-
-#: src/async/pitfalls/pin.md:1
-msgid "# Pin"
-msgstr ""
-
-#: src/async/pitfalls/pin.md:3
-msgid ""
-"When you await a future, all local variables (that would ordinarily be stored on\n"
-"a stack frame) are instead stored in the Future for the current async block. If your\n"
-"future has pointers to data on the stack, those pointers might get invalidated.\n"
-"This is unsafe."
-msgstr ""
-
-#: src/async/pitfalls/pin.md:8
-msgid ""
-"Therefore, you must guarantee that the addresses your future points to don't\n"
-"change. That is why we need to `pin` futures. Using the same future repeatedly\n"
-"in a `select!` often leads to issues with pinned values."
-msgstr ""
-
-#: src/async/pitfalls/pin.md:12
-msgid ""
-"```rust,editable,compile_fail\n"
-"use tokio::sync::{mpsc, oneshot};\n"
-"use tokio::task::spawn;\n"
-"use tokio::time::{sleep, Duration};\n"
-"\n"
-"// A work item. In this case, just sleep for the given time and respond\n"
-"// with a message on the `respond_on` channel.\n"
-"#[derive(Debug)]\n"
-"struct Work {\n"
-" input: u32,\n"
-" respond_on: oneshot::Sender,\n"
-"}\n"
-"\n"
-"// A worker which listens for work on a queue and performs it.\n"
-"async fn worker(mut work_queue: mpsc::Receiver) {\n"
-" let mut iterations = 0;\n"
-" loop {\n"
-" tokio::select! {\n"
-" Some(work) = work_queue.recv() => {\n"
-" sleep(Duration::from_millis(10)).await; // Pretend to work.\n"
-" work.respond_on\n"
-" .send(work.input * 1000)\n"
-" .expect(\"failed to send response\");\n"
-" iterations += 1;\n"
-" }\n"
-" // TODO: report number of iterations every 100ms\n"
-" }\n"
-" }\n"
-"}\n"
-"\n"
-"// A requester which requests work and waits for it to complete.\n"
-"async fn do_work(work_queue: &mpsc::Sender, input: u32) -> u32 {\n"
-" let (tx, rx) = oneshot::channel();\n"
-" work_queue\n"
-" .send(Work {\n"
-" input,\n"
-" respond_on: tx,\n"
-" })\n"
-" .await\n"
-" .expect(\"failed to send on work queue\");\n"
-" rx.await.expect(\"failed waiting for response\")\n"
-"}\n"
-"\n"
-"#[tokio::main]\n"
-"async fn main() {\n"
-" let (tx, rx) = mpsc::channel(10);\n"
-" spawn(worker(rx));\n"
-" for i in 0..100 {\n"
-" let resp = do_work(&tx, i).await;\n"
-" println!(\"work result for iteration {i}: {resp}\");\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/async/pitfalls/pin.md:68
-msgid ""
-"* You may recognize this as an example of the actor pattern. Actors\n"
-" typically call `select!` in a loop.\n"
-"\n"
-"* This serves as a summation of a few of the previous lessons, so take your time\n"
-" with it.\n"
-"\n"
-" * Naively add a `_ = sleep(Duration::from_millis(100)) => { println!(..) }`\n"
-" to the `select!`. This will never execute. Why?\n"
-"\n"
-" * Instead, add a `timeout_fut` containing that future outside of the `loop`:\n"
-"\n"
-" ```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"
-" ```\n"
-" * This still doesn't work. Follow the compiler errors, adding `&mut` to the\n"
-" `timeout_fut` in the `select!` to work around the move, then using\n"
-" `Box::pin`:\n"
-"\n"
-" ```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"
-" ```\n"
-"\n"
-" * This compiles, but once the timeout expires it is `Poll::Ready` on every\n"
-" iteration (a fused future would help with this). Update to reset\n"
-" `timeout_fut` every time it expires.\n"
-"\n"
-"* Box allocates on the heap. In some cases, `std::pin::pin!` (only recently\n"
-" stabilized, with older code often using `tokio::pin!`) is also an option, but\n"
-" that is difficult to use for a future that is reassigned.\n"
-"\n"
-"* Another alternative is to not use `pin` at all but spawn another task that will send to a "
-"`oneshot` channel every 100ms."
-msgstr ""
-
-#: src/async/pitfalls/async-traits.md:1
-#, fuzzy
-msgid "# Async Traits"
-msgstr "# Züge"
-
-#: src/async/pitfalls/async-traits.md:3
-msgid ""
-"Async methods in traits are not yet supported in the stable channel ([An experimental feature "
-"exists in nightly and should be stabilized in the mid term.](https://blog.rust-lang.org/inside-"
-"rust/2022/11/17/async-fn-in-trait-nightly.html))"
-msgstr ""
-
-#: src/async/pitfalls/async-traits.md:5
-msgid ""
-"The crate [async_trait](https://docs.rs/async-trait/latest/async_trait/) provides a workaround "
-"through a macro:"
-msgstr ""
-
-#: src/async/pitfalls/async-traits.md:7
-msgid ""
-"```rust,editable,compile_fail\n"
-"use async_trait::async_trait;\n"
-"use std::time::Instant;\n"
-"use tokio::time::{sleep, Duration};\n"
-"\n"
-"#[async_trait]\n"
-"trait Sleeper {\n"
-" async fn sleep(&self);\n"
-"}\n"
-"\n"
-"struct FixedSleeper {\n"
-" sleep_ms: u64,\n"
-"}\n"
-"\n"
-"#[async_trait]\n"
-"impl Sleeper for FixedSleeper {\n"
-" async fn sleep(&self) {\n"
-" sleep(Duration::from_millis(self.sleep_ms)).await;\n"
-" }\n"
-"}\n"
-"\n"
-"async fn run_all_sleepers_multiple_times(sleepers: Vec>, n_times: usize) {\n"
-" for _ in 0..n_times {\n"
-" println!(\"running all sleepers..\");\n"
-" for sleeper in &sleepers {\n"
-" let start = Instant::now();\n"
-" sleeper.sleep().await;\n"
-" println!(\"slept for {}ms\", start.elapsed().as_millis());\n"
-" }\n"
-" }\n"
-"}\n"
-"\n"
-"#[tokio::main]\n"
-"async fn main() {\n"
-" let sleepers: Vec> = vec![\n"
-" Box::new(FixedSleeper { sleep_ms: 50 }),\n"
-" Box::new(FixedSleeper { sleep_ms: 100 }),\n"
-" ];\n"
-" run_all_sleepers_multiple_times(sleepers, 5).await;\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/async/pitfalls/async-traits.md:49
-#, fuzzy
-msgid " "
-msgstr ""
-
-#: src/async/pitfalls/async-traits.md:51
-msgid ""
-"* `async_trait` is easy to use, but note that it's using heap allocations to\n"
-" achieve this. This heap allocation has performance overhead.\n"
-"\n"
-"* The challenges in language support for `async trait` are deep Rust and\n"
-" probably not worth describing in-depth. Niko Matsakis did a good job of\n"
-" explaining them in [this\n"
-" post](https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/)\n"
-" if you are interested in digging deeper.\n"
-"\n"
-"* Try creating a new sleeper struct that will sleep for a random amount of time\n"
-" and adding it to the Vec.\n"
-"\n"
-"* Try making the `sleep` call take `&mut self`."
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:1
-msgid "# Elevator Operation"
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:3
-msgid ""
-"Elevators seem simple. You press a button, doors open, you wait, and you're at\n"
-"the floor you requested. But implementing an elevator controller is surprisingly\n"
-"difficult! This exercise involves building a simple elevator control that\n"
-"operates in a simple simulator."
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:8
-msgid ""
-"The overall design of this elevator uses the actor pattern: you will implement a\n"
-"controller task that communicates with other components of the elevator system\n"
-"by sending and receiving messages."
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:12
-#, fuzzy
-msgid "## Getting Started"
-msgstr "# Destrukturierende Strukturen"
-
-#: src/exercises/day-4/elevator.md:14
-msgid ""
-"Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the "
-"`elevator`\n"
-"directory for the following files."
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:17 src/exercises/bare-metal/compass.md:26
-#: src/exercises/bare-metal/rtc.md:16
-#, fuzzy
-msgid "`src/main.rs`:"
-msgstr "_hello_rust/src/main.rs_:"
-
-#: src/exercises/day-4/elevator.md:21
-msgid ""
-"```rust,compile_fail\n"
-"use building::BuildingEvent;\n"
-"use tokio::sync::broadcast;\n"
-"\n"
-"mod building;\n"
-"mod controller;\n"
-"mod driver;\n"
-"\n"
-"#[tokio::main]\n"
-"async fn main() {\n"
-" let building = driver::make_building();\n"
-" let (building_task, events_rx, building_cmd_tx, driver_cmd_tx) = building.start();\n"
-"\n"
-" tokio::spawn(print_events(events_rx.resubscribe()));\n"
-" tokio::spawn(driver::driver(events_rx.resubscribe(), driver_cmd_tx));\n"
-" tokio::spawn(controller::controller(events_rx, building_cmd_tx));\n"
-" building_task.await.unwrap();\n"
-"}\n"
-"\n"
-"async fn print_events(mut events_rx: broadcast::Receiver) {\n"
-" while let Ok(evt) = events_rx.recv().await {\n"
-" println!(\"BuildingEvent::{:?}\", evt);\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:47
-#, fuzzy
-msgid "`src/building.rs`:"
-msgstr "_hello_rust/src/main.rs_:"
-
-#: src/exercises/day-4/elevator.md:49
-msgid ""
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:51
-msgid ""
-"```rust,compile_fail\n"
-"//! The building simulates floors and elevators.\n"
-"\n"
-"use tokio::sync::{broadcast, mpsc};\n"
-"use tokio::task;\n"
-"use tokio::time;\n"
-"\n"
-"#[derive(Debug, Clone)]\n"
-"pub enum Direction {\n"
-" Up,\n"
-" Down,\n"
-"}\n"
-"\n"
-"/// A passenger is a person with a destination floor in mind.\n"
-"#[derive(Debug)]\n"
-"struct Passenger {\n"
-" destination: FloorId,\n"
-"}\n"
-"\n"
-"/// FloorId identifies a floor. These are zero-based integers.\n"
-"pub type FloorId = usize;\n"
-"\n"
-"/// Floor represents the current status of a floor in the building.\n"
-"#[derive(Default, Debug)]\n"
-"struct Floor {\n"
-" passengers: Vec,\n"
-"}\n"
-"\n"
-"/// ElevatorId identifies an elevator in the building. These are zero-based integers.\n"
-"pub type ElevatorId = usize;\n"
-"\n"
-"/// Elevator represents the current status of an elevator in the building.\n"
-"#[derive(Default, Debug)]\n"
-"struct Elevator {\n"
-" /// Floor the elevator is currently on. In the simulation the elevator\n"
-" /// transports instantaneously from one floor to the next in a single\n"
-" /// simulation tick.\n"
-" position: FloorId,\n"
-" /// Destination floor for the elevator, if any. This can change at any time.\n"
-" destination: Option,\n"
-" /// Passengers currently on the elevator.\n"
-" passengers: Vec,\n"
-" /// True if the elevator is stopped with the doors open. The elevator\n"
-" /// will not move with the doors open, but they will close at the next\n"
-" /// tick of the simulation.\n"
-" doors_open: bool,\n"
-"}\n"
-"\n"
-"/// A BuildingEvent is an event that occurs in the building.\n"
-"#[derive(Debug, Clone)]\n"
-"pub enum BuildingEvent {\n"
-" /// A passenger has pressed a floor button in the elevator.\n"
-" FloorButtonPressed(ElevatorId, FloorId),\n"
-" /// A passenger on the given floor has pressed the call button.\n"
-" CallButtonPressed(FloorId, Direction),\n"
-" /// The elevator has arrived at the given floor. If this is the\n"
-" /// elevator's destination, then it will stop open its doors.\n"
-" AtFloor(ElevatorId, FloorId),\n"
-" /// A passenger has been delivered to their desired floor.\n"
-" PassengerDelivered(FloorId),\n"
-"}\n"
-"\n"
-"/// A BuildingCommand tells the building what to do.\n"
-"#[derive(Debug)]\n"
-"pub enum BuildingCommand {\n"
-" /// Set the elevator's destination. The elevator will close its doors\n"
-" /// if necessary and then begin moving toward this floor.\n"
-" GoToFloor(ElevatorId, FloorId),\n"
-"}\n"
-"\n"
-"/// A DriverCommand is a message from the driver to change the state of\n"
-"/// the building.\n"
-"#[derive(Debug)]\n"
-"pub enum DriverCommand {\n"
-" /// A passenger has arrived and is waiting for an elevator. The passenger will automatically\n"
-" /// press the relevant call button, board the elevator when it arrives, press their floor\n"
-" /// button, and depart when the doors open on their destination floor.\n"
-" PassengerArrived { at: FloorId, destination: FloorId },\n"
-"\n"
-" /// Halt all activity in the building and end the building task.\n"
-" Halt,\n"
-"}\n"
-"\n"
-"/// Building manages the current status of the building.\n"
-"#[derive(Debug)]\n"
-"pub struct Building {\n"
-" floors: Vec,\n"
-" elevators: Vec,\n"
-"}\n"
-"\n"
-"impl Building {\n"
-" pub fn new(num_floors: usize, num_elevators: usize) -> Self {\n"
-" let mut floors = vec![];\n"
-" for _ in 0..num_floors {\n"
-" floors.push(Floor::default());\n"
-" }\n"
-" let mut elevators = vec![];\n"
-" for _ in 0..num_elevators {\n"
-" elevators.push(Elevator::default());\n"
-" }\n"
-" Self { floors, elevators }\n"
-" }\n"
-"\n"
-" /// Start the building. The resulting channels are used to communicate\n"
-" /// with the building\n"
-" pub fn start(\n"
-" self,\n"
-" ) -> (\n"
-" task::JoinHandle<()>,\n"
-" broadcast::Receiver,\n"
-" mpsc::Sender,\n"
-" mpsc::Sender,\n"
-" ) {\n"
-" let (events_tx, events_rx) = broadcast::channel(10);\n"
-" let (building_cmd_tx, building_cmd_rx) = mpsc::channel(10);\n"
-" let (driver_cmd_tx, driver_cmd_rx) = mpsc::channel(10);\n"
-" let task = tokio::spawn(self.run(events_tx, building_cmd_rx, driver_cmd_rx));\n"
-" (task, events_rx, building_cmd_tx, driver_cmd_tx)\n"
-" }\n"
-"\n"
-" async fn run(\n"
-" mut self,\n"
-" events_tx: broadcast::Sender,\n"
-" mut building_cmd_rx: mpsc::Receiver,\n"
-" mut driver_cmd_rx: mpsc::Receiver,\n"
-" ) {\n"
-" let mut ticker = time::interval(time::Duration::from_millis(100));\n"
-" loop {\n"
-" tokio::select! {\n"
-" Some(BuildingCommand::GoToFloor(el, fl)) = building_cmd_rx.recv() => {\n"
-" self.elevators[el].destination = Some(fl);\n"
-" }\n"
-" Some(cmd) = driver_cmd_rx.recv() => {\n"
-" match cmd {\n"
-" DriverCommand::PassengerArrived{at, destination} => {\n"
-" self.new_passenger(&events_tx, at, destination).await;\n"
-" }\n"
-" DriverCommand::Halt => return,\n"
-" }\n"
-" }\n"
-" _ = ticker.tick() => self.move_elevators(&events_tx).await\n"
-" }\n"
-" }\n"
-" }\n"
-"\n"
-" /// Move the elevators toward their destinations.\n"
-" async fn move_elevators(&mut self, events_tx: &broadcast::Sender) {\n"
-" for el in 0..self.elevators.len() {\n"
-" let elevator = &mut self.elevators[el];\n"
-"\n"
-" // If the elevator's doors are open, close them and wait for the next tick.\n"
-" if elevator.doors_open {\n"
-" elevator.doors_open = false;\n"
-" continue;\n"
-" }\n"
-"\n"
-" // If the elevator has somewhere to go, move toward it.\n"
-" if let Some(dest) = elevator.destination {\n"
-" if dest > elevator.position {\n"
-" elevator.position += 1;\n"
-" }\n"
-" if dest < elevator.position {\n"
-" elevator.position -= 1;\n"
-" }\n"
-" events_tx\n"
-" .send(BuildingEvent::AtFloor(el, elevator.position))\n"
-" .unwrap();\n"
-"\n"
-" // If the elevator has reached its destination, open\n"
-" // the doors and let passengers get on and off.\n"
-" if elevator.position == dest {\n"
-" elevator.destination = None;\n"
-" elevator.doors_open = true;\n"
-" self.exchange_passengers(&events_tx, el).await;\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-"\n"
-" /// Handle a new passenger arriving at the given floor.\n"
-" async fn new_passenger(\n"
-" &mut self,\n"
-" events_tx: &broadcast::Sender,\n"
-" at: FloorId,\n"
-" destination: FloorId,\n"
-" ) {\n"
-" println!(\"Passenger arrived at {} going to {}\", at, destination);\n"
-" if at == destination {\n"
-" events_tx\n"
-" .send(BuildingEvent::PassengerDelivered(destination))\n"
-" .unwrap();\n"
-" return;\n"
-" }\n"
-"\n"
-" self.floors[at].passengers.push(Passenger { destination });\n"
-" let dir = if at < destination {\n"
-" Direction::Up\n"
-" } else {\n"
-" Direction::Down\n"
-" };\n"
-" events_tx\n"
-" .send(BuildingEvent::CallButtonPressed(at, dir))\n"
-" .unwrap();\n"
-" }\n"
-"\n"
-" /// The doors for the given elevator are open, so take on and discharge passengers.\n"
-" async fn exchange_passengers(\n"
-" &mut self,\n"
-" events_tx: &broadcast::Sender,\n"
-" el: ElevatorId,\n"
-" ) {\n"
-" let elevator = &mut self.elevators[el];\n"
-" let fl = elevator.position;\n"
-"\n"
-" // Handle passengers leaving the elevator at their floor.\n"
-" let (this_floor, other_floors): (Vec, Vec) = elevator\n"
-" .passengers\n"
-" .drain(..)\n"
-" .partition(|px| px.destination == fl);\n"
-" for px in this_floor {\n"
-" events_tx\n"
-" .send(BuildingEvent::PassengerDelivered(px.destination))\n"
-" .unwrap();\n"
-" }\n"
-" elevator.passengers = other_floors;\n"
-"\n"
-" // Handle passengers entering the elevator.\n"
-" for px in self.floors[fl].passengers.drain(..) {\n"
-" events_tx\n"
-" .send(BuildingEvent::FloorButtonPressed(el, px.destination))\n"
-" .unwrap();\n"
-" elevator.passengers.push(px);\n"
-" }\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:288
-#, fuzzy
-msgid "`src/driver.rs`:"
-msgstr "_hello_rust/src/main.rs_:"
-
-#: src/exercises/day-4/elevator.md:290
-msgid ""
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:292
-msgid ""
-"```rust,compile_fail\n"
-"//! The driver controls when and where passengers arrive.\n"
-"\n"
-"use crate::building::{Building, BuildingEvent, DriverCommand};\n"
-"use tokio::sync::{broadcast, mpsc};\n"
-"\n"
-"/// Create a new building to be driven by this driver.\n"
-"pub fn make_building() -> Building {\n"
-" Building::new(3, 1)\n"
-"}\n"
-"\n"
-"/// Simulate people arriving at the ground floor and going to the first floor, one by one.\n"
-"pub async fn driver(\n"
-" mut events_rx: broadcast::Receiver,\n"
-" driver_cmd_tx: mpsc::Sender,\n"
-") {\n"
-" for _ in 0..3 {\n"
-" // A passenger has arrived..\n"
-" driver_cmd_tx\n"
-" .send(DriverCommand::PassengerArrived {\n"
-" at: 0,\n"
-" destination: 2,\n"
-" })\n"
-" .await\n"
-" .unwrap();\n"
-"\n"
-" // Wait until they are delivered..\n"
-" while let Ok(evt) = events_rx.recv().await {\n"
-" if let BuildingEvent::PassengerDelivered(_) = evt {\n"
-" break;\n"
-" }\n"
-" }\n"
-" }\n"
-"\n"
-" driver_cmd_tx.send(DriverCommand::Halt).await.unwrap();\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:330
-#, fuzzy
-msgid "`src/controller.rs`:"
-msgstr "_hello_rust/src/main.rs_:"
-
-#: src/exercises/day-4/elevator.md:332
-msgid ""
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:334
-msgid ""
-"```rust,compile_fail\n"
-"//! The controller directs the elevators to operate so that passengers\n"
-"//! get to their destinations.\n"
-"\n"
-"use crate::building::{BuildingCommand, BuildingEvent};\n"
-"use tokio::sync::{broadcast, mpsc};\n"
-"\n"
-"pub async fn controller(\n"
-" mut events_rx: broadcast::Receiver,\n"
-" building_cmd_tx: mpsc::Sender,\n"
-") {\n"
-" while let Ok(evt) = events_rx.recv().await {\n"
-" match evt {\n"
-" BuildingEvent::CallButtonPressed(at, _) => {\n"
-" building_cmd_tx\n"
-" .send(BuildingCommand::GoToFloor(0, at))\n"
-" .await\n"
-" .unwrap();\n"
-" }\n"
-" BuildingEvent::FloorButtonPressed(_, destination) => {\n"
-" building_cmd_tx\n"
-" .send(BuildingCommand::GoToFloor(0, destination))\n"
-" .await\n"
-" .unwrap();\n"
-" }\n"
-" _ => {}\n"
-" }\n"
-" }\n"
-"}\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:365 src/exercises/bare-metal/compass.md:64
-#: src/exercises/bare-metal/rtc.md:380
-msgid "`Cargo.toml` (you shouldn't need to change this):"
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:369
-msgid ""
-"```toml\n"
-"[workspace]\n"
-"\n"
-"[package]\n"
-"name = \"elevator\"\n"
-"version = \"0.1.0\"\n"
-"edition = \"2021\"\n"
-"\n"
-"[dependencies]\n"
-"tokio = { version = \"1.26.0\", features = [\"full\"] }\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:381
-#, fuzzy
-msgid "Use `cargo run` to run the elevator simulation."
-msgstr "Verwenden Sie \"Cargo Test\", um die Komponententests zu finden und auszuführen."
-
-#: src/exercises/day-4/elevator.md:383
-#, fuzzy
-msgid "## Exercises"
-msgstr "# Übungen"
-
-#: src/exercises/day-4/elevator.md:385
-msgid ""
-"Begin by implementing a controller that can transport the passengers provided by\n"
-"the simple driver. There is only one elevator, and passengers always go from\n"
-"floor 0 to floor 2, one-by-one."
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:389
-msgid "Once you have this done, make the problem more complex. Suggested tasks:"
-msgstr ""
-
-#: src/exercises/day-4/elevator.md:391
-msgid ""
-" * Make the driver more complex, with passengers arriving at random floors with\n"
-" random destinations at random times.\n"
-"\n"
-" * Create a building with more than one elevator, and adjust the controller to\n"
-" handle this efficiently.\n"
-"\n"
-" * Add additional events and metadata to analyze your controller's efficiency.\n"
-" What is the distribution of wait time for passengers? Is the result fair?\n"
-"\n"
-" * Modify the building to support a maximum passenger capacity for each\n"
-" elevator, and modify the controller to take this information into account.\n"
-"\n"
-" * Update the driver to simulate business traffic, with lots of passengers going\n"
-" up from the ground floor at the same time, and those passengers returning to\n"
-" the ground floor some time later. Can your controller adjust to these\n"
-" circumstances?\n"
-"\n"
-" * Modify the building to support \"destination dispatch\", where passengers\n"
-" signal their destination floor in the elevator lobby, before boarding the\n"
-" elevator.\n"
-"\n"
-" * If you are taking the course with other students, trade controllers or\n"
-" drivers with another student to see how robust your design is.\n"
-"\n"
-" * Build a textual or graphical display of the elevators as they run."
-msgstr ""
-
-#: src/thanks.md:1
-#, fuzzy
-msgid "# Thanks!"
-msgstr "# Danke!"
-
-#: src/thanks.md:3
-#, fuzzy
-msgid ""
-"_Thank you for taking Comprehensive Rust 🦀!_ We hope you enjoyed it and that it\n"
-"was useful."
-msgstr ""
-"_Vielen Dank, dass Sie Comprehensive Rust 🦀 genommen haben!_ Wir hoffen, dass es Ihnen gefallen "
-"hat und dass es\n"
-"war nützlich."
-
-#: src/thanks.md:6
-#, fuzzy
-msgid ""
-"We've had a lot of fun putting the course together. The course is not perfect,\n"
-"so if you spotted any mistakes or have ideas for improvements, please get in\n"
-"[contact with us on\n"
-"GitHub](https://github.com/google/comprehensive-rust/discussions). We would love\n"
-"to hear from you."
-msgstr ""
-"Es hat uns viel Spaß gemacht, den Kurs zusammenzustellen. Der Kurs ist nicht perfekt,\n"
-"Wenn Sie also Fehler entdeckt haben oder Verbesserungsvorschläge haben, melden Sie sich bitte\n"
-"[Kontakt mit uns auf\n"
-"GitHub](https://github.com/google/comprehensive-rust/discussions). Wir würden lieben\n"
-"von dir zu hören."
-
-#: src/other-resources.md:1
-#, fuzzy
-msgid "# Other Rust Resources"
-msgstr "# Andere Rostressourcen"
-
-#: src/other-resources.md:3
-#, fuzzy
-msgid ""
-"The Rust community has created a wealth of high-quality and free resources\n"
-"online."
-msgstr ""
-"Die Rust-Community hat eine Fülle hochwertiger und kostenloser Ressourcen geschaffen\n"
-"online."
-
-#: src/other-resources.md:6
-#, fuzzy
-msgid "## Official Documentation"
-msgstr "## Offizielle Dokumentation"
-
-#: src/other-resources.md:8
-#, fuzzy
-msgid "The Rust project hosts many resources. These cover Rust in general:"
-msgstr "Das Rust-Projekt beherbergt viele Ressourcen. Diese decken Rust im Allgemeinen ab:"
-
-#: src/other-resources.md:10
-#, fuzzy
-msgid ""
-"* [The Rust Programming Language](https://doc.rust-lang.org/book/): the\n"
-" canonical free book about Rust. Covers the language in detail and includes a\n"
-" few projects for people to build.\n"
-"* [Rust By Example](https://doc.rust-lang.org/rust-by-example/): covers the Rust\n"
-" syntax via a series of examples which showcase different constructs. Sometimes\n"
-" includes small exercises where you are asked to expand on the code in the\n"
-" examples.\n"
-"* [Rust Standard Library](https://doc.rust-lang.org/std/): full documentation of\n"
-" the standard library for Rust.\n"
-"* [The Rust Reference](https://doc.rust-lang.org/reference/): an incomplete book\n"
-" which describes the Rust grammar and memory model."
-msgstr ""
-"* [Die Programmiersprache Rust](https://doc.rust-lang.org/book/): die\n"
-" Kanonisches kostenloses Buch über Rust. Deckt die Sprache im Detail ab und enthält a\n"
-" wenige Projekte für Menschen zu bauen.\n"
-"* [Rust By Example](https://doc.rust-lang.org/rust-by-example/): deckt den Rust ab\n"
-" Syntax über eine Reihe von Beispielen, die verschiedene Konstrukte demonstrieren. Manchmal\n"
-" enthält kleine Übungen, in denen Sie aufgefordert werden, den Code in der zu erweitern\n"
-" Beispiele.\n"
-"* [Rust Standard Library](https://doc.rust-lang.org/std/): vollständige Dokumentation von\n"
-" die Standardbibliothek für Rust.\n"
-"* [The Rust Reference](https://doc.rust-lang.org/reference/): ein unvollständiges Buch\n"
-" das die Rust-Grammatik und das Speichermodell beschreibt."
-
-#: src/other-resources.md:22
-#, fuzzy
-msgid "More specialized guides hosted on the official Rust site:"
-msgstr "Weitere spezialisierte Guides, die auf der offiziellen Rust-Website gehostet werden:"
-
-#: src/other-resources.md:24
-#, fuzzy
-msgid ""
-"* [The Rustonomicon](https://doc.rust-lang.org/nomicon/): covers unsafe Rust,\n"
-" including working with raw pointers and interfacing with other languages\n"
-" (FFI).\n"
-"* [Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/):\n"
-" covers the new asynchronous programming model which was introduced after the\n"
-" Rust Book was written.\n"
-"* [The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/): an\n"
-" introduction to using Rust on embedded devices without an operating system."
-msgstr ""
-"* [The Rustonomicon](https://doc.rust-lang.org/nomicon/): deckt unsicheres Rust ab,\n"
-" einschließlich der Arbeit mit rohen Zeigern und der Anbindung an andere Sprachen\n"
-" (FFI).\n"
-"* [Asynchrone Programmierung in Rust](https://rust-lang.github.io/async-book/):\n"
-" deckt das neue asynchrone Programmiermodell ab, das nach dem eingeführt wurde\n"
-" Rust Book wurde geschrieben.\n"
-"* [Das eingebettete Rust-Buch] (https://doc.rust-lang.org/stable/embedded-book/): an\n"
-" Einführung in die Verwendung von Rust auf eingebetteten Geräten ohne Betriebssystem."
-
-#: src/other-resources.md:33
-#, fuzzy
-msgid "## Unofficial Learning Material"
-msgstr "## Inoffizielles Lernmaterial"
-
-#: src/other-resources.md:35
-#, fuzzy
-msgid "A small selection of other guides and tutorial for Rust:"
-msgstr "Eine kleine Auswahl an weiteren Guides und Tutorials für Rust:"
-
-#: src/other-resources.md:37
-#, fuzzy
-msgid ""
-"* [Learn Rust the Dangerous Way](http://cliffle.com/p/dangerust/): covers Rust\n"
-" from the perspective of low-level C programmers.\n"
-"* [Rust for Embedded C\n"
-" Programmers](https://docs.opentitan.org/doc/ug/rust_for_c/): covers Rust from\n"
-" the perspective of developers who write firmware in C.\n"
-"* [Rust for professionals](https://overexact.com/rust-for-professionals/):\n"
-" covers the syntax of Rust using side-by-side comparisons with other languages\n"
-" such as C, C++, Java, JavaScript, and Python.\n"
-"* [Rust on Exercism](https://exercism.org/tracks/rust): 100+ exercises to help\n"
-" you learn Rust.\n"
-"* [Ferrous Teaching\n"
-" Material](https://ferrous-systems.github.io/teaching-material/index.html): a\n"
-" series of small presentations covering both basic and advanced part of the\n"
-" Rust language. Other topics such as WebAssembly, and async/await are also\n"
-" covered.\n"
-"* [Beginner's Series to\n"
-" Rust](https://docs.microsoft.com/en-us/shows/beginners-series-to-rust/) and\n"
-" [Take your first steps with\n"
-" Rust](https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/): two\n"
-" Rust guides aimed at new developers. The first is a set of 35 videos and the\n"
-" second is a set of 11 modules which covers Rust syntax and basic constructs.\n"
-"* [Learn Rust With Entirely Too Many Linked\n"
-" Lists](https://rust-unofficial.github.io/too-many-lists/): in-depth\n"
-" exploration of Rust's memory management rules, through implementing a few\n"
-" different types of list structures."
-msgstr ""
-"* [Learn Rust the Dangerous Way](http://cliffle.com/p/dangerust/): deckt Rust ab\n"
-" aus der Perspektive von Low-Level-C-Programmierern.\n"
-"* [Rost für eingebettetes C\n"
-" Programmierer] (https://docs.opentitan.org/doc/ug/rust_for_c/): deckt Rust ab\n"
-" die Perspektive von Entwicklern, die Firmware in C schreiben.\n"
-"* [Rost für Profis](https://overexact.com/rust-for-professionals/):\n"
-" deckt die Syntax von Rust durch Side-by-Side-Vergleiche mit anderen Sprachen ab\n"
-" wie C, C++, Java, JavaScript und Python.\n"
-"* [Rust on Exercism](https://exercism.org/tracks/rust): Über 100 hilfreiche Übungen\n"
-" Sie lernen Rost.\n"
-"* [Eisenlehre\n"
-" Material](https://ferrous-systems.github.io/teaching-material/index.html): a\n"
-" Reihe von kleinen Präsentationen, die sowohl den grundlegenden als auch den fortgeschrittenen "
-"Teil des\n"
-" Rostige Sprache. Andere Themen wie WebAssembly und async/await sind ebenfalls enthalten\n"
-" bedeckt.\n"
-"* [Anfängerserie bis\n"
-" Rust](https://docs.microsoft.com/en-us/shows/beginners-series-to-rust/) und\n"
-" [Machen Sie Ihre ersten Schritte mit\n"
-" Rust](https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/): zwei\n"
-" Rust-Leitfäden für neue Entwickler. Die erste ist eine Reihe von 35 Videos und die\n"
-" Das zweite ist ein Satz von 11 Modulen, der die Rust-Syntax und grundlegende Konstrukte abdeckt."
-
-#: src/other-resources.md:63
-#, fuzzy
-msgid ""
-"Please see the [Little Book of Rust Books](https://lborb.github.io/book/) for\n"
-"even more Rust books."
-msgstr ""
-"Weitere Informationen finden Sie im [Little Book of Rust Books] (https://lborb.github.io/book/).\n"
-"noch mehr Rust-Bücher."
-
-#: src/credits.md:1
-#, fuzzy
-msgid "# Credits"
-msgstr "# Credits"
-
-#: src/credits.md:3
-#, fuzzy
-msgid ""
-"The material here builds on top of the many great sources of Rust documentation.\n"
-"See the page on [other resources](other-resources.md) for a full list of useful\n"
-"resources."
-msgstr ""
-"Das Material hier baut auf den vielen großartigen Quellen der Rust-Dokumentation auf.\n"
-"Auf der Seite [andere Ressourcen] (other-resources.md) finden Sie eine vollständige Liste "
-"nützlicher Ressourcen\n"
-"Ressourcen."
-
-#: src/credits.md:7
-#, fuzzy
-msgid ""
-"The material of Comprehensive Rust is licensed under the terms of the Apache 2.0\n"
-"license, please see [`LICENSE`](../LICENSE) for details."
-msgstr ""
-"Das Material von Comprehensive Rust ist unter den Bedingungen von Apache 2.0 lizenziert\n"
-"Lizenz finden Sie unter [`LICENSE`](../LICENSE) für Einzelheiten."
-
-#: src/credits.md:10
-#, fuzzy
-msgid "## Rust by Example"
-msgstr "## Rost zum Beispiel"
-
-#: src/credits.md:12
-#, fuzzy
-msgid ""
-"Some examples and exercises have been copied and adapted from [Rust by\n"
-"Example](https://doc.rust-lang.org/rust-by-example/). Please see the\n"
-"`third_party/rust-by-example/` directory for details, including the license\n"
-"terms."
-msgstr ""
-"Einige Beispiele und Übungen wurden aus [Rust by\n"
-"Beispiel](https://doc.rust-lang.org/rust-by-example/). Bitte sehen Sie sich ... an\n"
-"`third_party/rust-by-example/`-Verzeichnis für Details, einschließlich der Lizenz\n"
-"Bedingungen."
-
-#: src/credits.md:17
-#, fuzzy
-msgid "## Rust on Exercism"
-msgstr "## Rost auf Übung"
-
-#: src/credits.md:19
-#, fuzzy
-msgid ""
-"Some exercises have been copied and adapted from [Rust on\n"
-"Exercism](https://exercism.org/tracks/rust). Please see the\n"
-"`third_party/rust-on-exercism/` directory for details, including the license\n"
-"terms."
-msgstr ""
-"Einige Übungen wurden von [Rust on\n"
-"Übung] (https://exercism.org/tracks/rust). Bitte sehen Sie sich ... an\n"
-"`third_party/rust-on-exercism/`-Verzeichnis für Details, einschließlich der Lizenz\n"
-"Bedingungen."
-
-#: src/credits.md:24
-#, fuzzy
-msgid "## CXX"
-msgstr "##CXX"
-
-#: src/credits.md:26
-#, fuzzy
-msgid ""
-"The [Interoperability with C++](android/interoperability/cpp.md) section uses an\n"
-"image from [CXX](https://cxx.rs/). Please see the `third_party/cxx/` directory\n"
-"for details, including the license terms."
-msgstr ""
-"Der Abschnitt [Interoperability with C++](android/interoperability/cpp.md) verwendet eine\n"
-"Bild von [CXX](https://cxx.rs/). Bitte sehen Sie sich das Verzeichnis `third_party/cxx/` an\n"
-"für Details, einschließlich der Lizenzbedingungen."
-
-#: src/welcome-bare-metal.md:1
+#: src/bare-metal.md:1
#, fuzzy
msgid "# Welcome to Bare Metal Rust"
msgstr "# Willkommen bei Comprehensive Rust 🦀"
-#: src/welcome-bare-metal.md:3
+#: src/bare-metal.md:3
msgid ""
"This is a standalone one-day course about bare-metal Rust, aimed at people who are familiar with "
"the\n"
@@ -14637,14 +12243,14 @@ msgid ""
"experience with bare-metal programming in some other language such as C."
msgstr ""
-#: src/welcome-bare-metal.md:7
+#: src/bare-metal.md:7
msgid ""
"Today we will talk about 'bare-metal' Rust: running Rust code without an OS underneath us. This "
"will\n"
"be divided into several parts:"
msgstr ""
-#: src/welcome-bare-metal.md:10
+#: src/bare-metal.md:10
msgid ""
"- What is `no_std` Rust?\n"
"- Writing firmware for microcontrollers.\n"
@@ -14652,7 +12258,7 @@ msgid ""
"- Some useful crates for bare-metal Rust development."
msgstr ""
-#: src/welcome-bare-metal.md:15
+#: src/bare-metal.md:15
msgid ""
"For the microcontroller part of the course we will use the [BBC micro:bit](https://microbit.org/) "
"v2\n"
@@ -14663,11 +12269,11 @@ msgid ""
"an on-board SWD debugger."
msgstr ""
-#: src/welcome-bare-metal.md:20
+#: src/bare-metal.md:20
msgid "To get started, install some tools we'll need later. On gLinux or Debian:"
msgstr ""
-#: src/welcome-bare-metal.md:22
+#: src/bare-metal.md:22
msgid ""
"```bash\n"
"sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom pkg-config qemu-system-"
@@ -14679,11 +12285,11 @@ msgid ""
"```"
msgstr ""
-#: src/welcome-bare-metal.md:30
+#: src/bare-metal.md:30
msgid "And give users in the `plugdev` group access to the micro:bit programmer:"
msgstr ""
-#: src/welcome-bare-metal.md:32
+#: src/bare-metal.md:32
msgid ""
"```bash\n"
"echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", GROUP=\"plugdev\"' |\\\n"
@@ -14692,11 +12298,11 @@ msgid ""
"```"
msgstr ""
-#: src/welcome-bare-metal.md:38
+#: src/bare-metal.md:38
msgid "On MacOS:"
msgstr ""
-#: src/welcome-bare-metal.md:40
+#: src/bare-metal.md:40
msgid ""
"```bash\n"
"xcode-select --install\n"
@@ -15474,6 +13080,17 @@ msgid ""
"directory for the following files."
msgstr ""
+#: src/exercises/bare-metal/compass.md:26 src/exercises/bare-metal/rtc.md:19
+#, fuzzy
+msgid "`src/main.rs`:"
+msgstr "_hello_rust/src/main.rs_:"
+
+#: src/exercises/bare-metal/compass.md:28 src/exercises/bare-metal/rtc.md:21
+#: src/exercises/concurrency/dining-philosophers.md:17 src/exercises/concurrency/link-checker.md:55
+#: src/exercises/concurrency/dining-philosophers-async.md:11
+msgid ""
+msgstr ""
+
#: src/exercises/bare-metal/compass.md:30
msgid ""
"```rust,compile_fail\n"
@@ -15511,6 +13128,16 @@ 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:66 src/exercises/bare-metal/rtc.md:387
+#: src/exercises/concurrency/dining-philosophers.md:63 src/exercises/concurrency/link-checker.md:35
+#: src/exercises/concurrency/dining-philosophers-async.md:60 src/exercises/concurrency/chat-app.md:17
+msgid ""
+msgstr ""
+
#: src/exercises/bare-metal/compass.md:68
msgid ""
"```toml\n"
@@ -15553,11 +13180,11 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/compass.md:100 src/exercises/bare-metal/rtc.md:980
+#: 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:102 src/exercises/bare-metal/rtc.md:982
+#: src/exercises/bare-metal/compass.md:102 src/exercises/bare-metal/rtc.md:987
msgid ""
msgstr ""
@@ -15667,7 +13294,7 @@ msgstr ""
#: src/bare-metal/aps/inline-assembly.md:39
msgid ""
-"(If you actually want to do this, use the [`psci`][1] crate which has wrappers for all these "
+"(If you actually want to do this, use the [`smccc`][1] crate which has wrappers for all these "
"functions.)"
msgstr ""
@@ -16073,7 +13700,8 @@ msgid ""
"use core::fmt::Write;\n"
"use core::panic::PanicInfo;\n"
"use log::error;\n"
-"use psci::system_off;\n"
+"use smccc::psci::system_off;\n"
+"use smccc::Hvc;\n"
"\n"
"/// Base address of the primary PL011 UART.\n"
"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n"
@@ -16100,12 +13728,12 @@ msgid ""
" }\n"
"\n"
" writeln!(uart, \"Bye!\").unwrap();\n"
-" system_off().unwrap();\n"
+" system_off::().unwrap();\n"
"}\n"
"```"
msgstr ""
-#: src/bare-metal/aps/better-uart/using.md:50
+#: src/bare-metal/aps/better-uart/using.md:51
msgid ""
"* As in the [inline assembly](../inline-assembly.md) example, this `main` function is called from "
"our\n"
@@ -16186,7 +13814,8 @@ msgid ""
"use crate::pl011::Uart;\n"
"use core::panic::PanicInfo;\n"
"use log::{error, info, LevelFilter};\n"
-"use psci::system_off;\n"
+"use smccc::psci::system_off;\n"
+"use smccc::Hvc;\n"
"\n"
"/// Base address of the primary PL011 UART.\n"
"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n"
@@ -16202,19 +13831,19 @@ msgid ""
"\n"
" assert_eq!(x1, 42);\n"
"\n"
-" system_off().unwrap();\n"
+" system_off::().unwrap();\n"
"}\n"
"\n"
"#[panic_handler]\n"
"fn panic(info: &PanicInfo) -> ! {\n"
" error!(\"{info}\");\n"
-" system_off().unwrap();\n"
+" system_off::().unwrap();\n"
" loop {}\n"
"}\n"
"```"
msgstr ""
-#: src/bare-metal/aps/logging/using.md:45
+#: src/bare-metal/aps/logging/using.md:46
msgid ""
"* Note that our panic handler can now log details of panics.\n"
"* Run the example in QEMU with `make qemu_logger` under `src/bare-metal/aps/examples`."
@@ -16470,6 +14099,11 @@ msgid ""
"* The Rust Playground includes `spin`, so this example will run fine inline."
msgstr ""
+#: src/bare-metal/android.md:1
+#, fuzzy
+msgid "# Android"
+msgstr "# Android"
+
#: src/bare-metal/android.md:3
msgid ""
"To build a bare-metal Rust binary in AOSP, you need to use a `rust_ffi_static` Soong rule to "
@@ -16580,17 +14214,21 @@ msgid ""
" in the future. (Call [`core::hint::spin_loop`][3] inside the loop.)\n"
"3. _Extension if you have time:_ Enable and handle the interrupt generated by the RTC match. You "
"can\n"
-" use the driver provided in the `arm-gic` crate to configure the Arm Generic Interrupt "
-"Controller."
+" use the driver provided in the [`arm-gic`][4] crate to configure the Arm Generic Interrupt "
+"Controller.\n"
+" - Use the RTC interrupt, which is wired to the GIC as `IntId::spi(2)`.\n"
+" - Once the interrupt is enabled, you can put the core to sleep via `arm_gic::wfi()`, which will "
+"cause the core to sleep until it receives an interrupt.\n"
+" "
msgstr ""
-#: src/exercises/bare-metal/rtc.md:13
+#: src/exercises/bare-metal/rtc.md:16
msgid ""
"Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the `rtc`\n"
"directory for the following files."
msgstr ""
-#: src/exercises/bare-metal/rtc.md:20
+#: src/exercises/bare-metal/rtc.md:23
msgid ""
"```rust,compile_fail\n"
"#![no_main]\n"
@@ -16604,7 +14242,8 @@ msgid ""
"use arm_gic::gicv3::GicV3;\n"
"use core::panic::PanicInfo;\n"
"use log::{error, info, trace, LevelFilter};\n"
-"use psci::system_off;\n"
+"use smccc::psci::system_off;\n"
+"use smccc::Hvc;\n"
"\n"
"/// Base addresses of the GICv3.\n"
"const GICD_BASE_ADDRESS: *mut u64 = 0x800_0000 as _;\n"
@@ -16628,31 +14267,31 @@ msgid ""
" let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, GICR_BASE_ADDRESS) };\n"
" gic.setup();\n"
"\n"
-" // TODO: Initialise RTC and print value.\n"
+" // TODO: Create instance of RTC driver and print current time.\n"
"\n"
" // TODO: Wait for 3 seconds.\n"
"\n"
-" system_off().unwrap();\n"
+" system_off::().unwrap();\n"
"}\n"
"\n"
"#[panic_handler]\n"
"fn panic(info: &PanicInfo) -> ! {\n"
" error!(\"{info}\");\n"
-" system_off().unwrap();\n"
+" system_off::().unwrap();\n"
" loop {}\n"
"}\n"
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:71
+#: src/exercises/bare-metal/rtc.md:75
msgid "`src/exceptions.rs` (you should only need to change this for the 3rd part of the exercise):"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:73
+#: src/exercises/bare-metal/rtc.md:77
msgid ""
msgstr ""
-#: src/exercises/bare-metal/rtc.md:75
+#: src/exercises/bare-metal/rtc.md:79
msgid ""
"```rust,compile_fail\n"
"// Copyright 2023 Google LLC\n"
@@ -16671,12 +14310,13 @@ msgid ""
"\n"
"use arm_gic::gicv3::GicV3;\n"
"use log::{error, info, trace};\n"
-"use psci::system_off;\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"
+" system_off::().unwrap();\n"
"}\n"
"\n"
"#[no_mangle]\n"
@@ -16689,50 +14329,50 @@ msgid ""
"#[no_mangle]\n"
"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n"
" error!(\"fiq_current\");\n"
-" system_off().unwrap();\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"
+" 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"
+" 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"
+" 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"
+" 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"
+" system_off::().unwrap();\n"
"}\n"
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:144
+#: src/exercises/bare-metal/rtc.md:149
msgid "`src/logger.rs` (you shouldn't need to change this):"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:146
+#: src/exercises/bare-metal/rtc.md:151
msgid ""
msgstr ""
-#: src/exercises/bare-metal/rtc.md:148
+#: src/exercises/bare-metal/rtc.md:153
msgid ""
"```rust,compile_fail\n"
"// Copyright 2023 Google LLC\n"
@@ -16792,15 +14432,15 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:205
+#: src/exercises/bare-metal/rtc.md:210
msgid "`src/pl011.rs` (you shouldn't need to change this):"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:207
+#: src/exercises/bare-metal/rtc.md:212
msgid ""
msgstr ""
-#: src/exercises/bare-metal/rtc.md:209
+#: src/exercises/bare-metal/rtc.md:214
msgid ""
"```rust,compile_fail\n"
"// Copyright 2023 Google LLC\n"
@@ -16974,7 +14614,7 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:384
+#: src/exercises/bare-metal/rtc.md:389
msgid ""
"```toml\n"
"[workspace]\n"
@@ -16990,7 +14630,7 @@ msgid ""
"bitflags = \"2.0.0\"\n"
"chrono = { version = \"0.4.24\", default-features = false }\n"
"log = \"0.4.17\"\n"
-"psci = \"0.1.1\"\n"
+"smccc = \"0.1.1\"\n"
"spin = \"0.9.8\"\n"
"\n"
"[build-dependencies]\n"
@@ -16998,15 +14638,15 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:405
+#: src/exercises/bare-metal/rtc.md:410
msgid "`build.rs` (you shouldn't need to change this):"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:407
+#: src/exercises/bare-metal/rtc.md:412
msgid ""
msgstr ""
-#: src/exercises/bare-metal/rtc.md:409
+#: src/exercises/bare-metal/rtc.md:414
msgid ""
"```rust,compile_fail\n"
"// Copyright 2023 Google LLC\n"
@@ -17041,15 +14681,15 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:441
+#: src/exercises/bare-metal/rtc.md:446
msgid "`entry.S` (you shouldn't need to change this):"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:443
+#: src/exercises/bare-metal/rtc.md:448
msgid ""
msgstr ""
-#: src/exercises/bare-metal/rtc.md:445
+#: src/exercises/bare-metal/rtc.md:450
msgid ""
"```armasm\n"
"/*\n"
@@ -17200,15 +14840,15 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:590
+#: src/exercises/bare-metal/rtc.md:595
msgid "`exceptions.S` (you shouldn't need to change this):"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:592
+#: src/exercises/bare-metal/rtc.md:597
msgid ""
msgstr ""
-#: src/exercises/bare-metal/rtc.md:594
+#: src/exercises/bare-metal/rtc.md:599
msgid ""
"```armasm\n"
"/*\n"
@@ -17392,15 +15032,15 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:775
+#: src/exercises/bare-metal/rtc.md:780
msgid "`idmap.S` (you shouldn't need to change this):"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:777
+#: src/exercises/bare-metal/rtc.md:782
msgid ""
msgstr ""
-#: src/exercises/bare-metal/rtc.md:779
+#: src/exercises/bare-metal/rtc.md:784
msgid ""
"```armasm\n"
"/*\n"
@@ -17448,15 +15088,15 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:824
+#: src/exercises/bare-metal/rtc.md:829
msgid "`image.ld` (you shouldn't need to change this):"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:826
+#: src/exercises/bare-metal/rtc.md:831
msgid ""
msgstr ""
-#: src/exercises/bare-metal/rtc.md:828
+#: src/exercises/bare-metal/rtc.md:833
msgid ""
"```ld\n"
"/*\n"
@@ -17566,15 +15206,15 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:935
+#: src/exercises/bare-metal/rtc.md:940
msgid "`Makefile` (you shouldn't need to change this):"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:937
+#: src/exercises/bare-metal/rtc.md:942
msgid ""
msgstr ""
-#: src/exercises/bare-metal/rtc.md:939
+#: src/exercises/bare-metal/rtc.md:944
msgid ""
"```makefile\n"
"# Copyright 2023 Google LLC\n"
@@ -17610,7 +15250,7 @@ msgid ""
"\t$(OBJCOPY) -O binary target/aarch64-unknown-none/debug/rtc $@\n"
"\n"
"qemu: rtc.bin\n"
-"\tqemu-system-aarch64 -machine virt,gic_version=3 -cpu max -serial mon:stdio -display none -kernel "
+"\tqemu-system-aarch64 -machine virt,gic-version=3 -cpu max -serial mon:stdio -display none -kernel "
"$< -s\n"
"\n"
"clean:\n"
@@ -17619,7 +15259,7 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:984
+#: src/exercises/bare-metal/rtc.md:989
msgid ""
"```toml\n"
"[build]\n"
@@ -17628,10 +15268,2495 @@ msgid ""
"```"
msgstr ""
-#: src/exercises/bare-metal/rtc.md:990
+#: src/exercises/bare-metal/rtc.md:995
msgid "Run the code in QEMU with `make qemu`."
msgstr ""
+#: src/concurrency.md:1
+#, fuzzy
+msgid "# Welcome to Concurrency in Rust"
+msgstr "# Willkommen bei Comprehensive Rust 🦀"
+
+#: src/concurrency.md:3
+#, fuzzy
+msgid ""
+"Rust has full support for concurrency using OS threads with mutexes and\n"
+"channels."
+msgstr ""
+"Rust bietet volle Unterstützung für Parallelität unter Verwendung von Betriebssystem-Threads mit "
+"Mutexes und\n"
+"Kanäle."
+
+#: src/concurrency.md:6
+#, fuzzy
+msgid ""
+"The Rust type system plays an important role in making many concurrency bugs\n"
+"compile time bugs. This is often referred to as _fearless concurrency_ since you\n"
+"can rely on the compiler to ensure correctness at runtime."
+msgstr ""
+"Das Rust-Typsystem spielt eine wichtige Rolle bei der Entstehung vieler Nebenläufigkeitsfehler\n"
+"Kompilierzeitfehler. Dies wird seit Ihnen oft als _furchtlose Parallelität_ bezeichnet\n"
+"kann sich auf den Compiler verlassen, um die Korrektheit zur Laufzeit sicherzustellen."
+
+#: src/concurrency/threads.md:1
+#, fuzzy
+msgid "# Threads"
+msgstr "# Threads"
+
+#: src/concurrency/threads.md:3
+#, fuzzy
+msgid "Rust threads work similarly to threads in other languages:"
+msgstr "Rust-Threads funktionieren ähnlich wie Threads in anderen Sprachen:"
+
+#: src/concurrency/threads.md:5
+msgid ""
+"```rust,editable\n"
+"use std::thread;\n"
+"use std::time::Duration;\n"
+"\n"
+"fn main() {\n"
+" thread::spawn(|| {\n"
+" for i in 1..10 {\n"
+" println!(\"Count in thread: {i}!\");\n"
+" thread::sleep(Duration::from_millis(5));\n"
+" }\n"
+" });\n"
+"\n"
+" for i in 1..5 {\n"
+" println!(\"Main thread: {i}\");\n"
+" thread::sleep(Duration::from_millis(5));\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/threads.md:24
+#, fuzzy
+msgid ""
+"* Threads are all daemon threads, the main thread does not wait for them.\n"
+"* Thread panics are independent of each other.\n"
+" * Panics can carry a payload, which can be unpacked with `downcast_ref`."
+msgstr ""
+"* Threads sind alle Daemon-Threads, der Haupt-Thread wartet nicht auf sie.\n"
+"* Thread-Panics sind voneinander unabhängig.\n"
+" * Paniken können eine Nutzlast tragen, die mit `downcast_ref` entpackt werden kann."
+
+#: src/concurrency/threads.md:32
+msgid ""
+"* Notice that the thread is stopped before it reaches 10 — the main thread is\n"
+" not waiting.\n"
+"\n"
+"* Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for\n"
+" the thread to finish.\n"
+"\n"
+"* Trigger a panic in the thread, notice how this doesn't affect `main`.\n"
+"\n"
+"* Use the `Result` return value from `handle.join()` to get access to the panic\n"
+" payload. This is a good time to talk about [`Any`]."
+msgstr ""
+
+#: src/concurrency/scoped-threads.md:1
+#, fuzzy
+msgid "# Scoped Threads"
+msgstr "# Bereichsbezogene Threads"
+
+#: src/concurrency/scoped-threads.md:3
+#, fuzzy
+msgid "Normal threads cannot borrow from their environment:"
+msgstr "Normale Threads können nicht von ihrer Umgebung ausleihen:"
+
+#: src/concurrency/scoped-threads.md:5
+msgid ""
+"```rust,editable,compile_fail\n"
+"use std::thread;\n"
+"\n"
+"fn main() {\n"
+" let s = String::from(\"Hello\");\n"
+"\n"
+" thread::spawn(|| {\n"
+" println!(\"Length: {}\", s.len());\n"
+" });\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/scoped-threads.md:17
+#, fuzzy
+msgid "However, you can use a [scoped thread][1] for this:"
+msgstr "Sie können dafür jedoch einen [Scoped Thread][1] verwenden:"
+
+#: src/concurrency/scoped-threads.md:19
+msgid ""
+"```rust,editable\n"
+"use std::thread;\n"
+"\n"
+"fn main() {\n"
+" let s = String::from(\"Hello\");\n"
+"\n"
+" thread::scope(|scope| {\n"
+" scope.spawn(|| {\n"
+" println!(\"Length: {}\", s.len());\n"
+" });\n"
+" });\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/scoped-threads.md:37
+#, fuzzy
+msgid ""
+"* The reason for that is that when the `thread::scope` function completes, all the threads are "
+"guaranteed to be joined, so they can return borrowed data.\n"
+"* Normal Rust borrowing rules apply: you can either borrow mutably by one thread, or immutably by "
+"any number of threads.\n"
+" "
+msgstr ""
+"* Der Grund dafür ist, dass nach Abschluss der `thread::scope`-Funktion garantiert alle Threads "
+"verbunden sind, sodass sie geliehene Daten zurückgeben können.\n"
+"* Es gelten die normalen Rust-Ausleihregeln: Sie können entweder veränderlich von einem Thread "
+"ausleihen oder unveränderlich von einer beliebigen Anzahl von Threads.\n"
+" \n"
+" "
+
+#: src/concurrency/channels.md:1
+#, fuzzy
+msgid "# Channels"
+msgstr "# Kanäle"
+
+#: src/concurrency/channels.md:3
+#, fuzzy
+msgid ""
+"Rust channels have two parts: a `Sender` and a `Receiver`. The two parts\n"
+"are connected via the channel, but you only see the end-points."
+msgstr ""
+"Rust-Kanäle bestehen aus zwei Teilen: einem `Sender` und einem `Receiver`. Die zwei Teile\n"
+"über den Kanal verbunden sind, aber Sie sehen nur die Endpunkte."
+
+#: src/concurrency/channels.md:6
+msgid ""
+"```rust,editable\n"
+"use std::sync::mpsc;\n"
+"use std::thread;\n"
+"\n"
+"fn main() {\n"
+" let (tx, rx) = mpsc::channel();\n"
+"\n"
+" tx.send(10).unwrap();\n"
+" tx.send(20).unwrap();\n"
+"\n"
+" println!(\"Received: {:?}\", rx.recv());\n"
+" println!(\"Received: {:?}\", rx.recv());\n"
+"\n"
+" let tx2 = tx.clone();\n"
+" tx2.send(30).unwrap();\n"
+" println!(\"Received: {:?}\", rx.recv());\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/channels.md:27
+#, fuzzy
+msgid ""
+"* `mpsc` stands for Multi-Producer, Single-Consumer. `Sender` and `SyncSender` implement `Clone` "
+"(so\n"
+" you can make multiple producers) but `Receiver` does not.\n"
+"* `send()` and `recv()` return `Result`. If they return `Err`, it means the counterpart `Sender` "
+"or\n"
+" `Receiver` is dropped and the channel is closed."
+msgstr ""
+"* „mpsc“ steht für Multi-Producer, Single-Consumer. `Sender` und `SyncSender` implementieren "
+"`Clone` (also\n"
+" Sie können mehrere Producer erstellen), aber 'Receiver' nicht.\n"
+"* `send()` und `recv()` geben `Result` zurück. Wenn sie `Err` zurückgeben, bedeutet dies das "
+"Gegenstück `Sender` bzw\n"
+" „Receiver“ wird fallen gelassen und der Kanal wird geschlossen."
+
+#: src/concurrency/channels/unbounded.md:1
+#, fuzzy
+msgid "# Unbounded Channels"
+msgstr "# Unbegrenzte Kanäle"
+
+#: src/concurrency/channels/unbounded.md:3
+#, fuzzy
+msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:"
+msgstr "Einen unbegrenzten und asynchronen Kanal erhält man mit `mpsc::channel()`:"
+
+#: src/concurrency/channels/unbounded.md:5
+msgid ""
+"```rust,editable\n"
+"use std::sync::mpsc;\n"
+"use std::thread;\n"
+"use std::time::Duration;\n"
+"\n"
+"fn main() {\n"
+" let (tx, rx) = mpsc::channel();\n"
+"\n"
+" thread::spawn(move || {\n"
+" let thread_id = thread::current().id();\n"
+" for i in 1..10 {\n"
+" tx.send(format!(\"Message {i}\")).unwrap();\n"
+" println!(\"{thread_id:?}: sent Message {i}\");\n"
+" }\n"
+" println!(\"{thread_id:?}: done\");\n"
+" });\n"
+" thread::sleep(Duration::from_millis(100));\n"
+"\n"
+" for msg in rx.iter() {\n"
+" println!(\"Main: got {msg}\");\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/channels/bounded.md:1
+#, fuzzy
+msgid "# Bounded Channels"
+msgstr "# Gebundene Kanäle"
+
+#: src/concurrency/channels/bounded.md:3
+#, fuzzy
+msgid "Bounded and synchronous channels make `send` block the current thread:"
+msgstr ""
+"Gebundene und synchrone Kanäle sorgen dafür, dass der aktuelle Thread durch „Senden“ blockiert "
+"wird:"
+
+#: src/concurrency/channels/bounded.md:5
+msgid ""
+"```rust,editable\n"
+"use std::sync::mpsc;\n"
+"use std::thread;\n"
+"use std::time::Duration;\n"
+"\n"
+"fn main() {\n"
+" let (tx, rx) = mpsc::sync_channel(3);\n"
+"\n"
+" thread::spawn(move || {\n"
+" let thread_id = thread::current().id();\n"
+" for i in 1..10 {\n"
+" tx.send(format!(\"Message {i}\")).unwrap();\n"
+" println!(\"{thread_id:?}: sent Message {i}\");\n"
+" }\n"
+" println!(\"{thread_id:?}: done\");\n"
+" });\n"
+" thread::sleep(Duration::from_millis(100));\n"
+"\n"
+" for msg in rx.iter() {\n"
+" println!(\"Main: got {msg}\");\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/send-sync.md:1
+#, fuzzy
+msgid "# `Send` and `Sync`"
+msgstr "# `Senden` und `Synchronisieren`"
+
+#: src/concurrency/send-sync.md:3
+#, fuzzy
+msgid "How does Rust know to forbid shared access across thread? The answer is in two traits:"
+msgstr ""
+"Woher weiß Rust, dass es den gemeinsamen Zugriff über Threads verbieten soll? Die Antwort liegt in "
+"zwei Merkmalen:"
+
+#: src/concurrency/send-sync.md:5
+#, fuzzy
+msgid ""
+"* [`Send`][1]: a type `T` is `Send` if it is safe to move a `T` across a thread\n"
+" boundary.\n"
+"* [`Sync`][2]: a type `T` is `Sync` if it is safe to move a `&T` across a thread\n"
+" boundary."
+msgstr ""
+"* [`Send`][1]: ein Typ `T` ist `Send`, wenn es sicher ist, ein `T` über einen Thread zu bewegen\n"
+" Grenze.\n"
+"* [`Sync`][2]: ein Typ `T` ist `Sync`, wenn es sicher ist, ein `&T` über einen Thread zu "
+"verschieben\n"
+" Grenze."
+
+#: src/concurrency/send-sync.md:10
+#, fuzzy
+msgid ""
+"`Send` and `Sync` are [unsafe traits][3]. The compiler will automatically derive them for your "
+"types\n"
+"as long as they only contain `Send` and `Sync` types. You can also implement them manually when "
+"you\n"
+"know it is valid."
+msgstr ""
+"„Senden“ und „Synchronisieren“ sind [unsichere Eigenschaften][3]. Der Compiler leitet sie "
+"automatisch für Ihre Typen ab\n"
+"solange sie nur die Typen `Send` und `Sync` enthalten. Sie können sie auch manuell implementieren, "
+"wenn Sie\n"
+"wissen, dass es gültig ist."
+
+#: src/concurrency/send-sync.md:20
+#, fuzzy
+msgid ""
+"* One can think of these traits as markers that the type has certain thread-safety properties.\n"
+"* They can be used in the generic constraints as normal traits.\n"
+" "
+msgstr ""
+"* Man kann sich diese Eigenschaften als Markierungen dafür vorstellen, dass der Typ bestimmte "
+"Thread-Sicherheitseigenschaften hat.\n"
+"* Sie können in den generischen Einschränkungen als normale Merkmale verwendet werden.\n"
+" \n"
+" "
+
+#: src/concurrency/send-sync/send.md:1
+#, fuzzy
+msgid "# `Send`"
+msgstr "# `Senden`"
+
+#: src/concurrency/send-sync/send.md:3
+#, fuzzy
+msgid "> A type `T` is [`Send`][1] if it is safe to move a `T` value to another thread."
+msgstr ""
+"> Ein Typ `T` ist [`Send`][1], wenn es sicher ist, einen `T`-Wert in einen anderen Thread zu "
+"verschieben."
+
+#: src/concurrency/send-sync/send.md:5
+#, fuzzy
+msgid ""
+"The effect of moving ownership to another thread is that _destructors_ will run\n"
+"in that thread. So the question is when you can allocate a value in one thread\n"
+"and deallocate it in another."
+msgstr ""
+"Das Verschieben der Eigentümerschaft auf einen anderen Thread hat zur Folge, dass _destructors_ "
+"ausgeführt wird\n"
+"in diesem Thread. Die Frage ist also, wann Sie einen Wert in einem Thread zuweisen können\n"
+"und es in einem anderen freigeben."
+
+#: src/concurrency/send-sync/send.md:13
+msgid ""
+"As an example, a connection to the SQLite library must only be accessed from a\n"
+"single thread."
+msgstr ""
+
+#: src/concurrency/send-sync/sync.md:1
+#, fuzzy
+msgid "# `Sync`"
+msgstr "# `Synchronisieren`"
+
+#: src/concurrency/send-sync/sync.md:3
+#, fuzzy
+msgid ""
+"> A type `T` is [`Sync`][1] if it is safe to access a `T` value from multiple\n"
+"> threads at the same time."
+msgstr ""
+"> Ein Typ `T` ist [`Sync`][1], wenn es sicher ist, von mehreren auf einen `T`-Wert zuzugreifen\n"
+"> Threads gleichzeitig."
+
+#: src/concurrency/send-sync/sync.md:6
+#, fuzzy
+msgid "More precisely, the definition is:"
+msgstr "Genauer gesagt lautet die Definition:"
+
+#: src/concurrency/send-sync/sync.md:8
+#, fuzzy
+msgid "> `T` is `Sync` if and only if `&T` is `Send`"
+msgstr "> `T` ist `Sync` genau dann, wenn `&T` `Send` ist"
+
+#: src/concurrency/send-sync/sync.md:14
+#, fuzzy
+msgid ""
+"This statement is essentially a shorthand way of saying that if a type is thread-safe for shared "
+"use, it is also thread-safe to pass references of it across threads."
+msgstr ""
+"Diese Anweisung ist im Wesentlichen eine Kurzform dafür, dass ein Typ, der für die gemeinsame "
+"Verwendung Thread-sicher ist, auch Thread-sicher ist, Verweise auf ihn über Threads hinweg zu "
+"übergeben."
+
+#: src/concurrency/send-sync/sync.md:16
+#, fuzzy
+msgid ""
+"This is because if a type is Sync it means that it can be shared across multiple threads without "
+"the risk of data races or other synchronization issues, so it is safe to move it to another "
+"thread. A reference to the type is also safe to move to another thread, because the data it "
+"references can be accessed from any thread safely."
+msgstr ""
+"Denn wenn ein Typ Sync ist, bedeutet dies, dass er von mehreren Threads gemeinsam genutzt werden "
+"kann, ohne das Risiko von Datenrennen oder anderen Synchronisierungsproblemen, sodass es sicher "
+"ist, ihn in einen anderen Thread zu verschieben. Ein Verweis auf den Typ kann auch sicher in einen "
+"anderen Thread verschoben werden, da auf die Daten, auf die er verweist, von jedem Thread aus "
+"sicher zugegriffen werden kann."
+
+#: src/concurrency/send-sync/examples.md:1
+#, fuzzy
+msgid "# Examples"
+msgstr "# Beispiele"
+
+#: src/concurrency/send-sync/examples.md:3
+#, fuzzy
+msgid "## `Send + Sync`"
+msgstr "## `Senden + Synchronisieren`"
+
+#: src/concurrency/send-sync/examples.md:5
+#, fuzzy
+msgid "Most types you come across are `Send + Sync`:"
+msgstr "Die meisten Typen, auf die Sie stoßen, sind „Send + Sync“:"
+
+#: src/concurrency/send-sync/examples.md:7
+msgid ""
+"* `i8`, `f32`, `bool`, `char`, `&str`, ...\n"
+"* `(T1, T2)`, `[T; N]`, `&[T]`, `struct { x: T }`, ...\n"
+"* `String`, `Option`, `Vec`, `Box`, ...\n"
+"* `Arc`: Explicitly thread-safe via atomic reference count.\n"
+"* `Mutex`: Explicitly thread-safe via internal locking.\n"
+"* `AtomicBool`, `AtomicU8`, ...: Uses special atomic instructions."
+msgstr ""
+
+#: src/concurrency/send-sync/examples.md:14
+#, fuzzy
+msgid ""
+"The generic types are typically `Send + Sync` when the type parameters are\n"
+"`Send + Sync`."
+msgstr ""
+"Die generischen Typen sind typischerweise `Send + Sync`, wenn es die Typparameter sind\n"
+"„Senden + Synchronisieren“."
+
+#: src/concurrency/send-sync/examples.md:17
+#, fuzzy
+msgid "## `Send + !Sync`"
+msgstr "## `Senden + !Sync`"
+
+#: src/concurrency/send-sync/examples.md:19
+#, fuzzy
+msgid ""
+"These types can be moved to other threads, but they're not thread-safe.\n"
+"Typically because of interior mutability:"
+msgstr ""
+"Diese Typen können in andere Threads verschoben werden, sind aber nicht Thread-sicher.\n"
+"Typischerweise wegen innerer Mutabilität:"
+
+#: src/concurrency/send-sync/examples.md:22
+#, fuzzy
+msgid ""
+"* `mpsc::Sender`\n"
+"* `mpsc::Receiver`\n"
+"* `Cell`\n"
+"* `RefCell`"
+msgstr ""
+"* `mpsc::Sender`\n"
+"* `mpsc::Receiver`\n"
+"* `Zelle`\n"
+"* `RefCell`"
+
+#: src/concurrency/send-sync/examples.md:27
+#, fuzzy
+msgid "## `!Send + Sync`"
+msgstr "## `!Senden + Synchronisieren`"
+
+#: src/concurrency/send-sync/examples.md:29
+#, fuzzy
+msgid "These types are thread-safe, but they cannot be moved to another thread:"
+msgstr "Diese Typen sind Thread-sicher, können aber nicht in einen anderen Thread verschoben werden:"
+
+#: src/concurrency/send-sync/examples.md:31
+#, fuzzy
+msgid ""
+"* `MutexGuard`: Uses OS level primitives which must be deallocated on the\n"
+" thread which created them."
+msgstr ""
+"* `MutexGuard`: Verwendet Primitive auf Betriebssystemebene, die auf dem freigegeben werden "
+"müssen\n"
+" Thread, der sie erstellt hat."
+
+#: src/concurrency/send-sync/examples.md:34
+#, fuzzy
+msgid "## `!Send + !Sync`"
+msgstr "## `!Senden + !Sync`"
+
+#: src/concurrency/send-sync/examples.md:36
+#, fuzzy
+msgid "These types are not thread-safe and cannot be moved to other threads:"
+msgstr "Diese Typen sind nicht Thread-sicher und können nicht in andere Threads verschoben werden:"
+
+#: src/concurrency/send-sync/examples.md:38
+#, fuzzy
+msgid ""
+"* `Rc`: each `Rc` has a reference to an `RcBox`, which contains a\n"
+" non-atomic reference count.\n"
+"* `*const T`, `*mut T`: Rust assumes raw pointers may have special\n"
+" concurrency considerations."
+msgstr ""
+"* `Rc`: Jedes `Rc` hat eine Referenz auf eine `RcBox`, die eine enthält\n"
+" nicht-atomarer Referenzzähler.\n"
+"* `*const T`, `*mut T`: Rust geht davon aus, dass Rohzeiger möglicherweise etwas Besonderes haben\n"
+" Parallelitätsüberlegungen."
+
+#: src/concurrency/shared_state.md:1
+#, fuzzy
+msgid "# Shared State"
+msgstr "# Geteilter Zustand"
+
+#: src/concurrency/shared_state.md:3
+#, fuzzy
+msgid ""
+"Rust uses the type system to enforce synchronization of shared data. This is\n"
+"primarily done via two types:"
+msgstr ""
+"Rust verwendet das Typsystem, um die Synchronisierung gemeinsam genutzter Daten zu erzwingen. Das "
+"ist\n"
+"hauptsächlich über zwei Arten:"
+
+#: src/concurrency/shared_state.md:6
+#, fuzzy
+msgid ""
+"* [`Arc`][1], atomic reference counted `T`: handles sharing between threads and\n"
+" takes care to deallocate `T` when the last reference is dropped,\n"
+"* [`Mutex`][2]: ensures mutually exclusive access to the `T` value."
+msgstr ""
+"* [`Arc`][1], Atomic Reference Counted `T`: handhabt die gemeinsame Nutzung zwischen Threads "
+"und\n"
+" sorgt dafür, dass `T` freigegeben wird, wenn die letzte Referenz gelöscht wird,\n"
+"* [`Mutex`][2]: sorgt für den sich gegenseitig ausschließenden Zugriff auf den `T`-Wert."
+
+#: src/concurrency/shared_state/arc.md:1
+#, fuzzy
+msgid "# `Arc`"
+msgstr "# `Bogen`"
+
+#: src/concurrency/shared_state/arc.md:3
+#, fuzzy
+msgid "[`Arc`][1] allows shared read-only access via `Arc::clone`:"
+msgstr "[`Arc`][1] ermöglicht den gemeinsamen Nur-Lese-Zugriff über seine `clone`-Methode:"
+
+#: src/concurrency/shared_state/arc.md:5
+msgid ""
+"```rust,editable\n"
+"use std::thread;\n"
+"use std::sync::Arc;\n"
+"\n"
+"fn main() {\n"
+" let v = Arc::new(vec![10, 20, 30]);\n"
+" let mut handles = Vec::new();\n"
+" for _ in 1..5 {\n"
+" let v = Arc::clone(&v);\n"
+" handles.push(thread::spawn(move || {\n"
+" let thread_id = thread::current().id();\n"
+" println!(\"{thread_id:?}: {v:?}\");\n"
+" }));\n"
+" }\n"
+"\n"
+" handles.into_iter().for_each(|h| h.join().unwrap());\n"
+" println!(\"v: {v:?}\");\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/shared_state/arc.md:29
+#, fuzzy
+msgid ""
+"* `Arc` stands for \"Atomic Reference Counted\", a thread safe version of `Rc` that uses atomic\n"
+" operations.\n"
+"* `Arc` implements `Clone` whether or not `T` does. It implements `Send` and `Sync` iff `T`\n"
+" implements them both.\n"
+"* `Arc::clone()` has the cost of atomic operations that get executed, but after that the use of "
+"the\n"
+" `T` is free.\n"
+"* Beware of reference cycles, `Arc` does not use a garbage collector to detect them.\n"
+" * `std::sync::Weak` can help."
+msgstr ""
+"* `Arc` steht für \"Atomic Reference Counted\", eine Thread-sichere Version von `Rc`, die atomar "
+"verwendet\n"
+" Operationen.\n"
+"* `Arc` implementiert `Clone` unabhängig davon, ob `T` dies tut oder nicht. Es implementiert "
+"`Send` und `Sync` iff `T`\n"
+" setzt sie beide um.\n"
+"* `Arc::clone()` hat die Kosten für atomare Operationen, die ausgeführt werden, aber danach die "
+"Verwendung der\n"
+" „T“ ist frei.\n"
+"* Hüten Sie sich vor Referenzzyklen, `Arc` verwendet keinen Garbage Collector, um sie zu "
+"erkennen.\n"
+" * `std::sync::Weak` kann helfen."
+
+#: src/concurrency/shared_state/mutex.md:1
+#, fuzzy
+msgid "# `Mutex`"
+msgstr "# `Mutex`"
+
+#: src/concurrency/shared_state/mutex.md:3
+#, fuzzy
+msgid ""
+"[`Mutex`][1] ensures mutual exclusion _and_ allows mutable access to `T`\n"
+"behind a read-only interface:"
+msgstr ""
+"[`Mutex`][1] sorgt für gegenseitigen Ausschluss _und_ erlaubt veränderlichen Zugriff auf `T`\n"
+"hinter einer Nur-Lese-Schnittstelle:"
+
+#: src/concurrency/shared_state/mutex.md:6
+msgid ""
+"```rust,editable\n"
+"use std::sync::Mutex;\n"
+"\n"
+"fn main() {\n"
+" let v = Mutex::new(vec![10, 20, 30]);\n"
+" println!(\"v: {:?}\", v.lock().unwrap());\n"
+"\n"
+" {\n"
+" let mut guard = v.lock().unwrap();\n"
+" guard.push(40);\n"
+" }\n"
+"\n"
+" println!(\"v: {:?}\", v.lock().unwrap());\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/shared_state/mutex.md:22
+#, fuzzy
+msgid ""
+"Notice how we have a [`impl Sync for Mutex`][2] blanket\n"
+"implementation."
+msgstr ""
+"Beachten Sie, wie wir eine [`impl Sync for Mutex`][2] Blanket haben\n"
+"Implementierung."
+
+#: src/concurrency/shared_state/mutex.md:31
+#, fuzzy
+msgid ""
+"* `Mutex` in Rust looks like a collection with just one element - the protected data.\n"
+" * It is not possible to forget to acquire the mutex before accessing the protected data.\n"
+"* You can get an `&mut T` from an `&Mutex` by taking the lock. The `MutexGuard` ensures that "
+"the\n"
+" `&mut T` doesn't outlive the lock being held.\n"
+"* `Mutex` implements both `Send` and `Sync` iff `T` implements `Send`.\n"
+"* A read-write lock counterpart - `RwLock`.\n"
+"* Why does `lock()` return a `Result`? \n"
+" * If the thread that held the `Mutex` panicked, the `Mutex` becomes \"poisoned\" to signal "
+"that\n"
+" the data it protected might be in an inconsistent state. Calling `lock()` on a poisoned "
+"mutex\n"
+" fails with a [`PoisonError`]. You can call `into_inner()` on the error to recover the data\n"
+" regardless."
+msgstr ""
+"* `Mutex` in Rust sieht aus wie eine Sammlung mit nur einem Element - den geschützten Daten.\n"
+" * Es ist nicht möglich, das Abrufen des Mutex zu vergessen, bevor auf die geschützten Daten "
+"zugegriffen wird.\n"
+"* Sie können ein `&mut T` von einem `&Mutex` erhalten, indem Sie die Sperre nehmen. Der "
+"`MutexGuard` sorgt dafür, dass die\n"
+" `&mut T` überlebt die gehaltene Sperre nicht.\n"
+"* `Mutex` implementiert sowohl `Send` als auch `Sync`, wenn `T` `Send` implementiert.\n"
+"* Ein Gegenstück zur Lese-Schreib-Sperre - `RwLock`.\n"
+"* Warum gibt `lock()` ein `Result` zurück?\n"
+" * Wenn der Thread, der den `Mutex` enthielt, in Panik geriet, wird der `Mutex` \"vergiftet\", "
+"um dies zu signalisieren\n"
+" Die geschützten Daten befinden sich möglicherweise in einem inkonsistenten Zustand. Aufruf "
+"von `lock()` auf einem vergifteten Mutex\n"
+" schlägt mit einem [`PoisonError`] fehl. Sie können `into_inner()` für den Fehler aufrufen, "
+"um die Daten wiederherzustellen\n"
+" trotzdem."
+
+#: src/concurrency/shared_state/example.md:3
+#, fuzzy
+msgid "Let us see `Arc` and `Mutex` in action:"
+msgstr "Sehen wir uns `Arc` und `Mutex` in Aktion an:"
+
+#: src/concurrency/shared_state/example.md:5
+msgid ""
+"```rust,editable,compile_fail\n"
+"use std::thread;\n"
+"// use std::sync::{Arc, Mutex};\n"
+"\n"
+"fn main() {\n"
+" let v = vec![10, 20, 30];\n"
+" let handle = thread::spawn(|| {\n"
+" v.push(10);\n"
+" });\n"
+" v.push(1000);\n"
+"\n"
+" handle.join().unwrap();\n"
+" println!(\"v: {v:?}\");\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/shared_state/example.md:23
+msgid "Possible solution:"
+msgstr ""
+
+#: src/concurrency/shared_state/example.md:25
+msgid ""
+"```rust,editable\n"
+"use std::sync::{Arc, Mutex};\n"
+"use std::thread;\n"
+"\n"
+"fn main() {\n"
+" let v = Arc::new(Mutex::new(vec![10, 20, 30]));\n"
+"\n"
+" let v2 = Arc::clone(&v);\n"
+" let handle = thread::spawn(move || {\n"
+" let mut v2 = v2.lock().unwrap();\n"
+" v2.push(10);\n"
+" });\n"
+"\n"
+" {\n"
+" let mut v = v.lock().unwrap();\n"
+" v.push(1000);\n"
+" }\n"
+"\n"
+" handle.join().unwrap();\n"
+"\n"
+" println!(\"v: {v:?}\");\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/concurrency/shared_state/example.md:49
+msgid "Notable parts:"
+msgstr ""
+
+#: src/concurrency/shared_state/example.md:51
+#, fuzzy
+msgid ""
+"* `v` is wrapped in both `Arc` and `Mutex`, because their concerns are orthogonal.\n"
+" * Wrapping a `Mutex` in an `Arc` is a common pattern to share mutable state between threads.\n"
+"* `v: Arc<_>` needs to be cloned as `v2` before it can be moved into another thread. Note `move` "
+"was added to the lambda signature.\n"
+"* Blocks are introduced to narrow the scope of the `LockGuard` as much as possible."
+msgstr ""
+"* `v` ist sowohl in `Arc` als auch in `Mutex` eingeschlossen, weil ihre Anliegen orthogonal sind.\n"
+" * Das Umhüllen eines `Mutex` in einen `Arc` ist ein gängiges Muster, um einen veränderlichen "
+"Zustand zwischen Threads zu teilen.\n"
+"* „v: Arc<_>“ muss als „v2“ geklont werden, bevor es in einen anderen Thread verschoben werden "
+"kann. Der Lambda-Signatur wurde der Hinweis „move“ hinzugefügt.\n"
+"* Blöcke werden eingeführt, um den Anwendungsbereich von `LockGuard` so weit wie möglich "
+"einzuschränken.\n"
+"* Wir müssen noch den `Mutex` erwerben, um unseren `Vec` zu drucken."
+
+#: src/exercises/concurrency/morning.md:3
+#, fuzzy
+msgid "Let us practice our new concurrency skills with"
+msgstr "Lassen Sie uns unsere neuen Nebenläufigkeitsfähigkeiten mit üben"
+
+#: src/exercises/concurrency/morning.md:5
+#, fuzzy
+msgid ""
+"* Dining philosophers: a classic problem in concurrency.\n"
+"\n"
+"* Multi-threaded link checker: a larger project where you'll use Cargo to\n"
+" download dependencies and then check links in parallel."
+msgstr ""
+"* Multithreaded Link Checker: ein größeres Projekt, für das Sie Cargo verwenden werden\n"
+" Abhängigkeiten herunterladen und dann parallel Links prüfen."
+
+#: src/exercises/concurrency/dining-philosophers.md:1
+#, fuzzy
+msgid "# Dining Philosophers"
+msgstr "# Speisende Philosophen"
+
+#: src/exercises/concurrency/dining-philosophers.md:3
+#, fuzzy
+msgid "The dining philosophers problem is a classic problem in concurrency:"
+msgstr "Das Dining-Philosophen-Problem ist ein klassisches Nebenläufigkeitsproblem:"
+
+#: src/exercises/concurrency/dining-philosophers.md:5
+#, fuzzy
+msgid ""
+"> Five philosophers dine together at the same table. Each philosopher has their\n"
+"> own place at the table. There is a fork between each plate. The dish served is\n"
+"> a kind of spaghetti which has to be eaten with two forks. Each philosopher can\n"
+"> only alternately think and eat. Moreover, a philosopher can only eat their\n"
+"> spaghetti when they have both a left and right fork. Thus two forks will only\n"
+"> be available when their two nearest neighbors are thinking, not eating. After\n"
+"> an individual philosopher finishes eating, they will put down both forks."
+msgstr ""
+"> Fünf Philosophen speisen gemeinsam am selben Tisch. Jeder Philosoph hat seine\n"
+"> eigener Platz am Tisch. Zwischen jedem Teller befindet sich eine Gabel. Das servierte Gericht "
+"ist\n"
+"> eine Art Spaghetti, die mit zwei Gabeln gegessen werden muss. Jeder Philosoph kann\n"
+"> nur abwechselnd denken und essen. Außerdem kann ein Philosoph nur ihre essen\n"
+"> Spaghetti, wenn sie sowohl eine linke als auch eine rechte Gabel haben. Also zwei Gabeln werden "
+"nur\n"
+"> verfügbar sein, wenn ihre beiden nächsten Nachbarn nachdenken, nicht essen. Nach\n"
+"> ein einzelner Philosoph mit dem Essen fertig ist, legen sie beide Gabeln weg."
+
+#: src/exercises/concurrency/dining-philosophers.md:13
+#, fuzzy
+msgid ""
+"You will need a local [Cargo installation](../../cargo/running-locally.md) for\n"
+"this exercise. Copy the code below to a file called `src/main.rs`, fill out the\n"
+"blanks, and test that `cargo run` does not deadlock:"
+msgstr ""
+"Dazu benötigen Sie eine lokale [Cargo-Installation](../../cargo/running-locally.md).\n"
+"diese Übung. Kopieren Sie den folgenden Code in die Datei `src/main.rs`, füllen Sie die Lücken "
+"aus,\n"
+"und teste, dass `cargo run` keinen Deadlock verursacht:"
+
+#: src/exercises/concurrency/dining-philosophers.md:19
+msgid ""
+"```rust,compile_fail\n"
+"use std::sync::{mpsc, Arc, Mutex};\n"
+"use std::thread;\n"
+"use std::time::Duration;\n"
+"\n"
+"struct Fork;\n"
+"\n"
+"struct Philosopher {\n"
+" name: String,\n"
+" // left_fork: ...\n"
+" // right_fork: ...\n"
+" // thoughts: ...\n"
+"}\n"
+"\n"
+"impl Philosopher {\n"
+" fn think(&self) {\n"
+" self.thoughts\n"
+" .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n"
+" .unwrap();\n"
+" }\n"
+"\n"
+" fn eat(&self) {\n"
+" // Pick up forks...\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"
+"\n"
+"fn main() {\n"
+" // Create forks\n"
+"\n"
+" // Create philosophers\n"
+"\n"
+" // Make them think and eat\n"
+"\n"
+" // Output their thoughts\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/dining-philosophers.md:61
+msgid "You can use the following `Cargo.toml`:"
+msgstr ""
+
+#: src/exercises/concurrency/dining-philosophers.md:65
+msgid ""
+"```toml\n"
+"[package]\n"
+"name = \"dining-philosophers\"\n"
+"version = \"0.1.0\"\n"
+"edition = \"2021\"\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/link-checker.md:1
+#, fuzzy
+msgid "# Multi-threaded Link Checker"
+msgstr "# Multithreaded Link Checker"
+
+#: src/exercises/concurrency/link-checker.md:3
+#, fuzzy
+msgid ""
+"Let us use our new knowledge to create a multi-threaded link checker. It should\n"
+"start at a webpage and check that links on the page are valid. It should\n"
+"recursively check other pages on the same domain and keep doing this until all\n"
+"pages have been validated."
+msgstr ""
+"Lassen Sie uns unser neues Wissen nutzen, um einen Multithread-Link-Checker zu erstellen. Es "
+"sollte\n"
+"Starten Sie auf einer Webseite und prüfen Sie, ob die Links auf der Seite gültig sind. Es sollte\n"
+"Überprüfen Sie rekursiv andere Seiten auf derselben Domain und tun Sie dies so lange, bis alle\n"
+"Seiten wurden validiert."
+
+#: src/exercises/concurrency/link-checker.md:8
+#, fuzzy
+msgid ""
+"For this, you will need an HTTP client such as [`reqwest`][1]. Create a new\n"
+"Cargo project and `reqwest` it as a dependency with:"
+msgstr ""
+"Dazu benötigen Sie einen HTTP-Client wie [`reqwest`][1]. Erstelle eine neue\n"
+"Frachtprojekt und `reqwest` es als Abhängigkeit mit:"
+
+#: 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
+#, fuzzy
+msgid ""
+"> If `cargo add` fails with `error: no such subcommand`, then please edit the\n"
+"> `Cargo.toml` file by hand. Add the dependencies listed below."
+msgstr ""
+"> Wenn `cargo add` mit `error: no such subcommand` fehlschlägt, dann bearbeiten Sie bitte die\n"
+"> `Cargo.toml`-Datei von Hand. Fügen Sie die unten aufgeführten Abhängigkeiten hinzu."
+
+#: src/exercises/concurrency/link-checker.md:20
+#, fuzzy
+msgid "You will also need a way to find links. We can use [`scraper`][2] for that:"
+msgstr ""
+"Sie benötigen auch eine Möglichkeit, Links zu finden. Dafür können wir [`scraper`][2] verwenden:"
+
+#: src/exercises/concurrency/link-checker.md:22
+msgid ""
+"```shell\n"
+"$ cargo add scraper\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/link-checker.md:26
+#, fuzzy
+msgid ""
+"Finally, we'll need some way of handling errors. We use [`thiserror`][3] for\n"
+"that:"
+msgstr ""
+"Schließlich brauchen wir eine Möglichkeit, mit Fehlern umzugehen. Wir verwenden [`thiserror`][3] "
+"für\n"
+"Das:"
+
+#: src/exercises/concurrency/link-checker.md:29
+msgid ""
+"```shell\n"
+"$ cargo add thiserror\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/link-checker.md:33
+#, fuzzy
+msgid "The `cargo add` calls will update the `Cargo.toml` file to look like this:"
+msgstr ""
+"Die `cargo add`-Aufrufe aktualisieren die `Cargo.toml`-Datei so, dass sie wie folgt aussieht:"
+
+#: src/exercises/concurrency/link-checker.md:37
+msgid ""
+"```toml\n"
+"[package]\n"
+"name = \"link-checker\"\n"
+"version = \"0.1.0\"\n"
+"edition = \"2021\"\n"
+"publish = false\n"
+"\n"
+"[dependencies]\n"
+"reqwest = { version = \"0.11.12\", features = [\"blocking\", \"rustls-tls\"] }\n"
+"scraper = \"0.13.0\"\n"
+"thiserror = \"1.0.37\"\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/link-checker.md:50
+#, fuzzy
+msgid ""
+"You can now download the start page. Try with a small site such as\n"
+"`https://www.google.org/`."
+msgstr ""
+"Sie können nun die Startseite herunterladen. Versuchen Sie es mit einer kleinen Website wie z\n"
+"`https://www.google.org/`."
+
+#: src/exercises/concurrency/link-checker.md:53
+#, fuzzy
+msgid "Your `src/main.rs` file should look something like this:"
+msgstr "Ihre `src/main.rs`-Datei sollte in etwa so aussehen:"
+
+#: src/exercises/concurrency/link-checker.md:57
+msgid ""
+"```rust,compile_fail\n"
+"use reqwest::blocking::{get, Response};\n"
+"use reqwest::Url;\n"
+"use scraper::{Html, Selector};\n"
+"use thiserror::Error;\n"
+"\n"
+"#[derive(Error, Debug)]\n"
+"enum Error {\n"
+" #[error(\"request error: {0}\")]\n"
+" ReqwestError(#[from] reqwest::Error),\n"
+"}\n"
+"\n"
+"fn extract_links(response: Response) -> Result, Error> {\n"
+" let base_url = response.url().to_owned();\n"
+" let document = response.text()?;\n"
+" let html = Html::parse_document(&document);\n"
+" let selector = Selector::parse(\"a\").unwrap();\n"
+"\n"
+" let mut valid_urls = Vec::new();\n"
+" for element in html.select(&selector) {\n"
+" if let Some(href) = element.value().attr(\"href\") {\n"
+" match base_url.join(href) {\n"
+" Ok(url) => valid_urls.push(url),\n"
+" Err(err) => {\n"
+" println!(\"On {base_url}: could not parse {href:?}: {err} (ignored)\",);\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+"\n"
+" Ok(valid_urls)\n"
+"}\n"
+"\n"
+"fn main() {\n"
+" let start_url = Url::parse(\"https://www.google.org\").unwrap();\n"
+" let response = get(start_url).unwrap();\n"
+" match extract_links(response) {\n"
+" Ok(links) => println!(\"Links: {links:#?}\"),\n"
+" Err(err) => println!(\"Could not extract links: {err:#}\"),\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/link-checker.md:100
+#, fuzzy
+msgid "Run the code in `src/main.rs` with"
+msgstr "Führen Sie den Code in `src/main.rs` mit aus"
+
+#: src/exercises/concurrency/link-checker.md:102
+msgid ""
+"```shell\n"
+"$ cargo run\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/link-checker.md:106 src/exercises/concurrency/chat-app.md:140
+#, fuzzy
+msgid "## Tasks"
+msgstr "## Aufgaben"
+
+#: src/exercises/concurrency/link-checker.md:108
+#, fuzzy
+msgid ""
+"* Use threads to check the links in parallel: send the URLs to be checked to a\n"
+" channel and let a few threads check the URLs in parallel.\n"
+"* Extend this to recursively extract links from all pages on the\n"
+" `www.google.org` domain. Put an upper limit of 100 pages or so so that you\n"
+" don't end up being blocked by the site."
+msgstr ""
+"* Verwenden Sie Threads, um die Links parallel zu prüfen: Senden Sie die zu prüfenden URLs an a\n"
+" Channel und lass ein paar Threads parallel die URLs prüfen.\n"
+"* Erweitern Sie dies, um Links von allen Seiten rekursiv zu extrahieren\n"
+" `www.google.org`-Domain. Setzen Sie eine Obergrenze von 100 Seiten oder so, dass Sie\n"
+" am Ende nicht von der Seite blockiert werden."
+
+#: src/async.md:1
+#, fuzzy
+msgid "# Async Rust"
+msgstr "# Warum Rost?"
+
+#: src/async.md:3
+msgid ""
+"\"Async\" is a concurrency model where multiple tasks are executed concurrently by\n"
+"executing each task until it would block, then switching to another task that is\n"
+"ready to make progress. The model allows running a larger number of tasks on a\n"
+"limited number of threads. This is because the per-task overhead is typically\n"
+"very low and operating systems provide primitives for efficiently identifying\n"
+"I/O that is able to proceed."
+msgstr ""
+
+#: src/async.md:10
+msgid ""
+"Rust's asynchronous operation is based on \"futures\", which represent work that\n"
+"may be completed in the future. Futures are \"polled\" until they signal that\n"
+"they are complete."
+msgstr ""
+
+#: src/async.md:14
+msgid ""
+"Futures are polled by an async runtime, and several different runtimes are\n"
+"available."
+msgstr ""
+
+#: src/async.md:17
+#, fuzzy
+msgid "## Comparisons"
+msgstr "# Vergleich"
+
+#: src/async.md:19
+msgid ""
+" * Python has a similar model in its `asyncio`. However, its `Future` type is\n"
+" callback-based, and not polled. Async Python programs require a \"loop\",\n"
+" similar to a runtime in Rust.\n"
+"\n"
+" * JavaScript's `Promise` is similar, but again callback-based. The language\n"
+" runtime implements the event loop, so many of the details of Promise\n"
+" resolution are hidden."
+msgstr ""
+
+#: src/async/async-await.md:1
+msgid "# `async`/`await`"
+msgstr ""
+
+#: src/async/async-await.md:3
+msgid "At a high level, async Rust code looks very much like \"normal\" sequential code:"
+msgstr ""
+
+#: src/async/async-await.md:5
+msgid ""
+"```rust,editable,compile_fail\n"
+"use futures::executor::block_on;\n"
+"\n"
+"async fn count_to(count: i32) {\n"
+" for i in 1..=count {\n"
+" println!(\"Count is: {i}!\");\n"
+" }\n"
+"}\n"
+"\n"
+"async fn async_main(count: i32) {\n"
+" count_to(count).await;\n"
+"}\n"
+"\n"
+"fn main() {\n"
+" block_on(async_main(10));\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/async/async-await.md:27
+msgid ""
+"* Note that this is a simplified example to show the syntax. There is no long\n"
+" running operation or any real concurrency in it!\n"
+"\n"
+"* What is the return type of an async call?\n"
+" * Use `let future: () = async_main(10);` in `main` to see the type.\n"
+"\n"
+"* The \"async\" keyword is syntactic sugar. The compiler replaces the return type\n"
+" with a future. \n"
+"\n"
+"* You cannot make `main` async, without additional instructions to the compiler\n"
+" on how to use the returned future.\n"
+"\n"
+"* You need an executor to run async code. `block_on` blocks the current thread\n"
+" until the provided future has run to completion. \n"
+"\n"
+"* `.await` asynchronously waits for the completion of another operation. Unlike\n"
+" `block_on`, `.await` doesn't block the current thread.\n"
+"\n"
+"* `.await` can only be used inside an `async` function (or block; these are\n"
+" introduced later). "
+msgstr ""
+
+#: src/async/futures.md:1
+#, fuzzy
+msgid "# Futures"
+msgstr "# Schließungen"
+
+#: src/async/futures.md:3
+msgid ""
+"[`Future`](https://doc.rust-lang.org/std/future/trait.Future.html)\n"
+"is a trait, implemented by objects that represent an operation that may not be\n"
+"complete yet. A future can be polled, and `poll` returns a\n"
+"[`Poll`](https://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 uncommon) to\n"
+"implement `Future` for your own types. For example, the `JoinHandle` returned\n"
+"from `tokio::spawn` implements `Future` to allow joining to it."
+msgstr ""
+
+#: src/async/futures.md:27
+msgid ""
+"The `.await` keyword, applied to a Future, causes the current async function to\n"
+"pause until that Future is ready, and then evaluates to its output."
+msgstr ""
+
+#: src/async/futures.md:32
+msgid ""
+"* The `Future` and `Poll` types are implemented exactly as shown; click the\n"
+" links to show the implementations in the docs.\n"
+"\n"
+"* We will not get to `Pin` and `Context`, as we will focus on writing async\n"
+" code, rather than building new async primitives. Briefly:\n"
+"\n"
+" * `Context` allows a Future to schedule itself to be polled again when an\n"
+" event occurs.\n"
+"\n"
+" * `Pin` ensures that the Future isn't moved in memory, so that pointers into\n"
+" that future remain valid. This is required to allow references to remain\n"
+" valid after an `.await`."
+msgstr ""
+
+#: src/async/runtimes.md:1
+#, fuzzy
+msgid "# Runtimes"
+msgstr "Laufzeiten"
+
+#: src/async/runtimes.md:3
+msgid ""
+"A *runtime* provides support for performing operations asynchronously (a\n"
+"*reactor*) and is responsible for executing futures (an *executor*). Rust does not have a\n"
+"\"built-in\" runtime, but several options are available:"
+msgstr ""
+
+#: src/async/runtimes.md:7
+msgid ""
+" * [Tokio](https://tokio.rs/) - performant, with a well-developed ecosystem of\n"
+" functionality like [Hyper](https://hyper.rs/) for HTTP or\n"
+" [Tonic](https://github.com/hyperium/tonic) for gRPC.\n"
+" * [async-std](https://async.rs/) - aims to be a \"std for async\", and includes a\n"
+" basic runtime in `async::task`.\n"
+" * [smol](https://docs.rs/smol/latest/smol/) - simple and lightweight"
+msgstr ""
+
+#: src/async/runtimes.md:14
+msgid ""
+"Several larger applications have their own runtimes. For example,\n"
+"[Fuchsia](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/lib/fuchsia-async/src/lib."
+"rs)\n"
+"already has one."
+msgstr ""
+
+#: src/async/runtimes.md:20
+msgid ""
+"* Note that of the listed runtimes, only Tokio is supported in the Rust\n"
+" playground. The playground also does not permit any I/O, so most interesting\n"
+" async things can't run in the playground.\n"
+"\n"
+"* Futures are \"inert\" in that they do not do anything (not even start an I/O\n"
+" operation) unless there is an executor polling them. This differs from JS\n"
+" Promises, for example, which will run to completion even if they are never\n"
+" used."
+msgstr ""
+
+#: src/async/runtimes/tokio.md:1
+msgid "# Tokio"
+msgstr ""
+
+#: src/async/runtimes/tokio.md:4
+msgid "Tokio provides: "
+msgstr ""
+
+#: src/async/runtimes/tokio.md:6
+msgid ""
+"* A multi-threaded runtime for executing asynchronous code.\n"
+"* An asynchronous version of the standard library.\n"
+"* A large ecosystem of libraries."
+msgstr ""
+
+#: src/async/runtimes/tokio.md:10
+msgid ""
+"```rust,editable,compile_fail\n"
+"use tokio::time;\n"
+"\n"
+"async fn count_to(count: i32) {\n"
+" for i in 1..=count {\n"
+" println!(\"Count in task: {i}!\");\n"
+" time::sleep(time::Duration::from_millis(5)).await;\n"
+" }\n"
+"}\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() {\n"
+" tokio::spawn(count_to(10));\n"
+"\n"
+" for i in 1..5 {\n"
+" println!(\"Main task: {i}\");\n"
+" time::sleep(time::Duration::from_millis(5)).await;\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/async/runtimes/tokio.md:33
+msgid ""
+"* With the `tokio::main` macro we can now make `main` async.\n"
+"\n"
+"* The `spawn` function creates a new, concurrent \"task\".\n"
+"\n"
+"* Note: `spawn` takes a `Future`, you don't call `.await` on `count_to`."
+msgstr ""
+
+#: src/async/runtimes/tokio.md:39
+msgid "**Further exploration:**"
+msgstr ""
+
+#: src/async/runtimes/tokio.md:41
+msgid ""
+"* Why does `count_to` not (usually) get to 10? This is an example of async\n"
+" cancellation. `tokio::spawn` returns a handle which can be awaited to wait\n"
+" until it finishes.\n"
+"\n"
+"* Try `count_to(10).await` instead of spawning.\n"
+"\n"
+"* Try awaiting the task returned from `tokio::spawn`."
+msgstr ""
+
+#: src/async/tasks.md:1
+#, fuzzy
+msgid "# Tasks"
+msgstr "## Aufgaben"
+
+#: src/async/tasks.md:3
+msgid ""
+"Runtimes have the concept of a \"task\", similar to a thread but much\n"
+"less resource-intensive."
+msgstr ""
+
+#: src/async/tasks.md:6
+msgid ""
+"A task has a single top-level future which the executor polls to make progress.\n"
+"That future may have one or more nested futures that its `poll` method polls,\n"
+"corresponding loosely to a call stack. Concurrency within a task is possible by\n"
+"polling multiple child futures, such as racing a timer and an I/O operation."
+msgstr ""
+
+#: src/async/tasks.md:11
+msgid ""
+"```rust,compile_fail\n"
+"use tokio::io::{self, AsyncReadExt, AsyncWriteExt};\n"
+"use tokio::net::TcpListener;\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() -> io::Result<()> {\n"
+" let listener = TcpListener::bind(\"127.0.0.1:6142\").await?;\n"
+"\tprintln!(\"listening on port 6142\");\n"
+"\n"
+" loop {\n"
+" let (mut socket, addr) = listener.accept().await?;\n"
+"\n"
+" println!(\"connection from {addr:?}\");\n"
+"\n"
+" tokio::spawn(async move {\n"
+" if let Err(e) = socket.write_all(b\"Who are you?\\n\").await {\n"
+" println!(\"socket error: {e:?}\");\n"
+" return;\n"
+" }\n"
+"\n"
+" let mut buf = vec![0; 1024];\n"
+" let reply = match socket.read(&mut buf).await {\n"
+" Ok(n) => {\n"
+" let name = std::str::from_utf8(&buf[..n]).unwrap().trim();\n"
+" format!(\"Thanks for dialing in, {name}!\\n\")\n"
+" }\n"
+" Err(e) => {\n"
+" println!(\"socket error: {e:?}\");\n"
+" return;\n"
+" }\n"
+" };\n"
+"\n"
+" if let Err(e) = socket.write_all(reply.as_bytes()).await {\n"
+" println!(\"socket error: {e:?}\");\n"
+" }\n"
+" });\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/async/tasks.md:53 src/async/control-flow/join.md:36
+msgid "Copy this example into your prepared `src/main.rs` and run it from there."
+msgstr ""
+
+#: src/async/tasks.md:55
+msgid ""
+"* Ask students to visualize what the state of the example server would be with a\n"
+" few connected clients. What tasks exist? What are their Futures?\n"
+"\n"
+"* This is the first time we've seen an `async` block. This is similar to a\n"
+" closure, but does not take any arguments. Its return value is a Future,\n"
+" similar to an `async fn`. \n"
+"\n"
+"* Refactor the async block into a function, and improve the error handling using `?`."
+msgstr ""
+
+#: src/async/channels.md:1
+#, fuzzy
+msgid "# Async Channels"
+msgstr "# Kanäle"
+
+#: src/async/channels.md:3
+msgid "Several crates have support for `async`/`await`. For instance `tokio` channels:"
+msgstr ""
+
+#: src/async/channels.md:5
+msgid ""
+"```rust,editable,compile_fail\n"
+"use tokio::sync::mpsc::{self, Receiver};\n"
+"\n"
+"async fn ping_handler(mut input: Receiver<()>) {\n"
+" let mut count: usize = 0;\n"
+"\n"
+" while let Some(_) = input.recv().await {\n"
+" count += 1;\n"
+" println!(\"Received {count} pings so far.\");\n"
+" }\n"
+"\n"
+" println!(\"ping_handler complete\");\n"
+"}\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() {\n"
+" let (sender, receiver) = mpsc::channel(32);\n"
+" let ping_handler_task = tokio::spawn(ping_handler(receiver));\n"
+" for i in 0..10 {\n"
+" sender.send(()).await.expect(\"Failed to send ping.\");\n"
+" println!(\"Sent {} pings so far.\", i + 1);\n"
+" }\n"
+"\n"
+" std::mem::drop(sender);\n"
+" ping_handler_task.await.expect(\"Something went wrong in ping handler task.\");\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/async/channels.md:35
+msgid ""
+"* Change the channel size to `3` and see how it affects the execution.\n"
+"\n"
+"* Overall, the interface is similar to the `sync` channels as seen in the\n"
+" [morning class](concurrency/channels.md).\n"
+"\n"
+"* Try removing the `std::mem::drop` call. What happens? Why?\n"
+"\n"
+"* The [Flume](https://docs.rs/flume/latest/flume/) crate has channels that\n"
+" implement both `sync` and `async` `send` and `recv`. This can be convenient\n"
+" for complex applications with both IO and heavy CPU processing tasks.\n"
+"\n"
+"* What makes working with `async` channels preferable is the ability to combine\n"
+" them with other `future`s to combine them and create complex control flow."
+msgstr ""
+
+#: src/async/control-flow.md:1
+#, fuzzy
+msgid "# Futures Control Flow"
+msgstr "# Kontrollfluss"
+
+#: src/async/control-flow.md:3
+msgid ""
+"Futures can be combined together to produce concurrent compute flow graphs. We\n"
+"have already seen tasks, that function as independent threads of execution."
+msgstr ""
+
+#: src/async/control-flow.md:6
+msgid ""
+"- [Join](control-flow/join.md)\n"
+"- [Select](control-flow/select.md)"
+msgstr ""
+
+#: src/async/control-flow/join.md:1
+msgid "# Join"
+msgstr ""
+
+#: src/async/control-flow/join.md:3
+msgid ""
+"A join operation waits until all of a set of futures are ready, and\n"
+"returns a collection of their results. This is similar to `Promise.all` in\n"
+"JavaScript or `asyncio.gather` in Python."
+msgstr ""
+
+#: src/async/control-flow/join.md:7
+msgid ""
+"```rust,editable,compile_fail\n"
+"use anyhow::Result;\n"
+"use futures::future;\n"
+"use reqwest;\n"
+"use std::collections::HashMap;\n"
+"\n"
+"async fn size_of_page(url: &str) -> Result {\n"
+" let resp = reqwest::get(url).await?;\n"
+" Ok(resp.text().await?.len())\n"
+"}\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() {\n"
+" let urls: [&str; 4] = [\n"
+" \"https://google.com\",\n"
+" \"https://httpbin.org/ip\",\n"
+" \"https://play.rust-lang.org/\",\n"
+" \"BAD_URL\",\n"
+" ];\n"
+" let futures_iter = urls.into_iter().map(size_of_page);\n"
+" let results = future::join_all(futures_iter).await;\n"
+" let page_sizes_dict: HashMap<&str, Result> =\n"
+" urls.into_iter().zip(results.into_iter()).collect();\n"
+" println!(\"{:?}\", page_sizes_dict);\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/async/control-flow/join.md:38
+msgid ""
+"* For multiple futures of disjoint types, you can use `std::future::join!` but\n"
+" you must know how many futures you will have at compile time. This is\n"
+" currently in the `futures` crate, soon to be stabilised in `std::future`.\n"
+"\n"
+"* The risk of `join` is that one of the futures may never resolve, this would\n"
+" cause your program to stall. \n"
+"\n"
+"* You can also combine `join_all` with `join!` for instance to join all requests\n"
+" to an http service as well as a database query. Try adding a\n"
+" `tokio::time::sleep` to the future, using `futures::join!`. This is not a\n"
+" timeout (that requires `select!`, explained in the next chapter), but demonstrates `join!`."
+msgstr ""
+
+#: src/async/control-flow/select.md:1
+#, fuzzy
+msgid "# Select"
+msgstr "# Aufstellen"
+
+#: src/async/control-flow/select.md:3
+msgid ""
+"A select operation waits until any of a set of futures is ready, and responds to\n"
+"that future's result. In JavaScript, this is similar to `Promise.race`. In\n"
+"Python, it compares to `asyncio.wait(task_set,\n"
+"return_when=asyncio.FIRST_COMPLETED)`."
+msgstr ""
+
+#: src/async/control-flow/select.md:8
+msgid ""
+"This is usually a macro, similar to match, with each arm of the form `pattern =\n"
+"future => statement`. When the future is ready, the statement is executed with the\n"
+"variable bound to the future's result."
+msgstr ""
+
+#: src/async/control-flow/select.md:12
+msgid ""
+"```rust,editable,compile_fail\n"
+"use tokio::sync::mpsc::{self, Receiver};\n"
+"use tokio::time::{sleep, Duration};\n"
+"\n"
+"#[derive(Debug, PartialEq)]\n"
+"enum Animal {\n"
+" Cat { name: String },\n"
+" Dog { name: String },\n"
+"}\n"
+"\n"
+"async fn first_animal_to_finish_race(\n"
+" mut cat_rcv: Receiver,\n"
+" mut dog_rcv: Receiver,\n"
+") -> Option {\n"
+" tokio::select! {\n"
+" cat_name = cat_rcv.recv() => Some(Animal::Cat { name: cat_name? }),\n"
+" dog_name = dog_rcv.recv() => Some(Animal::Dog { name: dog_name? })\n"
+" }\n"
+"}\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() {\n"
+" let (cat_sender, cat_receiver) = mpsc::channel(32);\n"
+" let (dog_sender, dog_receiver) = mpsc::channel(32);\n"
+" tokio::spawn(async move {\n"
+" sleep(Duration::from_millis(500)).await;\n"
+" cat_sender\n"
+" .send(String::from(\"Felix\"))\n"
+" .await\n"
+" .expect(\"Failed to send cat.\");\n"
+" });\n"
+" tokio::spawn(async move {\n"
+" sleep(Duration::from_millis(50)).await;\n"
+" dog_sender\n"
+" .send(String::from(\"Rex\"))\n"
+" .await\n"
+" .expect(\"Failed to send dog.\");\n"
+" });\n"
+"\n"
+" let winner = first_animal_to_finish_race(cat_receiver, dog_receiver)\n"
+" .await\n"
+" .expect(\"Failed to receive winner\");\n"
+"\n"
+" println!(\"Winner is {winner:?}\");\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/async/control-flow/select.md:61
+msgid ""
+"* In this example, we have a race between a cat and a dog.\n"
+" `first_animal_to_finish_race` listens to both channels and will pick whichever\n"
+" arrives first. Since the dog takes 50ms, it wins against the cat that\n"
+" take 500ms seconds.\n"
+"\n"
+"* You can use `oneshot` channels in this example as the channels are supposed to\n"
+" receive only one `send`.\n"
+"\n"
+"* Try adding a deadline to the race, demonstrating selecting different sorts of\n"
+" futures.\n"
+"\n"
+"* Note that `select!` moves the values it is given. It is easiest to use\n"
+" when every execution of `select!` creates new futures. An alternative is to\n"
+" pass `&mut future` instead of the future itself, but this can lead to\n"
+" issues, further discussed in the pinning slide."
+msgstr ""
+
+#: src/async/pitfalls.md:1
+msgid "# Pitfalls of async/await"
+msgstr ""
+
+#: src/async/pitfalls.md:3
+msgid ""
+"Async / await provides convenient and efficient abstraction for concurrent asynchronous "
+"programming. However, the async/await model in Rust also comes with its share of pitfalls and "
+"footguns. We illustrate some of them in this chapter:"
+msgstr ""
+
+#: src/async/pitfalls.md:5
+msgid ""
+"- [Blocking the Executor](pitfalls/blocking-executor.md)\n"
+"- [Pin](pitfalls/pin.md)\n"
+"- [Async Traits](pitfall/async-traits.md)"
+msgstr ""
+
+#: src/async/pitfalls/blocking-executor.md:1
+msgid "# Blocking the executor"
+msgstr ""
+
+#: src/async/pitfalls/blocking-executor.md:3
+msgid ""
+"Most async runtimes only allow IO tasks to run concurrently.\n"
+"This means that CPU blocking tasks will block the executor and prevent other tasks from being "
+"executed.\n"
+"An easy workaround is to use async equivalent methods where possible."
+msgstr ""
+
+#: src/async/pitfalls/blocking-executor.md:7
+msgid ""
+"```rust,editable,compile_fail\n"
+"use futures::future::join_all;\n"
+"use std::time::Instant;\n"
+"\n"
+"async fn sleep_ms(start: &Instant, id: u64, duration_ms: u64) {\n"
+" std::thread::sleep(std::time::Duration::from_millis(duration_ms));\n"
+" println!(\n"
+" \"future {id} slept for {duration_ms}ms, finished after {}ms\",\n"
+" start.elapsed().as_millis()\n"
+" );\n"
+"}\n"
+"\n"
+"#[tokio::main(flavor = \"current_thread\")]\n"
+"async fn main() {\n"
+" let start = Instant::now();\n"
+" let sleep_futures = (1..=10).map(|t| sleep_ms(&start, t, t * 10));\n"
+" join_all(sleep_futures).await;\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/async/pitfalls/blocking-executor.md:29
+msgid ""
+"* Run the code and see that the sleeps happen consecutively rather than\n"
+" concurrently.\n"
+"\n"
+"* The `\"current_thread\"` flavor puts all tasks on a single thread. This makes the\n"
+" effect more obvious, but the bug is still present in the multi-threaded\n"
+" flavor.\n"
+"\n"
+"* Switch the `std::thread::sleep` to `tokio::time::sleep` and await its result.\n"
+"\n"
+"* Another fix would be to `tokio::task::spawn_blocking` which spawns an actual\n"
+" thread and transforms its handle into a future without blocking the executor.\n"
+"\n"
+"* You should not think of tasks as OS threads. They do not map 1 to 1 and most\n"
+" executors will allow many tasks to run on a single OS thread. This is\n"
+" particularly problematic when interacting with other libraries via FFI, where\n"
+" that library might depend on thread-local storage or map to specific OS\n"
+" threads (e.g., CUDA). Prefer `tokio::task::spawn_blocking` in such situations.\n"
+"\n"
+"* Use sync mutexes with care. Holding a mutex over an `.await` may cause another\n"
+" task to block, and that task may be running on the same thread."
+msgstr ""
+
+#: src/async/pitfalls/pin.md:1
+msgid "# Pin"
+msgstr ""
+
+#: src/async/pitfalls/pin.md:3
+msgid ""
+"When you await a future, all local variables (that would ordinarily be stored on\n"
+"a stack frame) are instead stored in the Future for the current async block. If your\n"
+"future has pointers to data on the stack, those pointers might get invalidated.\n"
+"This is unsafe."
+msgstr ""
+
+#: src/async/pitfalls/pin.md:8
+msgid ""
+"Therefore, you must guarantee that the addresses your future points to don't\n"
+"change. That is why we need to `pin` futures. Using the same future repeatedly\n"
+"in a `select!` often leads to issues with pinned values."
+msgstr ""
+
+#: src/async/pitfalls/pin.md:12
+msgid ""
+"```rust,editable,compile_fail\n"
+"use tokio::sync::{mpsc, oneshot};\n"
+"use tokio::task::spawn;\n"
+"use tokio::time::{sleep, Duration};\n"
+"\n"
+"// A work item. In this case, just sleep for the given time and respond\n"
+"// with a message on the `respond_on` channel.\n"
+"#[derive(Debug)]\n"
+"struct Work {\n"
+" input: u32,\n"
+" respond_on: oneshot::Sender,\n"
+"}\n"
+"\n"
+"// A worker which listens for work on a queue and performs it.\n"
+"async fn worker(mut work_queue: mpsc::Receiver) {\n"
+" let mut iterations = 0;\n"
+" loop {\n"
+" tokio::select! {\n"
+" Some(work) = work_queue.recv() => {\n"
+" sleep(Duration::from_millis(10)).await; // Pretend to work.\n"
+" work.respond_on\n"
+" .send(work.input * 1000)\n"
+" .expect(\"failed to send response\");\n"
+" iterations += 1;\n"
+" }\n"
+" // TODO: report number of iterations every 100ms\n"
+" }\n"
+" }\n"
+"}\n"
+"\n"
+"// A requester which requests work and waits for it to complete.\n"
+"async fn do_work(work_queue: &mpsc::Sender, input: u32) -> u32 {\n"
+" let (tx, rx) = oneshot::channel();\n"
+" work_queue\n"
+" .send(Work {\n"
+" input,\n"
+" respond_on: tx,\n"
+" })\n"
+" .await\n"
+" .expect(\"failed to send on work queue\");\n"
+" rx.await.expect(\"failed waiting for response\")\n"
+"}\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() {\n"
+" let (tx, rx) = mpsc::channel(10);\n"
+" spawn(worker(rx));\n"
+" for i in 0..100 {\n"
+" let resp = do_work(&tx, i).await;\n"
+" println!(\"work result for iteration {i}: {resp}\");\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/async/pitfalls/pin.md:68
+msgid ""
+"* You may recognize this as an example of the actor pattern. Actors\n"
+" typically call `select!` in a loop.\n"
+"\n"
+"* This serves as a summation of a few of the previous lessons, so take your time\n"
+" with it.\n"
+"\n"
+" * Naively add a `_ = sleep(Duration::from_millis(100)) => { println!(..) }`\n"
+" to the `select!`. This will never execute. Why?\n"
+"\n"
+" * Instead, add a `timeout_fut` containing that future outside of the `loop`:\n"
+"\n"
+" ```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"
+" ```\n"
+" * This still doesn't work. Follow the compiler errors, adding `&mut` to the\n"
+" `timeout_fut` in the `select!` to work around the move, then using\n"
+" `Box::pin`:\n"
+"\n"
+" ```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"
+" ```\n"
+"\n"
+" * This compiles, but once the timeout expires it is `Poll::Ready` on every\n"
+" iteration (a fused future would help with this). Update to reset\n"
+" `timeout_fut` every time it expires.\n"
+"\n"
+"* Box allocates on the heap. In some cases, `std::pin::pin!` (only recently\n"
+" stabilized, with older code often using `tokio::pin!`) is also an option, but\n"
+" that is difficult to use for a future that is reassigned.\n"
+"\n"
+"* Another alternative is to not use `pin` at all but spawn another task that will send to a "
+"`oneshot` channel every 100ms."
+msgstr ""
+
+#: src/async/pitfalls/async-traits.md:1
+#, fuzzy
+msgid "# Async Traits"
+msgstr "# Züge"
+
+#: src/async/pitfalls/async-traits.md:3
+msgid ""
+"Async methods in traits are not yet supported in the stable channel ([An experimental feature "
+"exists in nightly and should be stabilized in the mid term.](https://blog.rust-lang.org/inside-"
+"rust/2022/11/17/async-fn-in-trait-nightly.html))"
+msgstr ""
+
+#: src/async/pitfalls/async-traits.md:5
+msgid ""
+"The crate [async_trait](https://docs.rs/async-trait/latest/async_trait/) provides a workaround "
+"through a macro:"
+msgstr ""
+
+#: src/async/pitfalls/async-traits.md:7
+msgid ""
+"```rust,editable,compile_fail\n"
+"use async_trait::async_trait;\n"
+"use std::time::Instant;\n"
+"use tokio::time::{sleep, Duration};\n"
+"\n"
+"#[async_trait]\n"
+"trait Sleeper {\n"
+" async fn sleep(&self);\n"
+"}\n"
+"\n"
+"struct FixedSleeper {\n"
+" sleep_ms: u64,\n"
+"}\n"
+"\n"
+"#[async_trait]\n"
+"impl Sleeper for FixedSleeper {\n"
+" async fn sleep(&self) {\n"
+" sleep(Duration::from_millis(self.sleep_ms)).await;\n"
+" }\n"
+"}\n"
+"\n"
+"async fn run_all_sleepers_multiple_times(sleepers: Vec>, n_times: usize) {\n"
+" for _ in 0..n_times {\n"
+" println!(\"running all sleepers..\");\n"
+" for sleeper in &sleepers {\n"
+" let start = Instant::now();\n"
+" sleeper.sleep().await;\n"
+" println!(\"slept for {}ms\", start.elapsed().as_millis());\n"
+" }\n"
+" }\n"
+"}\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() {\n"
+" let sleepers: Vec> = vec![\n"
+" Box::new(FixedSleeper { sleep_ms: 50 }),\n"
+" Box::new(FixedSleeper { sleep_ms: 100 }),\n"
+" ];\n"
+" run_all_sleepers_multiple_times(sleepers, 5).await;\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/async/pitfalls/async-traits.md:49
+#, fuzzy
+msgid " "
+msgstr ""
+
+#: src/async/pitfalls/async-traits.md:51
+msgid ""
+"* `async_trait` is easy to use, but note that it's using heap allocations to\n"
+" achieve this. This heap allocation has performance overhead.\n"
+"\n"
+"* The challenges in language support for `async trait` are deep Rust and\n"
+" probably not worth describing in-depth. Niko Matsakis did a good job of\n"
+" explaining them in [this\n"
+" post](https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/)\n"
+" if you are interested in digging deeper.\n"
+"\n"
+"* Try creating a new sleeper struct that will sleep for a random amount of time\n"
+" and adding it to the Vec."
+msgstr ""
+
+#: src/exercises/concurrency/afternoon.md:3
+msgid "To practice your Async Rust skills, we have again two exercises for you:"
+msgstr ""
+
+#: src/exercises/concurrency/afternoon.md:5
+msgid ""
+"* Dining philosophers: we already saw this problem in the morning. This time\n"
+" you are going to implement it with Async Rust.\n"
+"\n"
+"* A Broadcast Chat Application: this is a larger project that allows you\n"
+" experiment with more advanced Async Rust features."
+msgstr ""
+
+#: src/exercises/concurrency/dining-philosophers-async.md:1
+#, fuzzy
+msgid "# Dining Philosophers - Async"
+msgstr "# Speisende Philosophen"
+
+#: src/exercises/concurrency/dining-philosophers-async.md:3
+msgid ""
+"See [dining philosophers](dining-philosophers.md) for a description of the\n"
+"problem."
+msgstr ""
+
+#: src/exercises/concurrency/dining-philosophers-async.md:6
+#, fuzzy
+msgid ""
+"As before, you will need a local\n"
+"[Cargo installation](../../cargo/running-locally.md) for this exercise. Copy\n"
+"the code below to a file called `src/main.rs`, fill out the blanks, and test\n"
+"that `cargo run` does not deadlock:"
+msgstr ""
+"Dazu benötigen Sie eine lokale [Cargo-Installation](../../cargo/running-locally.md).\n"
+"diese Übung. Kopieren Sie den folgenden Code in die Datei `src/main.rs`, füllen Sie die Lücken "
+"aus,\n"
+"und teste, dass `cargo run` keinen Deadlock verursacht:"
+
+#: src/exercises/concurrency/dining-philosophers-async.md:13
+msgid ""
+"```rust,compile_fail\n"
+"use std::sync::Arc;\n"
+"use tokio::time;\n"
+"use tokio::sync::mpsc::{self, Sender};\n"
+"use tokio::sync::Mutex;\n"
+"\n"
+"struct Fork;\n"
+"\n"
+"struct Philosopher {\n"
+" name: String,\n"
+" // left_fork: ...\n"
+" // right_fork: ...\n"
+" // thoughts: ...\n"
+"}\n"
+"\n"
+"impl Philosopher {\n"
+" async fn think(&self) {\n"
+" self.thoughts\n"
+" .send(format!(\"Eureka! {} has a new idea!\", &self.name)).await\n"
+" .unwrap();\n"
+" }\n"
+"\n"
+" async fn eat(&self) {\n"
+" // Pick up forks...\n"
+" println!(\"{} is eating...\", &self.name);\n"
+" time::sleep(time::Duration::from_millis(5)).await;\n"
+" }\n"
+"}\n"
+"\n"
+"static PHILOSOPHERS: &[&str] =\n"
+" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() {\n"
+" // Create forks\n"
+"\n"
+" // Create philosophers\n"
+"\n"
+" // Make them think and eat\n"
+"\n"
+" // Output their thoughts\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/dining-philosophers-async.md:57
+msgid ""
+"Since this time you are using Async Rust, you'll need a `tokio` dependency.\n"
+"You can use the following `Cargo.toml`:"
+msgstr ""
+
+#: src/exercises/concurrency/dining-philosophers-async.md:62
+msgid ""
+"```toml\n"
+"[package]\n"
+"name = \"dining-philosophers-async-dine\"\n"
+"version = \"0.1.0\"\n"
+"edition = \"2021\"\n"
+"\n"
+"[dependencies]\n"
+"tokio = {version = \"1.26.0\", features = [\"sync\", \"time\", \"macros\", \"rt-multi-thread\"]}\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/dining-philosophers-async.md:72
+msgid ""
+"Also note that this time you have to use the `Mutex` and the `mpsc` module\n"
+"from the `tokio` crate."
+msgstr ""
+
+#: src/exercises/concurrency/dining-philosophers-async.md:77
+msgid "* Can you make your implementation single-threaded? "
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:1
+msgid "# Broadcast Chat Application"
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:3
+msgid ""
+"In this exercise, we want to use our new knowledge to implement a broadcast\n"
+"chat application. We have a chat server that the clients connect to and publish\n"
+"their messages. The client reads user messages from the standard input, and\n"
+"sends them to the server. The chat server broadcasts each message that it\n"
+"receives to all the clients."
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:9
+msgid ""
+"For this, we use [a broadcast channel][1] on the server, and\n"
+"[`tokio_websockets`][2] for the communication between the client and the\n"
+"server."
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:13
+msgid "Create a new Cargo project and add the following dependencies:"
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:15
+msgid "`Cargo.toml`:"
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:19
+msgid ""
+"```toml\n"
+"[package]\n"
+"name = \"chat-async\"\n"
+"version = \"0.1.0\"\n"
+"edition = \"2021\"\n"
+"\n"
+"[dependencies]\n"
+"futures-util = \"0.3.28\"\n"
+"http = \"0.2.9\"\n"
+"tokio = { version = \"1.28.1\", features = [\"full\"] }\n"
+"tokio-websockets = \"0.3.2\"\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:32
+msgid "## The required APIs"
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:33
+msgid ""
+"You are going to need the following functions from `tokio` and\n"
+"[`tokio_websockets`][2]. Spend a few minutes to familiarize yourself with the\n"
+"API. "
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:37
+msgid ""
+"- [WebsocketStream::next()][3]: for asynchronously reading messages from a\n"
+" Websocket Stream.\n"
+"- [SinkExt::send()][4] implemented by `WebsocketStream`: for asynchronously\n"
+" sending messages on a Websocket Stream.\n"
+"- [BufReader::read_line()][5]: for asynchronously reading user messages\n"
+" from the standard input.\n"
+"- [Sender::subscribe()][6]: for subscribing to a broadcast channel."
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:46
+#, fuzzy
+msgid "## Two binaries"
+msgstr "# Rust-Binärdateien"
+
+#: src/exercises/concurrency/chat-app.md:48
+msgid ""
+"Normally in a Cargo project, you can have only one binary, and one\n"
+"`src/main.rs` file. In this project, we need two binaries. One for the client,\n"
+"and one for the server. You could potentially make them two separate Cargo\n"
+"projects, but we are going to put them in a single Cargo project with two\n"
+"binaries. For this to work, the client and the server code should go under\n"
+"`src/bin` (see the [documentation][7]). "
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:55
+msgid ""
+"Copy the following server and client code into `src/bin/server.rs` and\n"
+"`src/bin/client.rs`, respectively. Your task is to complete these files as\n"
+"described below. "
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:59 src/exercises/concurrency/solutions-afternoon.md:117
+#, fuzzy
+msgid "`src/bin/server.rs`:"
+msgstr "_hello_rust/src/main.rs_:"
+
+#: src/exercises/concurrency/chat-app.md:61
+msgid ""
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:63
+msgid ""
+"```rust,compile_fail\n"
+"use futures_util::sink::SinkExt;\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"
+"\n"
+"async fn handle_connection(\n"
+" addr: SocketAddr,\n"
+" mut ws_stream: WebsocketStream,\n"
+" bcast_tx: Sender,\n"
+") -> Result<(), Box> {\n"
+"\n"
+" // TODO: For a hint, see the description of the task below.\n"
+"\n"
+"}\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() -> Result<(), Box> {\n"
+" let (bcast_tx, _) = channel(16);\n"
+"\n"
+" let listener = TcpListener::bind(\"127.0.0.1:2000\").await?;\n"
+" println!(\"listening on port 2000\");\n"
+"\n"
+" loop {\n"
+" let (socket, addr) = listener.accept().await?;\n"
+" println!(\"New connection from {addr:?}\");\n"
+" let bcast_tx = bcast_tx.clone();\n"
+" tokio::spawn(async move {\n"
+" // Wrap the raw TCP stream into a websocket.\n"
+" let ws_stream = ServerBuilder::new().accept(socket).await?;\n"
+"\n"
+" handle_connection(addr, ws_stream, bcast_tx).await\n"
+" });\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:102 src/exercises/concurrency/solutions-afternoon.md:202
+#, fuzzy
+msgid "`src/bin/client.rs`:"
+msgstr "_hello_rust/src/main.rs_:"
+
+#: src/exercises/concurrency/chat-app.md:104
+msgid ""
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:106
+msgid ""
+"```rust,compile_fail\n"
+"use futures_util::SinkExt;\n"
+"use http::Uri;\n"
+"use tokio::io::{AsyncBufReadExt, BufReader};\n"
+"use tokio_websockets::{ClientBuilder, Message};\n"
+"\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"
+"\n"
+" let stdin = tokio::io::stdin();\n"
+" let mut stdin = BufReader::new(stdin);\n"
+"\n"
+"\n"
+" // TODO: For a hint, see the description of the task below.\n"
+"\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/chat-app.md:127
+#, fuzzy
+msgid "## Running the binaries"
+msgstr "# Ablauf des Kurses"
+
+#: src/exercises/concurrency/chat-app.md:128
+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
+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
+msgid ""
+"* Implement the `handle_connection` function in `src/bin/server.rs`.\n"
+" * Hint: Use `tokio::select!` for concurrently performing two tasks in a\n"
+" continuous loop. One task receives messages from the client and broadcasts\n"
+" them. The other sends messages received by the server to the client.\n"
+"* Complete the main function in `src/bin/client.rs`.\n"
+" * Hint: As before, use `tokio::select!` in a continuous loop for concurrently\n"
+" performing two tasks: (1) reading user messages from standard input and\n"
+" sending them to the server, and (2) receiving messages from the server, and\n"
+" displaying them for the user.\n"
+"* Optional: Once you are done, change the code to broadcast messages to all\n"
+" clients, but the sender of the message."
+msgstr ""
+
+#: src/thanks.md:1
+#, fuzzy
+msgid "# Thanks!"
+msgstr "# Danke!"
+
+#: src/thanks.md:3
+#, fuzzy
+msgid ""
+"_Thank you for taking Comprehensive Rust 🦀!_ We hope you enjoyed it and that it\n"
+"was useful."
+msgstr ""
+"_Vielen Dank, dass Sie Comprehensive Rust 🦀 genommen haben!_ Wir hoffen, dass es Ihnen gefallen "
+"hat und dass es\n"
+"war nützlich."
+
+#: src/thanks.md:6
+#, fuzzy
+msgid ""
+"We've had a lot of fun putting the course together. The course is not perfect,\n"
+"so if you spotted any mistakes or have ideas for improvements, please get in\n"
+"[contact with us on\n"
+"GitHub](https://github.com/google/comprehensive-rust/discussions). We would love\n"
+"to hear from you."
+msgstr ""
+"Es hat uns viel Spaß gemacht, den Kurs zusammenzustellen. Der Kurs ist nicht perfekt,\n"
+"Wenn Sie also Fehler entdeckt haben oder Verbesserungsvorschläge haben, melden Sie sich bitte\n"
+"[Kontakt mit uns auf\n"
+"GitHub](https://github.com/google/comprehensive-rust/discussions). Wir würden lieben\n"
+"von dir zu hören."
+
+#: src/other-resources.md:1
+#, fuzzy
+msgid "# Other Rust Resources"
+msgstr "# Andere Rostressourcen"
+
+#: src/other-resources.md:3
+#, fuzzy
+msgid ""
+"The Rust community has created a wealth of high-quality and free resources\n"
+"online."
+msgstr ""
+"Die Rust-Community hat eine Fülle hochwertiger und kostenloser Ressourcen geschaffen\n"
+"online."
+
+#: src/other-resources.md:6
+#, fuzzy
+msgid "## Official Documentation"
+msgstr "## Offizielle Dokumentation"
+
+#: src/other-resources.md:8
+#, fuzzy
+msgid "The Rust project hosts many resources. These cover Rust in general:"
+msgstr "Das Rust-Projekt beherbergt viele Ressourcen. Diese decken Rust im Allgemeinen ab:"
+
+#: src/other-resources.md:10
+#, fuzzy
+msgid ""
+"* [The Rust Programming Language](https://doc.rust-lang.org/book/): the\n"
+" canonical free book about Rust. Covers the language in detail and includes a\n"
+" few projects for people to build.\n"
+"* [Rust By Example](https://doc.rust-lang.org/rust-by-example/): covers the Rust\n"
+" syntax via a series of examples which showcase different constructs. Sometimes\n"
+" includes small exercises where you are asked to expand on the code in the\n"
+" examples.\n"
+"* [Rust Standard Library](https://doc.rust-lang.org/std/): full documentation of\n"
+" the standard library for Rust.\n"
+"* [The Rust Reference](https://doc.rust-lang.org/reference/): an incomplete book\n"
+" which describes the Rust grammar and memory model."
+msgstr ""
+"* [Die Programmiersprache Rust](https://doc.rust-lang.org/book/): die\n"
+" Kanonisches kostenloses Buch über Rust. Deckt die Sprache im Detail ab und enthält a\n"
+" wenige Projekte für Menschen zu bauen.\n"
+"* [Rust By Example](https://doc.rust-lang.org/rust-by-example/): deckt den Rust ab\n"
+" Syntax über eine Reihe von Beispielen, die verschiedene Konstrukte demonstrieren. Manchmal\n"
+" enthält kleine Übungen, in denen Sie aufgefordert werden, den Code in der zu erweitern\n"
+" Beispiele.\n"
+"* [Rust Standard Library](https://doc.rust-lang.org/std/): vollständige Dokumentation von\n"
+" die Standardbibliothek für Rust.\n"
+"* [The Rust Reference](https://doc.rust-lang.org/reference/): ein unvollständiges Buch\n"
+" das die Rust-Grammatik und das Speichermodell beschreibt."
+
+#: src/other-resources.md:22
+#, fuzzy
+msgid "More specialized guides hosted on the official Rust site:"
+msgstr "Weitere spezialisierte Guides, die auf der offiziellen Rust-Website gehostet werden:"
+
+#: src/other-resources.md:24
+#, fuzzy
+msgid ""
+"* [The Rustonomicon](https://doc.rust-lang.org/nomicon/): covers unsafe Rust,\n"
+" including working with raw pointers and interfacing with other languages\n"
+" (FFI).\n"
+"* [Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/):\n"
+" covers the new asynchronous programming model which was introduced after the\n"
+" Rust Book was written.\n"
+"* [The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/): an\n"
+" introduction to using Rust on embedded devices without an operating system."
+msgstr ""
+"* [The Rustonomicon](https://doc.rust-lang.org/nomicon/): deckt unsicheres Rust ab,\n"
+" einschließlich der Arbeit mit rohen Zeigern und der Anbindung an andere Sprachen\n"
+" (FFI).\n"
+"* [Asynchrone Programmierung in Rust](https://rust-lang.github.io/async-book/):\n"
+" deckt das neue asynchrone Programmiermodell ab, das nach dem eingeführt wurde\n"
+" Rust Book wurde geschrieben.\n"
+"* [Das eingebettete Rust-Buch] (https://doc.rust-lang.org/stable/embedded-book/): an\n"
+" Einführung in die Verwendung von Rust auf eingebetteten Geräten ohne Betriebssystem."
+
+#: src/other-resources.md:33
+#, fuzzy
+msgid "## Unofficial Learning Material"
+msgstr "## Inoffizielles Lernmaterial"
+
+#: src/other-resources.md:35
+#, fuzzy
+msgid "A small selection of other guides and tutorial for Rust:"
+msgstr "Eine kleine Auswahl an weiteren Guides und Tutorials für Rust:"
+
+#: src/other-resources.md:37
+#, fuzzy
+msgid ""
+"* [Learn Rust the Dangerous Way](http://cliffle.com/p/dangerust/): covers Rust\n"
+" from the perspective of low-level C programmers.\n"
+"* [Rust for Embedded C\n"
+" Programmers](https://docs.opentitan.org/doc/ug/rust_for_c/): covers Rust from\n"
+" the perspective of developers who write firmware in C.\n"
+"* [Rust for professionals](https://overexact.com/rust-for-professionals/):\n"
+" covers the syntax of Rust using side-by-side comparisons with other languages\n"
+" such as C, C++, Java, JavaScript, and Python.\n"
+"* [Rust on Exercism](https://exercism.org/tracks/rust): 100+ exercises to help\n"
+" you learn Rust.\n"
+"* [Ferrous Teaching\n"
+" Material](https://ferrous-systems.github.io/teaching-material/index.html): a\n"
+" series of small presentations covering both basic and advanced part of the\n"
+" Rust language. Other topics such as WebAssembly, and async/await are also\n"
+" covered.\n"
+"* [Beginner's Series to\n"
+" Rust](https://docs.microsoft.com/en-us/shows/beginners-series-to-rust/) and\n"
+" [Take your first steps with\n"
+" Rust](https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/): two\n"
+" Rust guides aimed at new developers. The first is a set of 35 videos and the\n"
+" second is a set of 11 modules which covers Rust syntax and basic constructs.\n"
+"* [Learn Rust With Entirely Too Many Linked\n"
+" Lists](https://rust-unofficial.github.io/too-many-lists/): in-depth\n"
+" exploration of Rust's memory management rules, through implementing a few\n"
+" different types of list structures."
+msgstr ""
+"* [Learn Rust the Dangerous Way](http://cliffle.com/p/dangerust/): deckt Rust ab\n"
+" aus der Perspektive von Low-Level-C-Programmierern.\n"
+"* [Rost für eingebettetes C\n"
+" Programmierer] (https://docs.opentitan.org/doc/ug/rust_for_c/): deckt Rust ab\n"
+" die Perspektive von Entwicklern, die Firmware in C schreiben.\n"
+"* [Rost für Profis](https://overexact.com/rust-for-professionals/):\n"
+" deckt die Syntax von Rust durch Side-by-Side-Vergleiche mit anderen Sprachen ab\n"
+" wie C, C++, Java, JavaScript und Python.\n"
+"* [Rust on Exercism](https://exercism.org/tracks/rust): Über 100 hilfreiche Übungen\n"
+" Sie lernen Rost.\n"
+"* [Eisenlehre\n"
+" Material](https://ferrous-systems.github.io/teaching-material/index.html): a\n"
+" Reihe von kleinen Präsentationen, die sowohl den grundlegenden als auch den fortgeschrittenen "
+"Teil des\n"
+" Rostige Sprache. Andere Themen wie WebAssembly und async/await sind ebenfalls enthalten\n"
+" bedeckt.\n"
+"* [Anfängerserie bis\n"
+" Rust](https://docs.microsoft.com/en-us/shows/beginners-series-to-rust/) und\n"
+" [Machen Sie Ihre ersten Schritte mit\n"
+" Rust](https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/): zwei\n"
+" Rust-Leitfäden für neue Entwickler. Die erste ist eine Reihe von 35 Videos und die\n"
+" Das zweite ist ein Satz von 11 Modulen, der die Rust-Syntax und grundlegende Konstrukte abdeckt."
+
+#: src/other-resources.md:63
+#, fuzzy
+msgid ""
+"Please see the [Little Book of Rust Books](https://lborb.github.io/book/) for\n"
+"even more Rust books."
+msgstr ""
+"Weitere Informationen finden Sie im [Little Book of Rust Books] (https://lborb.github.io/book/).\n"
+"noch mehr Rust-Bücher."
+
+#: src/credits.md:1
+#, fuzzy
+msgid "# Credits"
+msgstr "# Credits"
+
+#: src/credits.md:3
+#, fuzzy
+msgid ""
+"The material here builds on top of the many great sources of Rust documentation.\n"
+"See the page on [other resources](other-resources.md) for a full list of useful\n"
+"resources."
+msgstr ""
+"Das Material hier baut auf den vielen großartigen Quellen der Rust-Dokumentation auf.\n"
+"Auf der Seite [andere Ressourcen] (other-resources.md) finden Sie eine vollständige Liste "
+"nützlicher Ressourcen\n"
+"Ressourcen."
+
+#: src/credits.md:7
+#, fuzzy
+msgid ""
+"The material of Comprehensive Rust is licensed under the terms of the Apache 2.0\n"
+"license, please see [`LICENSE`](../LICENSE) for details."
+msgstr ""
+"Das Material von Comprehensive Rust ist unter den Bedingungen von Apache 2.0 lizenziert\n"
+"Lizenz finden Sie unter [`LICENSE`](../LICENSE) für Einzelheiten."
+
+#: src/credits.md:10
+#, fuzzy
+msgid "## Rust by Example"
+msgstr "## Rost zum Beispiel"
+
+#: src/credits.md:12
+#, fuzzy
+msgid ""
+"Some examples and exercises have been copied and adapted from [Rust by\n"
+"Example](https://doc.rust-lang.org/rust-by-example/). Please see the\n"
+"`third_party/rust-by-example/` directory for details, including the license\n"
+"terms."
+msgstr ""
+"Einige Beispiele und Übungen wurden aus [Rust by\n"
+"Beispiel](https://doc.rust-lang.org/rust-by-example/). Bitte sehen Sie sich ... an\n"
+"`third_party/rust-by-example/`-Verzeichnis für Details, einschließlich der Lizenz\n"
+"Bedingungen."
+
+#: src/credits.md:17
+#, fuzzy
+msgid "## Rust on Exercism"
+msgstr "## Rost auf Übung"
+
+#: src/credits.md:19
+#, fuzzy
+msgid ""
+"Some exercises have been copied and adapted from [Rust on\n"
+"Exercism](https://exercism.org/tracks/rust). Please see the\n"
+"`third_party/rust-on-exercism/` directory for details, including the license\n"
+"terms."
+msgstr ""
+"Einige Übungen wurden von [Rust on\n"
+"Übung] (https://exercism.org/tracks/rust). Bitte sehen Sie sich ... an\n"
+"`third_party/rust-on-exercism/`-Verzeichnis für Details, einschließlich der Lizenz\n"
+"Bedingungen."
+
+#: src/credits.md:24
+#, fuzzy
+msgid "## CXX"
+msgstr "##CXX"
+
+#: src/credits.md:26
+#, fuzzy
+msgid ""
+"The [Interoperability with C++](android/interoperability/cpp.md) section uses an\n"
+"image from [CXX](https://cxx.rs/). Please see the `third_party/cxx/` directory\n"
+"for details, including the license terms."
+msgstr ""
+"Der Abschnitt [Interoperability with C++](android/interoperability/cpp.md) verwendet eine\n"
+"Bild von [CXX](https://cxx.rs/). Bitte sehen Sie sich das Verzeichnis `third_party/cxx/` an\n"
+"für Details, einschließlich der Lizenzbedingungen."
+
#: src/exercises/solutions.md:1
#, fuzzy
msgid "# Solutions"
@@ -17879,16 +18004,16 @@ msgid ""
" }\n"
"}\n"
"\n"
-"// This makes it possible to print Book values with {}.\n"
-"impl std::fmt::Display for Book {\n"
-" fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n"
-" write!(f, \"{} ({})\", self.title, self.year)\n"
-" }\n"
-"}\n"
-"// ANCHOR_END: setup\n"
-"\n"
-"// ANCHOR: Library_new\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"
+" // ANCHOR_END: setup\n"
+"\n"
+" // ANCHOR: Library_new\n"
" fn new() -> Library {\n"
" // ANCHOR_END: Library_new\n"
" Library { books: Vec::new() }\n"
@@ -17896,7 +18021,7 @@ msgid ""
"\n"
" // ANCHOR: Library_len\n"
" //fn len(self) -> usize {\n"
-" // unimplemented!()\n"
+" // todo!(\"Return the length of `self.books`\")\n"
" //}\n"
" // ANCHOR_END: Library_len\n"
" fn len(&self) -> usize {\n"
@@ -17905,7 +18030,7 @@ msgid ""
"\n"
" // ANCHOR: Library_is_empty\n"
" //fn is_empty(self) -> bool {\n"
-" // unimplemented!()\n"
+" // todo!(\"Return `true` if `self.books` is empty\")\n"
" //}\n"
" // ANCHOR_END: Library_is_empty\n"
" fn is_empty(&self) -> bool {\n"
@@ -17914,7 +18039,7 @@ msgid ""
"\n"
" // ANCHOR: Library_add_book\n"
" //fn add_book(self, book: Book) {\n"
-" // unimplemented!()\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"
@@ -17923,22 +18048,33 @@ msgid ""
"\n"
" // ANCHOR: Library_print_books\n"
" //fn print_books(self) {\n"
-" // unimplemented!()\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!(\"{}\", book);\n"
+" println!(\"{}, published in {}\", book.title, book.year);\n"
" }\n"
" }\n"
"\n"
" // ANCHOR: Library_oldest_book\n"
" //fn oldest_book(self) -> Option<&Book> {\n"
-" // unimplemented!()\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"
-" self.books.iter().min_by_key(|book| book.year)\n"
+" // Using a closure and a built-in method:\n"
+" // self.books.iter().min_by_key(|book| book.year)\n"
+"\n"
+" // Longer hand-written solution:\n"
+" let mut oldest: Option<&Book> = None;\n"
+" for book in self.books.iter() {\n"
+" if oldest.is_none() || book.year < oldest.unwrap().year {\n"
+" oldest = Some(book);\n"
+" }\n"
+" }\n"
+"\n"
+" oldest\n"
" }\n"
"}\n"
"\n"
@@ -17950,24 +18086,23 @@ msgid ""
"fn main() {\n"
" let library = Library::new();\n"
"\n"
-" //println!(\"Our library is empty: {}\", library.is_empty());\n"
-"\n"
-" let favorite_book = Book::new(\"Lord of the Rings\", 1954);\n"
-" println!(\"Our favorite book {favorite_book} should go in the library\");\n"
-" //library.add_book(favorite_book);\n"
+" //println!(\"The 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());\n"
+" //\n"
+" //\n"
" //library.print_books();\n"
" //\n"
" //match library.oldest_book() {\n"
-" // Some(book) => println!(\"My oldest book is {book}\"),\n"
-" // None => println!(\"My library is empty!\"),\n"
+" // Some(book) => println!(\"The oldest book is {}\", book.title),\n"
+" // None => println!(\"The library is empty!\"),\n"
" //}\n"
" //\n"
-" //println!(\"Our library has {} books\", library.len());\n"
-" for book in library.books {\n"
-" println!(\"{book}\");\n"
-" }\n"
+" //println!(\"The library has {} books\", library.len());\n"
+" //library.print_books();\n"
"}\n"
"// ANCHOR_END: main\n"
"\n"
@@ -18794,119 +18929,43 @@ msgid ""
" Ok(())\n"
"}\n"
"// ANCHOR_END: main\n"
-"```"
-msgstr ""
-
-#: src/exercises/day-4/solutions-morning.md:1
-#, fuzzy
-msgid "# Day 4 Morning Exercise"
-msgstr "# Tag 4 Morgengymnastik"
-
-#: src/exercises/day-4/solutions-morning.md:3
-#, fuzzy
-msgid "## Dining Philosophers"
-msgstr "## Essende Philosophen"
-
-#: src/exercises/day-4/solutions-morning.md:5
-#, fuzzy
-msgid "([back to exercise](dining-philosophers.md))"
-msgstr "([zurück zur Übung](dining-philosophers.md))"
-
-#: src/exercises/day-4/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"
+"#[cfg(test)]\n"
+"mod tests {\n"
+" use super::*;\n"
+" use std::error::Error;\n"
"\n"
-"struct Fork;\n"
-"\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"
-"\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"
-" .map(|_| Arc::new(Mutex::new(Fork)))\n"
-" .collect::>();\n"
-"\n"
-" for i in 0..forks.len() {\n"
-" let tx = tx.clone();\n"
-" let mut left_fork = forks[i].clone();\n"
-" let mut right_fork = forks[(i + 1) % forks.len()].clone();\n"
-"\n"
-" // To avoid a deadlock, we have to break the symmetry\n"
-" // somewhere. This will swap the forks without deinitializing\n"
-" // either of them.\n"
-" if i == forks.len() - 1 {\n"
-" std::mem::swap(&mut left_fork, &mut right_fork);\n"
-" }\n"
-"\n"
-" let philosopher = Philosopher {\n"
-" name: PHILOSOPHERS[i].to_string(),\n"
-" thoughts: tx,\n"
-" left_fork,\n"
-" right_fork,\n"
-" };\n"
-"\n"
-" thread::spawn(move || {\n"
-" for _ in 0..100 {\n"
-" philosopher.eat();\n"
-" philosopher.think();\n"
-" }\n"
-" });\n"
+" #[test]\n"
+" fn test_nonexisting_directory() {\n"
+" let iter = DirectoryIterator::new(\"no-such-directory\");\n"
+" assert!(iter.is_err());\n"
" }\n"
"\n"
-" drop(tx);\n"
-" for thought in rx {\n"
-" println!(\"{thought}\");\n"
+" #[test]\n"
+" fn test_empty_directory() -> Result<(), Box> {\n"
+" let tmp = tempfile::TempDir::new()?;\n"
+" let iter = DirectoryIterator::new(\n"
+" tmp.path().to_str().ok_or(\"Non UTF-8 character in path\")?,\n"
+" )?;\n"
+" let mut entries = iter.collect::>();\n"
+" entries.sort();\n"
+" assert_eq!(entries, &[\".\", \"..\"]);\n"
+" Ok(())\n"
+" }\n"
+"\n"
+" #[test]\n"
+" fn test_nonempty_directory() -> Result<(), Box> {\n"
+" let tmp = tempfile::TempDir::new()?;\n"
+" std::fs::write(tmp.path().join(\"foo.txt\"), \"The Foo Diaries\\n\")?;\n"
+" std::fs::write(tmp.path().join(\"bar.png\"), \"\\n\")?;\n"
+" std::fs::write(tmp.path().join(\"crab.rs\"), \"//! Crab\\n\")?;\n"
+" let iter = DirectoryIterator::new(\n"
+" tmp.path().to_str().ok_or(\"Non UTF-8 character in path\")?,\n"
+" )?;\n"
+" let mut entries = iter.collect::>();\n"
+" entries.sort();\n"
+" assert_eq!(entries, &[\".\", \"..\", \"bar.png\", \"crab.rs\", \"foo.txt\"]);\n"
+" Ok(())\n"
" }\n"
"}\n"
"```"
@@ -19143,7 +19202,8 @@ msgid ""
"use arm_gic::gicv3::GicV3;\n"
"use core::panic::PanicInfo;\n"
"use log::{error, info, trace, LevelFilter};\n"
-"use psci::system_off;\n"
+"use smccc::psci::system_off;\n"
+"use smccc::Hvc;\n"
"\n"
"/// Base addresses of the GICv3.\n"
"const GICD_BASE_ADDRESS: *mut u64 = 0x800_0000 as _;\n"
@@ -19235,24 +19295,24 @@ msgid ""
" info!(\"Finished waiting\");\n"
"\n"
" // ANCHOR: main_end\n"
-" system_off().unwrap();\n"
+" system_off::().unwrap();\n"
"}\n"
"\n"
"#[panic_handler]\n"
"fn panic(info: &PanicInfo) -> ! {\n"
" error!(\"{info}\");\n"
-" system_off().unwrap();\n"
+" system_off::().unwrap();\n"
" loop {}\n"
"}\n"
"// ANCHOR_END: main_end\n"
"```"
msgstr ""
-#: src/exercises/bare-metal/solutions-afternoon.md:148
+#: src/exercises/bare-metal/solutions-afternoon.md:149
msgid "`pl031.rs`:"
msgstr ""
-#: src/exercises/bare-metal/solutions-afternoon.md:150
+#: src/exercises/bare-metal/solutions-afternoon.md:151
msgid ""
"```rust\n"
"// Copyright 2023 Google LLC\n"
@@ -19377,6 +19437,595 @@ msgid ""
"```"
msgstr ""
+#: src/exercises/concurrency/solutions-morning.md:1
+#, fuzzy
+msgid "# Concurrency Morning Exercise"
+msgstr "# Tag 3 Morgengymnastik"
+
+#: src/exercises/concurrency/solutions-morning.md:3
+#, fuzzy
+msgid "## Dining Philosophers"
+msgstr "## Essende Philosophen"
+
+#: src/exercises/concurrency/solutions-morning.md:5
+#, fuzzy
+msgid "([back to exercise](dining-philosophers.md))"
+msgstr "([zurück zur Übung](dining-philosophers.md))"
+
+#: 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"
+"\n"
+"struct Fork;\n"
+"\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"
+"\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"
+" .map(|_| Arc::new(Mutex::new(Fork)))\n"
+" .collect::>();\n"
+"\n"
+" for i in 0..forks.len() {\n"
+" let tx = tx.clone();\n"
+" let mut left_fork = forks[i].clone();\n"
+" let mut right_fork = forks[(i + 1) % forks.len()].clone();\n"
+"\n"
+" // To avoid a deadlock, we have to break the symmetry\n"
+" // somewhere. This will swap the forks without deinitializing\n"
+" // either of them.\n"
+" if i == forks.len() - 1 {\n"
+" std::mem::swap(&mut left_fork, &mut right_fork);\n"
+" }\n"
+"\n"
+" let philosopher = Philosopher {\n"
+" name: PHILOSOPHERS[i].to_string(),\n"
+" thoughts: tx,\n"
+" left_fork,\n"
+" right_fork,\n"
+" };\n"
+"\n"
+" thread::spawn(move || {\n"
+" for _ in 0..100 {\n"
+" philosopher.eat();\n"
+" philosopher.think();\n"
+" }\n"
+" });\n"
+" }\n"
+"\n"
+" drop(tx);\n"
+" for thought in rx {\n"
+" println!(\"{thought}\");\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/solutions-afternoon.md:1
+#, fuzzy
+msgid "# Concurrency Afternoon Exercise"
+msgstr "# Tag 1 Nachmittagsübungen"
+
+#: src/exercises/concurrency/solutions-afternoon.md:3
+#, fuzzy
+msgid "## Dining Philosophers - Async"
+msgstr "## Essende Philosophen"
+
+#: src/exercises/concurrency/solutions-afternoon.md:5
+#, fuzzy
+msgid "([back to exercise](dining-philosophers-async.md))"
+msgstr "([zurück zur Übung](dining-philosophers.md))"
+
+#: 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"
+"use tokio::sync::Mutex;\n"
+"\n"
+"struct Fork;\n"
+"\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"
+" .send(format!(\"Eureka! {} has a new idea!\", &self.name)).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"
+" // to transfer to another task\n"
+" 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"
+"\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::new(Fork))));\n"
+"\n"
+" // Create philosophers\n"
+" let (philosophers, mut rx) = {\n"
+" let mut philosophers = vec![];\n"
+" let (tx, rx) = mpsc::channel(10);\n"
+" for (i, name) in PHILOSOPHERS.iter().enumerate() {\n"
+" let left_fork = forks[i].clone();\n"
+" let right_fork = forks[(i + 1) % PHILOSOPHERS.len()].clone();\n"
+" philosophers.push(Philosopher {\n"
+" name: name.to_string(),\n"
+" left_fork: if i % 2 == 0 { left_fork.clone() } else { right_fork.clone() },\n"
+" right_fork: if i % 2 == 0 { right_fork } else { left_fork },\n"
+" thoughts: tx.clone(),\n"
+" });\n"
+" }\n"
+" (philosophers, rx)\n"
+" // tx is dropped here, so we don't need to explicitly drop it later\n"
+" };\n"
+"\n"
+" // Make them think and eat\n"
+" for phil in philosophers {\n"
+" tokio::spawn(async move {\n"
+" for _ in 0..100 {\n"
+" phil.think().await;\n"
+" phil.eat().await;\n"
+" }\n"
+" });\n"
+"\n"
+" }\n"
+"\n"
+" // Output their thoughts\n"
+" while let Some(thought) = rx.recv().await {\n"
+" println!(\"Here is a thought: {thought}\");\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/solutions-afternoon.md:113
+msgid "## Broadcast Chat Application"
+msgstr ""
+
+#: src/exercises/concurrency/solutions-afternoon.md:115
+#, fuzzy
+msgid "([back to exercise](chat-app.md))"
+msgstr "([zurück zur Übung](luhn.md))"
+
+#: src/exercises/concurrency/solutions-afternoon.md:119
+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 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"
+" .await?;\n"
+" let mut bcast_rx = bcast_tx.subscribe();\n"
+"\n"
+" // A continuous loop for concurrently performing two tasks: (1) receiving\n"
+" // messages from `ws_stream` and broadcasting them, and (2) receiving\n"
+" // messages on `bcast_rx` and sending them to the client.\n"
+" loop {\n"
+" tokio::select! {\n"
+" 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"
+" }\n"
+" Some(Err(err)) => return Err(err.into()),\n"
+" None => return Ok(()),\n"
+" }\n"
+" }\n"
+" msg = bcast_rx.recv() => {\n"
+" ws_stream.send(Message::text(msg?)).await?;\n"
+" }\n"
+" }\n"
+" }\n"
+" // ANCHOR: main\n"
+"}\n"
+"\n"
+"#[tokio::main]\n"
+"async fn main() -> Result<(), Box> {\n"
+" let (bcast_tx, _) = channel(16);\n"
+"\n"
+" let listener = TcpListener::bind(\"127.0.0.1:2000\").await?;\n"
+" println!(\"listening on port 2000\");\n"
+"\n"
+" loop {\n"
+" let (socket, addr) = listener.accept().await?;\n"
+" println!(\"New connection from {addr:?}\");\n"
+" let bcast_tx = bcast_tx.clone();\n"
+" tokio::spawn(async move {\n"
+" // Wrap the raw TCP stream into a websocket.\n"
+" let ws_stream = ServerBuilder::new().accept(socket).await?;\n"
+"\n"
+" handle_connection(addr, ws_stream, bcast_tx).await\n"
+" });\n"
+" }\n"
+"}\n"
+"// ANCHOR_END: main\n"
+"```"
+msgstr ""
+
+#: src/exercises/concurrency/solutions-afternoon.md:204
+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::SinkExt;\n"
+"use http::Uri;\n"
+"use tokio::io::{AsyncBufReadExt, BufReader};\n"
+"use tokio_websockets::{ClientBuilder, Message};\n"
+"\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"
+"\n"
+" let stdin = tokio::io::stdin();\n"
+" let mut stdin = BufReader::new(stdin);\n"
+"\n"
+" // ANCHOR_END: setup\n"
+" // Continuous loop for concurrently sending and receiving messages.\n"
+" loop {\n"
+" let mut line = String::new();\n"
+" tokio::select! {\n"
+" incoming = ws_stream.next() => {\n"
+" match incoming {\n"
+" Some(Ok(msg)) => println!(\"From server: {}\", msg.as_text()?),\n"
+" Some(Err(err)) => return Err(err.into()),\n"
+" None => return Ok(()),\n"
+" }\n"
+" }\n"
+" res = stdin.read_line(&mut line) => {\n"
+" match res {\n"
+" Ok(0) => return Ok(()),\n"
+" Ok(_) => ws_stream.send(Message::text(line.trim_end().to_string())).await?,\n"
+" Err(err) => return Err(err.into()),\n"
+" }\n"
+" }\n"
+"\n"
+" }\n"
+" }\n"
+"}\n"
+"```"
+msgstr ""
+
+#~ msgid "Day 4"
+#~ msgstr "Der vierte Tag"
+
+#~ msgid "Closures"
+#~ msgstr "Funktionsabschlüsse"
+
+#~ msgid "Day 4: Morning"
+#~ msgstr "Tag 4: Morgens"
+
+#~ msgid "Day 4: Afternoon (Android)"
+#~ msgstr "Tag 4: Nachmittags (Android)"
+
+#~ msgid "Day 4: Afternoon (Async)"
+#~ msgstr "Tag 4: Nachmittags (Async)"
+
+#~ msgid "Day 4 Morning"
+#~ msgstr "Tag 4 Morgens"
+
+#~ msgid "On Day 4, we will cover Android-specific things such as:"
+#~ msgstr "An Tag 4 behandeln wir Android-spezifische Dinge wie:"
+
+#~ msgid ""
+#~ "* Building Android components in Rust.\n"
+#~ "* AIDL servers and clients.\n"
+#~ "* Interoperability with C, C++, and Java."
+#~ msgstr ""
+#~ "* Erstellen von Android-Komponenten in Rust.\n"
+#~ "* AIDL-Server und -Klienten.\n"
+#~ "* Interoperabilität mit C, C++ und Java."
+
+#~ msgid ""
+#~ "It is important to note that this course does not cover Android **application** \n"
+#~ "development in Rust, and that the Android-specific parts are specifically about\n"
+#~ "writing code for Android itself, the operating system. "
+#~ msgstr ""
+#~ "Es ist wichtig zu beachten, dass dieser Kurs keine Android **Anwendungsentwicklung** abdeckt \n"
+#~ "und dass es bei den Android-spezifischen Teilen um das \n"
+#~ "Schreiben von Code für das Betriebssystem Android geht. "
+
+#~ msgid ""
+#~ "* Learn how to use async Rust --- we'll only mention async Rust when\n"
+#~ " covering traditional concurrency primitives. Please see [Asynchronous\n"
+#~ " Programming in Rust](https://rust-lang.github.io/async-book/) instead for\n"
+#~ " details on this topic.\n"
+#~ "* Learn how to develop macros, please see [Chapter 19.5 in the Rust\n"
+#~ " Book](https://doc.rust-lang.org/book/ch19-06-macros.html) and [Rust by\n"
+#~ " Example](https://doc.rust-lang.org/rust-by-example/macros.html) instead."
+#~ msgstr ""
+#~ "* Lernen, wie man asynchrones Rust verwendet – wir erwähnen asynchrones Rust nur dann, wenn\n"
+#~ " wir traditionelle Nebenläufigkeitsprimitive abdecken. Siehe [Asynchronous\n"
+#~ " Programmierung in Rust](https://rust-lang.github.io/async-book/) für\n"
+#~ " Details zu diesem Thema.\n"
+#~ "* Lernen, wie man Makros entwickelt, siehe [Kapitel 19.5 im Rust\n"
+#~ " Buch](https://rust-lang-de.github.io/rustbook-de/ch19-06-macros.html) und [Rust by\n"
+#~ " Example](https://doc.rust-lang.org/rust-by-example/macros.html)."
+
+#~ msgid "# Day 4"
+#~ msgstr "# Tag 4"
+
+#~ msgid ""
+#~ "The afternoon of the fourth day should cover a topic of your choice. Include\n"
+#~ "the topic in the announcement of the course, so that participants know what to\n"
+#~ "expect."
+#~ msgstr ""
+#~ "Der Nachmittag des vierten Tages sollte ein von dir ausgewähltes Thema behandeln.\n"
+#~ "Erwähne das ausgewählte Thema in der Kursankündigung, sodass Teilnehmer wissen was auf sie "
+#~ "zukommt."
+
+#~ msgid ""
+#~ "This phase of the course is a chance for participants to see Rust in action on a\n"
+#~ "codebase they might be familiar with. You can choose from the topics already\n"
+#~ "defined here, or plan your own."
+#~ msgstr ""
+#~ "Dieser Abschnitt des Kurses ermöglicht es Teilnehmern Rust in einer Codebasis zu sehen die "
+#~ "siemöglicherweise schon kennen. Du kannst entweder von den hier vorgeschlagenen Themen wählen, "
+#~ "oder dein eigenes Thema planen."
+
+#~ msgid "Some topics need additional preparation:"
+#~ msgstr "Manche Themen benötigen eine besondere Vorbereitung:"
+
+#~ msgid "## Async"
+#~ msgstr "## Async"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Key points:"
+#~ msgstr "Kernpunkte:"
+
+#, fuzzy
+#~ msgid ""
+#~ "```rust,editable\n"
+#~ "fn main() {\n"
+#~ " fizzbuzz_to(20); // Defined below, no forward declaration needed\n"
+#~ "}\n"
+#~ "\n"
+#~ "fn is_divisible_by(lhs: u32, rhs: u32) -> bool {\n"
+#~ " if rhs == 0 {\n"
+#~ " return false; // Corner case, early return\n"
+#~ " }\n"
+#~ " lhs % rhs == 0 // The last expression in a block is the return value\n"
+#~ "}\n"
+#~ "\n"
+#~ "fn fizzbuzz(n: u32) -> () { // No return value means returning the unit type `()`\n"
+#~ " match (is_divisible_by(n, 3), is_divisible_by(n, 5)) {\n"
+#~ " (true, true) => println!(\"fizzbuzz\"),\n"
+#~ " (true, false) => println!(\"fizz\"),\n"
+#~ " (false, true) => println!(\"buzz\"),\n"
+#~ " (false, false) => println!(\"{n}\"),\n"
+#~ " }\n"
+#~ "}\n"
+#~ "\n"
+#~ "fn fizzbuzz_to(n: u32) { // `-> ()` is normally omitted\n"
+#~ " for i in 1..=n {\n"
+#~ " fizzbuzz(i);\n"
+#~ " }\n"
+#~ "}\n"
+#~ "```"
+#~ msgstr ""
+#~ "fn fizzbuzz(n: u32) -> () { // Kein Rückgabewert bedeutet Rückgabe des Einheitentyps `()`\n"
+#~ " Übereinstimmung (ist_teilbar_durch(n, 3), ist_teilbar_durch(n, 5)) {\n"
+#~ " (true, true) => println!(\"fizzbuzz\"),\n"
+#~ " (wahr, falsch) => println!(\"fizz\"),\n"
+#~ " (falsch, wahr) => println!(\"summen\"),\n"
+#~ " (falsch, falsch) => println!(\"{n}\"),\n"
+#~ " }\n"
+#~ "}"
+
+#, fuzzy
+#~ msgid ""
+#~ msgstr ""
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Key Points: "
+#~ msgstr "Wichtige Punkte:"
+
+#, fuzzy
+#~ msgid "You use `if` very similarly to how you would in other languages:"
+#~ msgstr "Sie verwenden \"if\" sehr ähnlich wie in anderen Sprachen:"
+
+#, fuzzy
+#~ msgid "If you want to match a value against a pattern, you can use `if let`:"
+#~ msgstr "Wenn Sie einen Wert mit einem Muster abgleichen möchten, können Sie `if let` verwenden:"
+
+#, fuzzy
+#~ msgid "The `while` keyword works very similar to other languages:"
+#~ msgstr "Das Schlüsselwort „while“ funktioniert sehr ähnlich wie in anderen Sprachen:"
+
+#, fuzzy
+#~ msgid "# `for` expressions"
+#~ msgstr "# `for`-Ausdrücke"
+
+#, fuzzy
+#~ msgid ""
+#~ "You will also want to browse the [`std::ffi`] module, particular for [`CStr`]\n"
+#~ "and [`CString`] types which are used to hold NUL-terminated strings coming from\n"
+#~ "C. The [Nomicon] also has a very useful chapter about FFI."
+#~ msgstr ""
+#~ "Sie sollten auch das Modul [`std::ffi`] durchsuchen, insbesondere nach [`CStr`]\n"
+#~ "und [`CString`]-Typen, die verwendet werden, um NUL-terminierte Zeichenfolgen zu halten, die "
+#~ "von kommen\n"
+#~ "C. Das [Nomicon] hat auch ein sehr nützliches Kapitel über FFI."
+
+#, fuzzy
+#~ msgid "# Welcome to Day 4"
+#~ msgstr "# Willkommen zu Tag 4"
+
+#, fuzzy
+#~ msgid "# Fearless Concurrency"
+#~ msgstr "# Furchtlose Parallelität"
+
+#, fuzzy
+#~ msgid "# Runtimes and Tasks"
+#~ msgstr "# Laufzeitgarantien"
+
+#, fuzzy
+#~ msgid "## Getting Started"
+#~ msgstr "# Destrukturierende Strukturen"
+
+#, fuzzy
+#~ msgid "`src/controller.rs`:"
+#~ msgstr "_hello_rust/src/main.rs_:"
+
+#, fuzzy
+#~ msgid "Use `cargo run` to run the elevator simulation."
+#~ msgstr "Verwenden Sie \"Cargo Test\", um die Komponententests zu finden und auszuführen."
+
+#, fuzzy
+#~ msgid "## Exercises"
+#~ msgstr "# Übungen"
+
+#, fuzzy
+#~ msgid "# Day 4 Morning Exercise"
+#~ msgstr "# Tag 4 Morgengymnastik"
+
#, fuzzy
#~ msgid ""
#~ "* `if let` can be more concise than `match`, e.g., when only one case is interesting. In "